1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
4 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
5 */
6
7 #include "devl_internal.h"
8
9 struct devlink_region {
10 struct devlink *devlink;
11 struct devlink_port *port;
12 struct list_head list;
13 union {
14 const struct devlink_region_ops *ops;
15 const struct devlink_port_region_ops *port_ops;
16 };
17 struct mutex snapshot_lock; /* protects snapshot_list,
18 * max_snapshots and cur_snapshots
19 * consistency.
20 */
21 struct list_head snapshot_list;
22 u32 max_snapshots;
23 u32 cur_snapshots;
24 u64 size;
25 };
26
27 struct devlink_snapshot {
28 struct list_head list;
29 struct devlink_region *region;
30 u8 *data;
31 u32 id;
32 };
33
34 static struct devlink_region *
devlink_region_get_by_name(struct devlink * devlink,const char * region_name)35 devlink_region_get_by_name(struct devlink *devlink, const char *region_name)
36 {
37 struct devlink_region *region;
38
39 list_for_each_entry(region, &devlink->region_list, list)
40 if (!strcmp(region->ops->name, region_name))
41 return region;
42
43 return NULL;
44 }
45
46 static struct devlink_region *
devlink_port_region_get_by_name(struct devlink_port * port,const char * region_name)47 devlink_port_region_get_by_name(struct devlink_port *port,
48 const char *region_name)
49 {
50 struct devlink_region *region;
51
52 list_for_each_entry(region, &port->region_list, list)
53 if (!strcmp(region->ops->name, region_name))
54 return region;
55
56 return NULL;
57 }
58
59 static struct devlink_snapshot *
devlink_region_snapshot_get_by_id(struct devlink_region * region,u32 id)60 devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id)
61 {
62 struct devlink_snapshot *snapshot;
63
64 list_for_each_entry(snapshot, ®ion->snapshot_list, list)
65 if (snapshot->id == id)
66 return snapshot;
67
68 return NULL;
69 }
70
devlink_nl_region_snapshot_id_put(struct sk_buff * msg,struct devlink * devlink,struct devlink_snapshot * snapshot)71 static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg,
72 struct devlink *devlink,
73 struct devlink_snapshot *snapshot)
74 {
75 struct nlattr *snap_attr;
76 int err;
77
78 snap_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_SNAPSHOT);
79 if (!snap_attr)
80 return -EINVAL;
81
82 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id);
83 if (err)
84 goto nla_put_failure;
85
86 nla_nest_end(msg, snap_attr);
87 return 0;
88
89 nla_put_failure:
90 nla_nest_cancel(msg, snap_attr);
91 return err;
92 }
93
devlink_nl_region_snapshots_id_put(struct sk_buff * msg,struct devlink * devlink,struct devlink_region * region)94 static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg,
95 struct devlink *devlink,
96 struct devlink_region *region)
97 {
98 struct devlink_snapshot *snapshot;
99 struct nlattr *snapshots_attr;
100 int err;
101
102 snapshots_attr = nla_nest_start_noflag(msg,
103 DEVLINK_ATTR_REGION_SNAPSHOTS);
104 if (!snapshots_attr)
105 return -EINVAL;
106
107 list_for_each_entry(snapshot, ®ion->snapshot_list, list) {
108 err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot);
109 if (err)
110 goto nla_put_failure;
111 }
112
113 nla_nest_end(msg, snapshots_attr);
114 return 0;
115
116 nla_put_failure:
117 nla_nest_cancel(msg, snapshots_attr);
118 return err;
119 }
120
devlink_nl_region_fill(struct sk_buff * msg,struct devlink * devlink,enum devlink_command cmd,u32 portid,u32 seq,int flags,struct devlink_region * region)121 static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink,
122 enum devlink_command cmd, u32 portid,
123 u32 seq, int flags,
124 struct devlink_region *region)
125 {
126 void *hdr;
127 int err;
128
129 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
130 if (!hdr)
131 return -EMSGSIZE;
132
133 err = devlink_nl_put_handle(msg, devlink);
134 if (err)
135 goto nla_put_failure;
136
137 if (region->port) {
138 err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
139 region->port->index);
140 if (err)
141 goto nla_put_failure;
142 }
143
144 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->ops->name);
145 if (err)
146 goto nla_put_failure;
147
148 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
149 region->size,
150 DEVLINK_ATTR_PAD);
151 if (err)
152 goto nla_put_failure;
153
154 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_MAX_SNAPSHOTS,
155 region->max_snapshots);
156 if (err)
157 goto nla_put_failure;
158
159 err = devlink_nl_region_snapshots_id_put(msg, devlink, region);
160 if (err)
161 goto nla_put_failure;
162
163 genlmsg_end(msg, hdr);
164 return 0;
165
166 nla_put_failure:
167 genlmsg_cancel(msg, hdr);
168 return err;
169 }
170
171 static struct sk_buff *
devlink_nl_region_notify_build(struct devlink_region * region,struct devlink_snapshot * snapshot,enum devlink_command cmd,u32 portid,u32 seq)172 devlink_nl_region_notify_build(struct devlink_region *region,
173 struct devlink_snapshot *snapshot,
174 enum devlink_command cmd, u32 portid, u32 seq)
175 {
176 struct devlink *devlink = region->devlink;
177 struct sk_buff *msg;
178 void *hdr;
179 int err;
180
181 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
182 if (!msg)
183 return ERR_PTR(-ENOMEM);
184
185 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, 0, cmd);
186 if (!hdr) {
187 err = -EMSGSIZE;
188 goto out_free_msg;
189 }
190
191 err = devlink_nl_put_handle(msg, devlink);
192 if (err)
193 goto out_cancel_msg;
194
195 if (region->port) {
196 err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
197 region->port->index);
198 if (err)
199 goto out_cancel_msg;
200 }
201
202 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME,
203 region->ops->name);
204 if (err)
205 goto out_cancel_msg;
206
207 if (snapshot) {
208 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID,
209 snapshot->id);
210 if (err)
211 goto out_cancel_msg;
212 } else {
213 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
214 region->size, DEVLINK_ATTR_PAD);
215 if (err)
216 goto out_cancel_msg;
217 }
218 genlmsg_end(msg, hdr);
219
220 return msg;
221
222 out_cancel_msg:
223 genlmsg_cancel(msg, hdr);
224 out_free_msg:
225 nlmsg_free(msg);
226 return ERR_PTR(err);
227 }
228
devlink_nl_region_notify(struct devlink_region * region,struct devlink_snapshot * snapshot,enum devlink_command cmd)229 static void devlink_nl_region_notify(struct devlink_region *region,
230 struct devlink_snapshot *snapshot,
231 enum devlink_command cmd)
232 {
233 struct devlink *devlink = region->devlink;
234 struct sk_buff *msg;
235
236 WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL);
237
238 if (!__devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
239 return;
240
241 msg = devlink_nl_region_notify_build(region, snapshot, cmd, 0, 0);
242 if (IS_ERR(msg))
243 return;
244
245 devlink_nl_notify_send(devlink, msg);
246 }
247
devlink_regions_notify_register(struct devlink * devlink)248 void devlink_regions_notify_register(struct devlink *devlink)
249 {
250 struct devlink_region *region;
251
252 list_for_each_entry(region, &devlink->region_list, list)
253 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
254 }
255
devlink_regions_notify_unregister(struct devlink * devlink)256 void devlink_regions_notify_unregister(struct devlink *devlink)
257 {
258 struct devlink_region *region;
259
260 list_for_each_entry_reverse(region, &devlink->region_list, list)
261 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
262 }
263
264 /**
265 * __devlink_snapshot_id_increment - Increment number of snapshots using an id
266 * @devlink: devlink instance
267 * @id: the snapshot id
268 *
269 * Track when a new snapshot begins using an id. Load the count for the
270 * given id from the snapshot xarray, increment it, and store it back.
271 *
272 * Called when a new snapshot is created with the given id.
273 *
274 * The id *must* have been previously allocated by
275 * devlink_region_snapshot_id_get().
276 *
277 * Returns 0 on success, or an error on failure.
278 */
__devlink_snapshot_id_increment(struct devlink * devlink,u32 id)279 static int __devlink_snapshot_id_increment(struct devlink *devlink, u32 id)
280 {
281 unsigned long count;
282 void *p;
283 int err;
284
285 xa_lock(&devlink->snapshot_ids);
286 p = xa_load(&devlink->snapshot_ids, id);
287 if (WARN_ON(!p)) {
288 err = -EINVAL;
289 goto unlock;
290 }
291
292 if (WARN_ON(!xa_is_value(p))) {
293 err = -EINVAL;
294 goto unlock;
295 }
296
297 count = xa_to_value(p);
298 count++;
299
300 err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
301 GFP_ATOMIC));
302 unlock:
303 xa_unlock(&devlink->snapshot_ids);
304 return err;
305 }
306
307 /**
308 * __devlink_snapshot_id_decrement - Decrease number of snapshots using an id
309 * @devlink: devlink instance
310 * @id: the snapshot id
311 *
312 * Track when a snapshot is deleted and stops using an id. Load the count
313 * for the given id from the snapshot xarray, decrement it, and store it
314 * back.
315 *
316 * If the count reaches zero, erase this id from the xarray, freeing it
317 * up for future re-use by devlink_region_snapshot_id_get().
318 *
319 * Called when a snapshot using the given id is deleted, and when the
320 * initial allocator of the id is finished using it.
321 */
__devlink_snapshot_id_decrement(struct devlink * devlink,u32 id)322 static void __devlink_snapshot_id_decrement(struct devlink *devlink, u32 id)
323 {
324 unsigned long count;
325 void *p;
326
327 xa_lock(&devlink->snapshot_ids);
328 p = xa_load(&devlink->snapshot_ids, id);
329 if (WARN_ON(!p))
330 goto unlock;
331
332 if (WARN_ON(!xa_is_value(p)))
333 goto unlock;
334
335 count = xa_to_value(p);
336
337 if (count > 1) {
338 count--;
339 __xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
340 GFP_ATOMIC);
341 } else {
342 /* If this was the last user, we can erase this id */
343 __xa_erase(&devlink->snapshot_ids, id);
344 }
345 unlock:
346 xa_unlock(&devlink->snapshot_ids);
347 }
348
349 /**
350 * __devlink_snapshot_id_insert - Insert a specific snapshot ID
351 * @devlink: devlink instance
352 * @id: the snapshot id
353 *
354 * Mark the given snapshot id as used by inserting a zero value into the
355 * snapshot xarray.
356 *
357 * This must be called while holding the devlink instance lock. Unlike
358 * devlink_snapshot_id_get, the initial reference count is zero, not one.
359 * It is expected that the id will immediately be used before
360 * releasing the devlink instance lock.
361 *
362 * Returns zero on success, or an error code if the snapshot id could not
363 * be inserted.
364 */
__devlink_snapshot_id_insert(struct devlink * devlink,u32 id)365 static int __devlink_snapshot_id_insert(struct devlink *devlink, u32 id)
366 {
367 int err;
368
369 xa_lock(&devlink->snapshot_ids);
370 if (xa_load(&devlink->snapshot_ids, id)) {
371 xa_unlock(&devlink->snapshot_ids);
372 return -EEXIST;
373 }
374 err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(0),
375 GFP_ATOMIC));
376 xa_unlock(&devlink->snapshot_ids);
377 return err;
378 }
379
380 /**
381 * __devlink_region_snapshot_id_get - get snapshot ID
382 * @devlink: devlink instance
383 * @id: storage to return snapshot id
384 *
385 * Allocates a new snapshot id. Returns zero on success, or a negative
386 * error on failure. Must be called while holding the devlink instance
387 * lock.
388 *
389 * Snapshot IDs are tracked using an xarray which stores the number of
390 * users of the snapshot id.
391 *
392 * Note that the caller of this function counts as a 'user', in order to
393 * avoid race conditions. The caller must release its hold on the
394 * snapshot by using devlink_region_snapshot_id_put.
395 */
__devlink_region_snapshot_id_get(struct devlink * devlink,u32 * id)396 static int __devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
397 {
398 return xa_alloc(&devlink->snapshot_ids, id, xa_mk_value(1),
399 xa_limit_32b, GFP_KERNEL);
400 }
401
402 /**
403 * __devlink_region_snapshot_create - create a new snapshot
404 * This will add a new snapshot of a region. The snapshot
405 * will be stored on the region struct and can be accessed
406 * from devlink. This is useful for future analyses of snapshots.
407 * Multiple snapshots can be created on a region.
408 * The @snapshot_id should be obtained using the getter function.
409 *
410 * Must be called only while holding the region snapshot lock.
411 *
412 * @region: devlink region of the snapshot
413 * @data: snapshot data
414 * @snapshot_id: snapshot id to be created
415 */
416 static int
__devlink_region_snapshot_create(struct devlink_region * region,u8 * data,u32 snapshot_id)417 __devlink_region_snapshot_create(struct devlink_region *region,
418 u8 *data, u32 snapshot_id)
419 {
420 struct devlink *devlink = region->devlink;
421 struct devlink_snapshot *snapshot;
422 int err;
423
424 lockdep_assert_held(®ion->snapshot_lock);
425
426 /* check if region can hold one more snapshot */
427 if (region->cur_snapshots == region->max_snapshots)
428 return -ENOSPC;
429
430 if (devlink_region_snapshot_get_by_id(region, snapshot_id))
431 return -EEXIST;
432
433 snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL);
434 if (!snapshot)
435 return -ENOMEM;
436
437 err = __devlink_snapshot_id_increment(devlink, snapshot_id);
438 if (err)
439 goto err_snapshot_id_increment;
440
441 snapshot->id = snapshot_id;
442 snapshot->region = region;
443 snapshot->data = data;
444
445 list_add_tail(&snapshot->list, ®ion->snapshot_list);
446
447 region->cur_snapshots++;
448
449 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW);
450 return 0;
451
452 err_snapshot_id_increment:
453 kfree(snapshot);
454 return err;
455 }
456
devlink_region_snapshot_del(struct devlink_region * region,struct devlink_snapshot * snapshot)457 static void devlink_region_snapshot_del(struct devlink_region *region,
458 struct devlink_snapshot *snapshot)
459 {
460 struct devlink *devlink = region->devlink;
461
462 lockdep_assert_held(®ion->snapshot_lock);
463
464 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL);
465 region->cur_snapshots--;
466 list_del(&snapshot->list);
467 region->ops->destructor(snapshot->data);
468 __devlink_snapshot_id_decrement(devlink, snapshot->id);
469 kfree(snapshot);
470 }
471
devlink_nl_region_get_doit(struct sk_buff * skb,struct genl_info * info)472 int devlink_nl_region_get_doit(struct sk_buff *skb, struct genl_info *info)
473 {
474 struct devlink *devlink = info->user_ptr[0];
475 struct devlink_port *port = NULL;
476 struct devlink_region *region;
477 const char *region_name;
478 struct sk_buff *msg;
479 unsigned int index;
480 int err;
481
482 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME))
483 return -EINVAL;
484
485 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
486 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
487
488 port = devlink_port_get_by_index(devlink, index);
489 if (!port)
490 return -ENODEV;
491 }
492
493 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
494 if (port)
495 region = devlink_port_region_get_by_name(port, region_name);
496 else
497 region = devlink_region_get_by_name(devlink, region_name);
498
499 if (!region)
500 return -EINVAL;
501
502 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
503 if (!msg)
504 return -ENOMEM;
505
506 err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET,
507 info->snd_portid, info->snd_seq, 0,
508 region);
509 if (err) {
510 nlmsg_free(msg);
511 return err;
512 }
513
514 return genlmsg_reply(msg, info);
515 }
516
devlink_nl_cmd_region_get_port_dumpit(struct sk_buff * msg,struct netlink_callback * cb,struct devlink_port * port,int * idx,int start,int flags)517 static int devlink_nl_cmd_region_get_port_dumpit(struct sk_buff *msg,
518 struct netlink_callback *cb,
519 struct devlink_port *port,
520 int *idx, int start, int flags)
521 {
522 struct devlink_region *region;
523 int err = 0;
524
525 list_for_each_entry(region, &port->region_list, list) {
526 if (*idx < start) {
527 (*idx)++;
528 continue;
529 }
530 err = devlink_nl_region_fill(msg, port->devlink,
531 DEVLINK_CMD_REGION_GET,
532 NETLINK_CB(cb->skb).portid,
533 cb->nlh->nlmsg_seq,
534 flags, region);
535 if (err)
536 goto out;
537 (*idx)++;
538 }
539
540 out:
541 return err;
542 }
543
devlink_nl_region_get_dump_one(struct sk_buff * msg,struct devlink * devlink,struct netlink_callback * cb,int flags)544 static int devlink_nl_region_get_dump_one(struct sk_buff *msg,
545 struct devlink *devlink,
546 struct netlink_callback *cb,
547 int flags)
548 {
549 struct devlink_nl_dump_state *state = devlink_dump_state(cb);
550 struct devlink_region *region;
551 struct devlink_port *port;
552 unsigned long port_index;
553 int idx = 0;
554 int err;
555
556 list_for_each_entry(region, &devlink->region_list, list) {
557 if (idx < state->idx) {
558 idx++;
559 continue;
560 }
561 err = devlink_nl_region_fill(msg, devlink,
562 DEVLINK_CMD_REGION_GET,
563 NETLINK_CB(cb->skb).portid,
564 cb->nlh->nlmsg_seq, flags,
565 region);
566 if (err) {
567 state->idx = idx;
568 return err;
569 }
570 idx++;
571 }
572
573 xa_for_each(&devlink->ports, port_index, port) {
574 err = devlink_nl_cmd_region_get_port_dumpit(msg, cb, port, &idx,
575 state->idx, flags);
576 if (err) {
577 state->idx = idx;
578 return err;
579 }
580 }
581
582 return 0;
583 }
584
devlink_nl_region_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)585 int devlink_nl_region_get_dumpit(struct sk_buff *skb,
586 struct netlink_callback *cb)
587 {
588 return devlink_nl_dumpit(skb, cb, devlink_nl_region_get_dump_one);
589 }
590
devlink_nl_region_del_doit(struct sk_buff * skb,struct genl_info * info)591 int devlink_nl_region_del_doit(struct sk_buff *skb, struct genl_info *info)
592 {
593 struct devlink *devlink = info->user_ptr[0];
594 struct devlink_snapshot *snapshot;
595 struct devlink_port *port = NULL;
596 struct devlink_region *region;
597 const char *region_name;
598 unsigned int index;
599 u32 snapshot_id;
600
601 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME) ||
602 GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_SNAPSHOT_ID))
603 return -EINVAL;
604
605 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
606 snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
607
608 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
609 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
610
611 port = devlink_port_get_by_index(devlink, index);
612 if (!port)
613 return -ENODEV;
614 }
615
616 if (port)
617 region = devlink_port_region_get_by_name(port, region_name);
618 else
619 region = devlink_region_get_by_name(devlink, region_name);
620
621 if (!region)
622 return -EINVAL;
623
624 mutex_lock(®ion->snapshot_lock);
625 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
626 if (!snapshot) {
627 mutex_unlock(®ion->snapshot_lock);
628 return -EINVAL;
629 }
630
631 devlink_region_snapshot_del(region, snapshot);
632 mutex_unlock(®ion->snapshot_lock);
633 return 0;
634 }
635
devlink_nl_region_new_doit(struct sk_buff * skb,struct genl_info * info)636 int devlink_nl_region_new_doit(struct sk_buff *skb, struct genl_info *info)
637 {
638 struct devlink *devlink = info->user_ptr[0];
639 struct devlink_snapshot *snapshot;
640 struct devlink_port *port = NULL;
641 struct nlattr *snapshot_id_attr;
642 struct devlink_region *region;
643 const char *region_name;
644 unsigned int index;
645 u32 snapshot_id;
646 u8 *data;
647 int err;
648
649 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME)) {
650 NL_SET_ERR_MSG(info->extack, "No region name provided");
651 return -EINVAL;
652 }
653
654 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
655
656 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
657 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
658
659 port = devlink_port_get_by_index(devlink, index);
660 if (!port)
661 return -ENODEV;
662 }
663
664 if (port)
665 region = devlink_port_region_get_by_name(port, region_name);
666 else
667 region = devlink_region_get_by_name(devlink, region_name);
668
669 if (!region) {
670 NL_SET_ERR_MSG(info->extack, "The requested region does not exist");
671 return -EINVAL;
672 }
673
674 if (!region->ops->snapshot) {
675 NL_SET_ERR_MSG(info->extack, "The requested region does not support taking an immediate snapshot");
676 return -EOPNOTSUPP;
677 }
678
679 mutex_lock(®ion->snapshot_lock);
680
681 if (region->cur_snapshots == region->max_snapshots) {
682 NL_SET_ERR_MSG(info->extack, "The region has reached the maximum number of stored snapshots");
683 err = -ENOSPC;
684 goto unlock;
685 }
686
687 snapshot_id_attr = info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID];
688 if (snapshot_id_attr) {
689 snapshot_id = nla_get_u32(snapshot_id_attr);
690
691 if (devlink_region_snapshot_get_by_id(region, snapshot_id)) {
692 NL_SET_ERR_MSG(info->extack, "The requested snapshot id is already in use");
693 err = -EEXIST;
694 goto unlock;
695 }
696
697 err = __devlink_snapshot_id_insert(devlink, snapshot_id);
698 if (err)
699 goto unlock;
700 } else {
701 err = __devlink_region_snapshot_id_get(devlink, &snapshot_id);
702 if (err) {
703 NL_SET_ERR_MSG(info->extack, "Failed to allocate a new snapshot id");
704 goto unlock;
705 }
706 }
707
708 if (port)
709 err = region->port_ops->snapshot(port, region->port_ops,
710 info->extack, &data);
711 else
712 err = region->ops->snapshot(devlink, region->ops,
713 info->extack, &data);
714 if (err)
715 goto err_snapshot_capture;
716
717 err = __devlink_region_snapshot_create(region, data, snapshot_id);
718 if (err)
719 goto err_snapshot_create;
720
721 if (!snapshot_id_attr) {
722 struct sk_buff *msg;
723
724 snapshot = devlink_region_snapshot_get_by_id(region,
725 snapshot_id);
726 if (WARN_ON(!snapshot)) {
727 err = -EINVAL;
728 goto unlock;
729 }
730
731 msg = devlink_nl_region_notify_build(region, snapshot,
732 DEVLINK_CMD_REGION_NEW,
733 info->snd_portid,
734 info->snd_seq);
735 err = PTR_ERR_OR_ZERO(msg);
736 if (err)
737 goto err_notify;
738
739 err = genlmsg_reply(msg, info);
740 if (err)
741 goto err_notify;
742 }
743
744 mutex_unlock(®ion->snapshot_lock);
745 return 0;
746
747 err_snapshot_create:
748 region->ops->destructor(data);
749 err_snapshot_capture:
750 __devlink_snapshot_id_decrement(devlink, snapshot_id);
751 mutex_unlock(®ion->snapshot_lock);
752 return err;
753
754 err_notify:
755 devlink_region_snapshot_del(region, snapshot);
756 unlock:
757 mutex_unlock(®ion->snapshot_lock);
758 return err;
759 }
760
devlink_nl_cmd_region_read_chunk_fill(struct sk_buff * msg,u8 * chunk,u32 chunk_size,u64 addr)761 static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg,
762 u8 *chunk, u32 chunk_size,
763 u64 addr)
764 {
765 struct nlattr *chunk_attr;
766 int err;
767
768 chunk_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_CHUNK);
769 if (!chunk_attr)
770 return -EINVAL;
771
772 err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk);
773 if (err)
774 goto nla_put_failure;
775
776 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr,
777 DEVLINK_ATTR_PAD);
778 if (err)
779 goto nla_put_failure;
780
781 nla_nest_end(msg, chunk_attr);
782 return 0;
783
784 nla_put_failure:
785 nla_nest_cancel(msg, chunk_attr);
786 return err;
787 }
788
789 #define DEVLINK_REGION_READ_CHUNK_SIZE 256
790
791 typedef int devlink_chunk_fill_t(void *cb_priv, u8 *chunk, u32 chunk_size,
792 u64 curr_offset,
793 struct netlink_ext_ack *extack);
794
795 static int
devlink_nl_region_read_fill(struct sk_buff * skb,devlink_chunk_fill_t * cb,void * cb_priv,u64 start_offset,u64 end_offset,u64 * new_offset,struct netlink_ext_ack * extack)796 devlink_nl_region_read_fill(struct sk_buff *skb, devlink_chunk_fill_t *cb,
797 void *cb_priv, u64 start_offset, u64 end_offset,
798 u64 *new_offset, struct netlink_ext_ack *extack)
799 {
800 u64 curr_offset = start_offset;
801 int err = 0;
802 u8 *data;
803
804 /* Allocate and re-use a single buffer */
805 data = kmalloc(DEVLINK_REGION_READ_CHUNK_SIZE, GFP_KERNEL);
806 if (!data)
807 return -ENOMEM;
808
809 *new_offset = start_offset;
810
811 while (curr_offset < end_offset) {
812 u32 data_size;
813
814 data_size = min_t(u32, end_offset - curr_offset,
815 DEVLINK_REGION_READ_CHUNK_SIZE);
816
817 err = cb(cb_priv, data, data_size, curr_offset, extack);
818 if (err)
819 break;
820
821 err = devlink_nl_cmd_region_read_chunk_fill(skb, data, data_size, curr_offset);
822 if (err)
823 break;
824
825 curr_offset += data_size;
826 }
827 *new_offset = curr_offset;
828
829 kfree(data);
830
831 return err;
832 }
833
834 static int
devlink_region_snapshot_fill(void * cb_priv,u8 * chunk,u32 chunk_size,u64 curr_offset,struct netlink_ext_ack __always_unused * extack)835 devlink_region_snapshot_fill(void *cb_priv, u8 *chunk, u32 chunk_size,
836 u64 curr_offset,
837 struct netlink_ext_ack __always_unused *extack)
838 {
839 struct devlink_snapshot *snapshot = cb_priv;
840
841 memcpy(chunk, &snapshot->data[curr_offset], chunk_size);
842
843 return 0;
844 }
845
846 static int
devlink_region_port_direct_fill(void * cb_priv,u8 * chunk,u32 chunk_size,u64 curr_offset,struct netlink_ext_ack * extack)847 devlink_region_port_direct_fill(void *cb_priv, u8 *chunk, u32 chunk_size,
848 u64 curr_offset, struct netlink_ext_ack *extack)
849 {
850 struct devlink_region *region = cb_priv;
851
852 return region->port_ops->read(region->port, region->port_ops, extack,
853 curr_offset, chunk_size, chunk);
854 }
855
856 static int
devlink_region_direct_fill(void * cb_priv,u8 * chunk,u32 chunk_size,u64 curr_offset,struct netlink_ext_ack * extack)857 devlink_region_direct_fill(void *cb_priv, u8 *chunk, u32 chunk_size,
858 u64 curr_offset, struct netlink_ext_ack *extack)
859 {
860 struct devlink_region *region = cb_priv;
861
862 return region->ops->read(region->devlink, region->ops, extack,
863 curr_offset, chunk_size, chunk);
864 }
865
devlink_nl_region_read_dumpit(struct sk_buff * skb,struct netlink_callback * cb)866 int devlink_nl_region_read_dumpit(struct sk_buff *skb,
867 struct netlink_callback *cb)
868 {
869 const struct genl_dumpit_info *info = genl_dumpit_info(cb);
870 struct devlink_nl_dump_state *state = devlink_dump_state(cb);
871 struct nlattr *chunks_attr, *region_attr, *snapshot_attr;
872 u64 ret_offset, start_offset, end_offset = U64_MAX;
873 struct nlattr **attrs = info->info.attrs;
874 struct devlink_port *port = NULL;
875 devlink_chunk_fill_t *region_cb;
876 struct devlink_region *region;
877 const char *region_name;
878 struct devlink *devlink;
879 unsigned int index;
880 void *region_cb_priv;
881 void *hdr;
882 int err;
883
884 start_offset = state->start_offset;
885
886 devlink = devlink_get_from_attrs_lock(sock_net(cb->skb->sk), attrs,
887 false);
888 if (IS_ERR(devlink))
889 return PTR_ERR(devlink);
890
891 if (!attrs[DEVLINK_ATTR_REGION_NAME]) {
892 NL_SET_ERR_MSG(cb->extack, "No region name provided");
893 err = -EINVAL;
894 goto out_unlock;
895 }
896
897 if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
898 index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
899
900 port = devlink_port_get_by_index(devlink, index);
901 if (!port) {
902 err = -ENODEV;
903 goto out_unlock;
904 }
905 }
906
907 region_attr = attrs[DEVLINK_ATTR_REGION_NAME];
908 region_name = nla_data(region_attr);
909
910 if (port)
911 region = devlink_port_region_get_by_name(port, region_name);
912 else
913 region = devlink_region_get_by_name(devlink, region_name);
914
915 if (!region) {
916 NL_SET_ERR_MSG_ATTR(cb->extack, region_attr, "Requested region does not exist");
917 err = -EINVAL;
918 goto out_unlock;
919 }
920
921 snapshot_attr = attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID];
922 if (!snapshot_attr) {
923 if (!nla_get_flag(attrs[DEVLINK_ATTR_REGION_DIRECT])) {
924 NL_SET_ERR_MSG(cb->extack, "No snapshot id provided");
925 err = -EINVAL;
926 goto out_unlock;
927 }
928
929 if (!region->ops->read) {
930 NL_SET_ERR_MSG(cb->extack, "Requested region does not support direct read");
931 err = -EOPNOTSUPP;
932 goto out_unlock;
933 }
934
935 if (port)
936 region_cb = &devlink_region_port_direct_fill;
937 else
938 region_cb = &devlink_region_direct_fill;
939 region_cb_priv = region;
940 } else {
941 struct devlink_snapshot *snapshot;
942 u32 snapshot_id;
943
944 if (nla_get_flag(attrs[DEVLINK_ATTR_REGION_DIRECT])) {
945 NL_SET_ERR_MSG_ATTR(cb->extack, snapshot_attr, "Direct region read does not use snapshot");
946 err = -EINVAL;
947 goto out_unlock;
948 }
949
950 snapshot_id = nla_get_u32(snapshot_attr);
951 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
952 if (!snapshot) {
953 NL_SET_ERR_MSG_ATTR(cb->extack, snapshot_attr, "Requested snapshot does not exist");
954 err = -EINVAL;
955 goto out_unlock;
956 }
957 region_cb = &devlink_region_snapshot_fill;
958 region_cb_priv = snapshot;
959 }
960
961 if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] &&
962 attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) {
963 if (!start_offset)
964 start_offset =
965 nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
966
967 end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
968 end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]);
969 }
970
971 if (end_offset > region->size)
972 end_offset = region->size;
973
974 /* return 0 if there is no further data to read */
975 if (start_offset == end_offset) {
976 err = 0;
977 goto out_unlock;
978 }
979
980 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
981 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
982 DEVLINK_CMD_REGION_READ);
983 if (!hdr) {
984 err = -EMSGSIZE;
985 goto out_unlock;
986 }
987
988 err = devlink_nl_put_handle(skb, devlink);
989 if (err)
990 goto nla_put_failure;
991
992 if (region->port) {
993 err = nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX,
994 region->port->index);
995 if (err)
996 goto nla_put_failure;
997 }
998
999 err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
1000 if (err)
1001 goto nla_put_failure;
1002
1003 chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS);
1004 if (!chunks_attr) {
1005 err = -EMSGSIZE;
1006 goto nla_put_failure;
1007 }
1008
1009 err = devlink_nl_region_read_fill(skb, region_cb, region_cb_priv,
1010 start_offset, end_offset, &ret_offset,
1011 cb->extack);
1012
1013 if (err && err != -EMSGSIZE)
1014 goto nla_put_failure;
1015
1016 /* Check if there was any progress done to prevent infinite loop */
1017 if (ret_offset == start_offset) {
1018 err = -EINVAL;
1019 goto nla_put_failure;
1020 }
1021
1022 state->start_offset = ret_offset;
1023
1024 nla_nest_end(skb, chunks_attr);
1025 genlmsg_end(skb, hdr);
1026 devl_unlock(devlink);
1027 devlink_put(devlink);
1028 return skb->len;
1029
1030 nla_put_failure:
1031 genlmsg_cancel(skb, hdr);
1032 out_unlock:
1033 devl_unlock(devlink);
1034 devlink_put(devlink);
1035 return err;
1036 }
1037
1038 /**
1039 * devl_region_create - create a new address region
1040 *
1041 * @devlink: devlink
1042 * @ops: region operations and name
1043 * @region_max_snapshots: Maximum supported number of snapshots for region
1044 * @region_size: size of region
1045 */
devl_region_create(struct devlink * devlink,const struct devlink_region_ops * ops,u32 region_max_snapshots,u64 region_size)1046 struct devlink_region *devl_region_create(struct devlink *devlink,
1047 const struct devlink_region_ops *ops,
1048 u32 region_max_snapshots,
1049 u64 region_size)
1050 {
1051 struct devlink_region *region;
1052
1053 devl_assert_locked(devlink);
1054
1055 if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
1056 return ERR_PTR(-EINVAL);
1057
1058 if (devlink_region_get_by_name(devlink, ops->name))
1059 return ERR_PTR(-EEXIST);
1060
1061 region = kzalloc(sizeof(*region), GFP_KERNEL);
1062 if (!region)
1063 return ERR_PTR(-ENOMEM);
1064
1065 region->devlink = devlink;
1066 region->max_snapshots = region_max_snapshots;
1067 region->ops = ops;
1068 region->size = region_size;
1069 INIT_LIST_HEAD(®ion->snapshot_list);
1070 mutex_init(®ion->snapshot_lock);
1071 list_add_tail(®ion->list, &devlink->region_list);
1072 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
1073
1074 return region;
1075 }
1076 EXPORT_SYMBOL_GPL(devl_region_create);
1077
1078 /**
1079 * devlink_region_create - create a new address region
1080 *
1081 * @devlink: devlink
1082 * @ops: region operations and name
1083 * @region_max_snapshots: Maximum supported number of snapshots for region
1084 * @region_size: size of region
1085 *
1086 * Context: Takes and release devlink->lock <mutex>.
1087 */
1088 struct devlink_region *
devlink_region_create(struct devlink * devlink,const struct devlink_region_ops * ops,u32 region_max_snapshots,u64 region_size)1089 devlink_region_create(struct devlink *devlink,
1090 const struct devlink_region_ops *ops,
1091 u32 region_max_snapshots, u64 region_size)
1092 {
1093 struct devlink_region *region;
1094
1095 devl_lock(devlink);
1096 region = devl_region_create(devlink, ops, region_max_snapshots,
1097 region_size);
1098 devl_unlock(devlink);
1099 return region;
1100 }
1101 EXPORT_SYMBOL_GPL(devlink_region_create);
1102
1103 /**
1104 * devlink_port_region_create - create a new address region for a port
1105 *
1106 * @port: devlink port
1107 * @ops: region operations and name
1108 * @region_max_snapshots: Maximum supported number of snapshots for region
1109 * @region_size: size of region
1110 *
1111 * Context: Takes and release devlink->lock <mutex>.
1112 */
1113 struct devlink_region *
devlink_port_region_create(struct devlink_port * port,const struct devlink_port_region_ops * ops,u32 region_max_snapshots,u64 region_size)1114 devlink_port_region_create(struct devlink_port *port,
1115 const struct devlink_port_region_ops *ops,
1116 u32 region_max_snapshots, u64 region_size)
1117 {
1118 struct devlink *devlink = port->devlink;
1119 struct devlink_region *region;
1120 int err = 0;
1121
1122 ASSERT_DEVLINK_PORT_INITIALIZED(port);
1123
1124 if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
1125 return ERR_PTR(-EINVAL);
1126
1127 devl_lock(devlink);
1128
1129 if (devlink_port_region_get_by_name(port, ops->name)) {
1130 err = -EEXIST;
1131 goto unlock;
1132 }
1133
1134 region = kzalloc(sizeof(*region), GFP_KERNEL);
1135 if (!region) {
1136 err = -ENOMEM;
1137 goto unlock;
1138 }
1139
1140 region->devlink = devlink;
1141 region->port = port;
1142 region->max_snapshots = region_max_snapshots;
1143 region->port_ops = ops;
1144 region->size = region_size;
1145 INIT_LIST_HEAD(®ion->snapshot_list);
1146 mutex_init(®ion->snapshot_lock);
1147 list_add_tail(®ion->list, &port->region_list);
1148 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
1149
1150 devl_unlock(devlink);
1151 return region;
1152
1153 unlock:
1154 devl_unlock(devlink);
1155 return ERR_PTR(err);
1156 }
1157 EXPORT_SYMBOL_GPL(devlink_port_region_create);
1158
1159 /**
1160 * devl_region_destroy - destroy address region
1161 *
1162 * @region: devlink region to destroy
1163 */
devl_region_destroy(struct devlink_region * region)1164 void devl_region_destroy(struct devlink_region *region)
1165 {
1166 struct devlink *devlink = region->devlink;
1167 struct devlink_snapshot *snapshot, *ts;
1168
1169 devl_assert_locked(devlink);
1170
1171 /* Free all snapshots of region */
1172 mutex_lock(®ion->snapshot_lock);
1173 list_for_each_entry_safe(snapshot, ts, ®ion->snapshot_list, list)
1174 devlink_region_snapshot_del(region, snapshot);
1175 mutex_unlock(®ion->snapshot_lock);
1176
1177 list_del(®ion->list);
1178 mutex_destroy(®ion->snapshot_lock);
1179
1180 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
1181 kfree(region);
1182 }
1183 EXPORT_SYMBOL_GPL(devl_region_destroy);
1184
1185 /**
1186 * devlink_region_destroy - destroy address region
1187 *
1188 * @region: devlink region to destroy
1189 *
1190 * Context: Takes and release devlink->lock <mutex>.
1191 */
devlink_region_destroy(struct devlink_region * region)1192 void devlink_region_destroy(struct devlink_region *region)
1193 {
1194 struct devlink *devlink = region->devlink;
1195
1196 devl_lock(devlink);
1197 devl_region_destroy(region);
1198 devl_unlock(devlink);
1199 }
1200 EXPORT_SYMBOL_GPL(devlink_region_destroy);
1201
1202 /**
1203 * devlink_region_snapshot_id_get - get snapshot ID
1204 *
1205 * This callback should be called when adding a new snapshot,
1206 * Driver should use the same id for multiple snapshots taken
1207 * on multiple regions at the same time/by the same trigger.
1208 *
1209 * The caller of this function must use devlink_region_snapshot_id_put
1210 * when finished creating regions using this id.
1211 *
1212 * Returns zero on success, or a negative error code on failure.
1213 *
1214 * @devlink: devlink
1215 * @id: storage to return id
1216 */
devlink_region_snapshot_id_get(struct devlink * devlink,u32 * id)1217 int devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
1218 {
1219 return __devlink_region_snapshot_id_get(devlink, id);
1220 }
1221 EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get);
1222
1223 /**
1224 * devlink_region_snapshot_id_put - put snapshot ID reference
1225 *
1226 * This should be called by a driver after finishing creating snapshots
1227 * with an id. Doing so ensures that the ID can later be released in the
1228 * event that all snapshots using it have been destroyed.
1229 *
1230 * @devlink: devlink
1231 * @id: id to release reference on
1232 */
devlink_region_snapshot_id_put(struct devlink * devlink,u32 id)1233 void devlink_region_snapshot_id_put(struct devlink *devlink, u32 id)
1234 {
1235 __devlink_snapshot_id_decrement(devlink, id);
1236 }
1237 EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_put);
1238
1239 /**
1240 * devlink_region_snapshot_create - create a new snapshot
1241 * This will add a new snapshot of a region. The snapshot
1242 * will be stored on the region struct and can be accessed
1243 * from devlink. This is useful for future analyses of snapshots.
1244 * Multiple snapshots can be created on a region.
1245 * The @snapshot_id should be obtained using the getter function.
1246 *
1247 * @region: devlink region of the snapshot
1248 * @data: snapshot data
1249 * @snapshot_id: snapshot id to be created
1250 */
devlink_region_snapshot_create(struct devlink_region * region,u8 * data,u32 snapshot_id)1251 int devlink_region_snapshot_create(struct devlink_region *region,
1252 u8 *data, u32 snapshot_id)
1253 {
1254 int err;
1255
1256 mutex_lock(®ion->snapshot_lock);
1257 err = __devlink_region_snapshot_create(region, data, snapshot_id);
1258 mutex_unlock(®ion->snapshot_lock);
1259 return err;
1260 }
1261 EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);
1262