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
9struct 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
27struct devlink_snapshot {
28 struct list_head list;
29 struct devlink_region *region;
30 u8 *data;
31 u32 id;
32};
33
34static struct devlink_region *
35devlink_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
46static struct devlink_region *
47devlink_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
59static struct devlink_snapshot *
60devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id)
61{
62 struct devlink_snapshot *snapshot;
63
64 list_for_each_entry(snapshot, &region->snapshot_list, list)
65 if (snapshot->id == id)
66 return snapshot;
67
68 return NULL;
69}
70
71static 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(skb: msg, attrtype: DEVLINK_ATTR_REGION_SNAPSHOT);
79 if (!snap_attr)
80 return -EINVAL;
81
82 err = nla_put_u32(skb: msg, attrtype: DEVLINK_ATTR_REGION_SNAPSHOT_ID, value: snapshot->id);
83 if (err)
84 goto nla_put_failure;
85
86 nla_nest_end(skb: msg, start: snap_attr);
87 return 0;
88
89nla_put_failure:
90 nla_nest_cancel(skb: msg, start: snap_attr);
91 return err;
92}
93
94static 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(skb: msg,
103 attrtype: DEVLINK_ATTR_REGION_SNAPSHOTS);
104 if (!snapshots_attr)
105 return -EINVAL;
106
107 list_for_each_entry(snapshot, &region->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(skb: msg, start: snapshots_attr);
114 return 0;
115
116nla_put_failure:
117 nla_nest_cancel(skb: msg, start: snapshots_attr);
118 return err;
119}
120
121static 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(skb: msg, portid, seq, family: &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(skb: msg, attrtype: DEVLINK_ATTR_PORT_INDEX,
139 value: region->port->index);
140 if (err)
141 goto nla_put_failure;
142 }
143
144 err = nla_put_string(skb: msg, attrtype: DEVLINK_ATTR_REGION_NAME, str: region->ops->name);
145 if (err)
146 goto nla_put_failure;
147
148 err = nla_put_u64_64bit(skb: msg, attrtype: DEVLINK_ATTR_REGION_SIZE,
149 value: region->size,
150 padattr: DEVLINK_ATTR_PAD);
151 if (err)
152 goto nla_put_failure;
153
154 err = nla_put_u32(skb: msg, attrtype: DEVLINK_ATTR_REGION_MAX_SNAPSHOTS,
155 value: 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(skb: msg, hdr);
164 return 0;
165
166nla_put_failure:
167 genlmsg_cancel(skb: msg, hdr);
168 return err;
169}
170
171static struct sk_buff *
172devlink_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(error: -ENOMEM);
184
185 hdr = genlmsg_put(skb: msg, portid, seq, family: &devlink_nl_family, flags: 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(skb: msg, attrtype: DEVLINK_ATTR_PORT_INDEX,
197 value: region->port->index);
198 if (err)
199 goto out_cancel_msg;
200 }
201
202 err = nla_put_string(skb: msg, attrtype: DEVLINK_ATTR_REGION_NAME,
203 str: region->ops->name);
204 if (err)
205 goto out_cancel_msg;
206
207 if (snapshot) {
208 err = nla_put_u32(skb: msg, attrtype: DEVLINK_ATTR_REGION_SNAPSHOT_ID,
209 value: snapshot->id);
210 if (err)
211 goto out_cancel_msg;
212 } else {
213 err = nla_put_u64_64bit(skb: msg, attrtype: DEVLINK_ATTR_REGION_SIZE,
214 value: region->size, padattr: DEVLINK_ATTR_PAD);
215 if (err)
216 goto out_cancel_msg;
217 }
218 genlmsg_end(skb: msg, hdr);
219
220 return msg;
221
222out_cancel_msg:
223 genlmsg_cancel(skb: msg, hdr);
224out_free_msg:
225 nlmsg_free(skb: msg);
226 return ERR_PTR(error: err);
227}
228
229static 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 if (!xa_get_mark(&devlinks, index: devlink->index, DEVLINK_REGISTERED))
238 return;
239
240 msg = devlink_nl_region_notify_build(region, snapshot, cmd, portid: 0, seq: 0);
241 if (IS_ERR(ptr: msg))
242 return;
243
244 genlmsg_multicast_netns(family: &devlink_nl_family, net: devlink_net(devlink), skb: msg,
245 portid: 0, group: DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
246}
247
248void 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, cmd: DEVLINK_CMD_REGION_NEW);
254}
255
256void 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, cmd: 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 */
279static 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, index: 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(entry: p);
298 count++;
299
300 err = xa_err(entry: __xa_store(&devlink->snapshot_ids, index: id, entry: xa_mk_value(v: count),
301 GFP_ATOMIC));
302unlock:
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 */
322static 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, index: 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(entry: p);
336
337 if (count > 1) {
338 count--;
339 __xa_store(&devlink->snapshot_ids, index: id, entry: xa_mk_value(v: count),
340 GFP_ATOMIC);
341 } else {
342 /* If this was the last user, we can erase this id */
343 __xa_erase(&devlink->snapshot_ids, index: id);
344 }
345unlock:
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 */
365static 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, index: id)) {
371 xa_unlock(&devlink->snapshot_ids);
372 return -EEXIST;
373 }
374 err = xa_err(entry: __xa_store(&devlink->snapshot_ids, index: id, entry: xa_mk_value(v: 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 */
396static int __devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
397{
398 return xa_alloc(xa: &devlink->snapshot_ids, id, entry: xa_mk_value(v: 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 */
416static int
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(&region->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, id: snapshot_id))
431 return -EEXIST;
432
433 snapshot = kzalloc(size: sizeof(*snapshot), GFP_KERNEL);
434 if (!snapshot)
435 return -ENOMEM;
436
437 err = __devlink_snapshot_id_increment(devlink, id: 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(new: &snapshot->list, head: &region->snapshot_list);
446
447 region->cur_snapshots++;
448
449 devlink_nl_region_notify(region, snapshot, cmd: DEVLINK_CMD_REGION_NEW);
450 return 0;
451
452err_snapshot_id_increment:
453 kfree(objp: snapshot);
454 return err;
455}
456
457static 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(&region->snapshot_lock);
463
464 devlink_nl_region_notify(region, snapshot, cmd: DEVLINK_CMD_REGION_DEL);
465 region->cur_snapshots--;
466 list_del(entry: &snapshot->list);
467 region->ops->destructor(snapshot->data);
468 __devlink_snapshot_id_decrement(devlink, id: snapshot->id);
469 kfree(objp: snapshot);
470}
471
472int 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(nla: info->attrs[DEVLINK_ATTR_PORT_INDEX]);
487
488 port = devlink_port_get_by_index(devlink, port_index: index);
489 if (!port)
490 return -ENODEV;
491 }
492
493 region_name = nla_data(nla: 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, cmd: DEVLINK_CMD_REGION_GET,
507 portid: info->snd_portid, seq: info->snd_seq, flags: 0,
508 region);
509 if (err) {
510 nlmsg_free(skb: msg);
511 return err;
512 }
513
514 return genlmsg_reply(skb: msg, info);
515}
516
517static 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, devlink: port->devlink,
531 cmd: DEVLINK_CMD_REGION_GET,
532 NETLINK_CB(cb->skb).portid,
533 seq: cb->nlh->nlmsg_seq,
534 flags, region);
535 if (err)
536 goto out;
537 (*idx)++;
538 }
539
540out:
541 return err;
542}
543
544static 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 cmd: DEVLINK_CMD_REGION_GET,
563 NETLINK_CB(cb->skb).portid,
564 seq: 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: &idx,
575 start: state->idx, flags);
576 if (err) {
577 state->idx = idx;
578 return err;
579 }
580 }
581
582 return 0;
583}
584
585int devlink_nl_region_get_dumpit(struct sk_buff *skb,
586 struct netlink_callback *cb)
587{
588 return devlink_nl_dumpit(msg: skb, cb, dump_one: devlink_nl_region_get_dump_one);
589}
590
591int 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(nla: info->attrs[DEVLINK_ATTR_REGION_NAME]);
606 snapshot_id = nla_get_u32(nla: info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
607
608 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
609 index = nla_get_u32(nla: info->attrs[DEVLINK_ATTR_PORT_INDEX]);
610
611 port = devlink_port_get_by_index(devlink, port_index: 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(&region->snapshot_lock);
625 snapshot = devlink_region_snapshot_get_by_id(region, id: snapshot_id);
626 if (!snapshot) {
627 mutex_unlock(lock: &region->snapshot_lock);
628 return -EINVAL;
629 }
630
631 devlink_region_snapshot_del(region, snapshot);
632 mutex_unlock(lock: &region->snapshot_lock);
633 return 0;
634}
635
636int 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(nla: info->attrs[DEVLINK_ATTR_REGION_NAME]);
655
656 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
657 index = nla_get_u32(nla: info->attrs[DEVLINK_ATTR_PORT_INDEX]);
658
659 port = devlink_port_get_by_index(devlink, port_index: 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(&region->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(nla: snapshot_id_attr);
690
691 if (devlink_region_snapshot_get_by_id(region, id: 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, id: snapshot_id);
698 if (err)
699 goto unlock;
700 } else {
701 err = __devlink_region_snapshot_id_get(devlink, id: &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 id: 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 cmd: DEVLINK_CMD_REGION_NEW,
733 portid: info->snd_portid,
734 seq: info->snd_seq);
735 err = PTR_ERR_OR_ZERO(ptr: msg);
736 if (err)
737 goto err_notify;
738
739 err = genlmsg_reply(skb: msg, info);
740 if (err)
741 goto err_notify;
742 }
743
744 mutex_unlock(lock: &region->snapshot_lock);
745 return 0;
746
747err_snapshot_create:
748 region->ops->destructor(data);
749err_snapshot_capture:
750 __devlink_snapshot_id_decrement(devlink, id: snapshot_id);
751 mutex_unlock(lock: &region->snapshot_lock);
752 return err;
753
754err_notify:
755 devlink_region_snapshot_del(region, snapshot);
756unlock:
757 mutex_unlock(lock: &region->snapshot_lock);
758 return err;
759}
760
761static 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(skb: msg, attrtype: DEVLINK_ATTR_REGION_CHUNK);
769 if (!chunk_attr)
770 return -EINVAL;
771
772 err = nla_put(skb: msg, attrtype: DEVLINK_ATTR_REGION_CHUNK_DATA, attrlen: chunk_size, data: chunk);
773 if (err)
774 goto nla_put_failure;
775
776 err = nla_put_u64_64bit(skb: msg, attrtype: DEVLINK_ATTR_REGION_CHUNK_ADDR, value: addr,
777 padattr: DEVLINK_ATTR_PAD);
778 if (err)
779 goto nla_put_failure;
780
781 nla_nest_end(skb: msg, start: chunk_attr);
782 return 0;
783
784nla_put_failure:
785 nla_nest_cancel(skb: msg, start: chunk_attr);
786 return err;
787}
788
789#define DEVLINK_REGION_READ_CHUNK_SIZE 256
790
791typedef int devlink_chunk_fill_t(void *cb_priv, u8 *chunk, u32 chunk_size,
792 u64 curr_offset,
793 struct netlink_ext_ack *extack);
794
795static int
796devlink_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(msg: skb, chunk: data, chunk_size: data_size, addr: curr_offset);
822 if (err)
823 break;
824
825 curr_offset += data_size;
826 }
827 *new_offset = curr_offset;
828
829 kfree(objp: data);
830
831 return err;
832}
833
834static int
835devlink_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
846static int
847devlink_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
856static int
857devlink_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
866int 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(net: sock_net(sk: cb->skb->sk), attrs);
887 if (IS_ERR(ptr: devlink))
888 return PTR_ERR(ptr: devlink);
889
890 if (!attrs[DEVLINK_ATTR_REGION_NAME]) {
891 NL_SET_ERR_MSG(cb->extack, "No region name provided");
892 err = -EINVAL;
893 goto out_unlock;
894 }
895
896 if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
897 index = nla_get_u32(nla: attrs[DEVLINK_ATTR_PORT_INDEX]);
898
899 port = devlink_port_get_by_index(devlink, port_index: index);
900 if (!port) {
901 err = -ENODEV;
902 goto out_unlock;
903 }
904 }
905
906 region_attr = attrs[DEVLINK_ATTR_REGION_NAME];
907 region_name = nla_data(nla: region_attr);
908
909 if (port)
910 region = devlink_port_region_get_by_name(port, region_name);
911 else
912 region = devlink_region_get_by_name(devlink, region_name);
913
914 if (!region) {
915 NL_SET_ERR_MSG_ATTR(cb->extack, region_attr, "Requested region does not exist");
916 err = -EINVAL;
917 goto out_unlock;
918 }
919
920 snapshot_attr = attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID];
921 if (!snapshot_attr) {
922 if (!nla_get_flag(nla: attrs[DEVLINK_ATTR_REGION_DIRECT])) {
923 NL_SET_ERR_MSG(cb->extack, "No snapshot id provided");
924 err = -EINVAL;
925 goto out_unlock;
926 }
927
928 if (!region->ops->read) {
929 NL_SET_ERR_MSG(cb->extack, "Requested region does not support direct read");
930 err = -EOPNOTSUPP;
931 goto out_unlock;
932 }
933
934 if (port)
935 region_cb = &devlink_region_port_direct_fill;
936 else
937 region_cb = &devlink_region_direct_fill;
938 region_cb_priv = region;
939 } else {
940 struct devlink_snapshot *snapshot;
941 u32 snapshot_id;
942
943 if (nla_get_flag(nla: attrs[DEVLINK_ATTR_REGION_DIRECT])) {
944 NL_SET_ERR_MSG_ATTR(cb->extack, snapshot_attr, "Direct region read does not use snapshot");
945 err = -EINVAL;
946 goto out_unlock;
947 }
948
949 snapshot_id = nla_get_u32(nla: snapshot_attr);
950 snapshot = devlink_region_snapshot_get_by_id(region, id: snapshot_id);
951 if (!snapshot) {
952 NL_SET_ERR_MSG_ATTR(cb->extack, snapshot_attr, "Requested snapshot does not exist");
953 err = -EINVAL;
954 goto out_unlock;
955 }
956 region_cb = &devlink_region_snapshot_fill;
957 region_cb_priv = snapshot;
958 }
959
960 if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] &&
961 attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) {
962 if (!start_offset)
963 start_offset =
964 nla_get_u64(nla: attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
965
966 end_offset = nla_get_u64(nla: attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
967 end_offset += nla_get_u64(nla: attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]);
968 }
969
970 if (end_offset > region->size)
971 end_offset = region->size;
972
973 /* return 0 if there is no further data to read */
974 if (start_offset == end_offset) {
975 err = 0;
976 goto out_unlock;
977 }
978
979 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, seq: cb->nlh->nlmsg_seq,
980 family: &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
981 cmd: DEVLINK_CMD_REGION_READ);
982 if (!hdr) {
983 err = -EMSGSIZE;
984 goto out_unlock;
985 }
986
987 err = devlink_nl_put_handle(msg: skb, devlink);
988 if (err)
989 goto nla_put_failure;
990
991 if (region->port) {
992 err = nla_put_u32(skb, attrtype: DEVLINK_ATTR_PORT_INDEX,
993 value: region->port->index);
994 if (err)
995 goto nla_put_failure;
996 }
997
998 err = nla_put_string(skb, attrtype: DEVLINK_ATTR_REGION_NAME, str: region_name);
999 if (err)
1000 goto nla_put_failure;
1001
1002 chunks_attr = nla_nest_start_noflag(skb, attrtype: DEVLINK_ATTR_REGION_CHUNKS);
1003 if (!chunks_attr) {
1004 err = -EMSGSIZE;
1005 goto nla_put_failure;
1006 }
1007
1008 err = devlink_nl_region_read_fill(skb, cb: region_cb, cb_priv: region_cb_priv,
1009 start_offset, end_offset, new_offset: &ret_offset,
1010 extack: cb->extack);
1011
1012 if (err && err != -EMSGSIZE)
1013 goto nla_put_failure;
1014
1015 /* Check if there was any progress done to prevent infinite loop */
1016 if (ret_offset == start_offset) {
1017 err = -EINVAL;
1018 goto nla_put_failure;
1019 }
1020
1021 state->start_offset = ret_offset;
1022
1023 nla_nest_end(skb, start: chunks_attr);
1024 genlmsg_end(skb, hdr);
1025 devl_unlock(devlink);
1026 devlink_put(devlink);
1027 return skb->len;
1028
1029nla_put_failure:
1030 genlmsg_cancel(skb, hdr);
1031out_unlock:
1032 devl_unlock(devlink);
1033 devlink_put(devlink);
1034 return err;
1035}
1036
1037/**
1038 * devl_region_create - create a new address region
1039 *
1040 * @devlink: devlink
1041 * @ops: region operations and name
1042 * @region_max_snapshots: Maximum supported number of snapshots for region
1043 * @region_size: size of region
1044 */
1045struct devlink_region *devl_region_create(struct devlink *devlink,
1046 const struct devlink_region_ops *ops,
1047 u32 region_max_snapshots,
1048 u64 region_size)
1049{
1050 struct devlink_region *region;
1051
1052 devl_assert_locked(devlink);
1053
1054 if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
1055 return ERR_PTR(error: -EINVAL);
1056
1057 if (devlink_region_get_by_name(devlink, region_name: ops->name))
1058 return ERR_PTR(error: -EEXIST);
1059
1060 region = kzalloc(size: sizeof(*region), GFP_KERNEL);
1061 if (!region)
1062 return ERR_PTR(error: -ENOMEM);
1063
1064 region->devlink = devlink;
1065 region->max_snapshots = region_max_snapshots;
1066 region->ops = ops;
1067 region->size = region_size;
1068 INIT_LIST_HEAD(list: &region->snapshot_list);
1069 mutex_init(&region->snapshot_lock);
1070 list_add_tail(new: &region->list, head: &devlink->region_list);
1071 devlink_nl_region_notify(region, NULL, cmd: DEVLINK_CMD_REGION_NEW);
1072
1073 return region;
1074}
1075EXPORT_SYMBOL_GPL(devl_region_create);
1076
1077/**
1078 * devlink_region_create - create a new address region
1079 *
1080 * @devlink: devlink
1081 * @ops: region operations and name
1082 * @region_max_snapshots: Maximum supported number of snapshots for region
1083 * @region_size: size of region
1084 *
1085 * Context: Takes and release devlink->lock <mutex>.
1086 */
1087struct devlink_region *
1088devlink_region_create(struct devlink *devlink,
1089 const struct devlink_region_ops *ops,
1090 u32 region_max_snapshots, u64 region_size)
1091{
1092 struct devlink_region *region;
1093
1094 devl_lock(devlink);
1095 region = devl_region_create(devlink, ops, region_max_snapshots,
1096 region_size);
1097 devl_unlock(devlink);
1098 return region;
1099}
1100EXPORT_SYMBOL_GPL(devlink_region_create);
1101
1102/**
1103 * devlink_port_region_create - create a new address region for a port
1104 *
1105 * @port: devlink port
1106 * @ops: region operations and name
1107 * @region_max_snapshots: Maximum supported number of snapshots for region
1108 * @region_size: size of region
1109 *
1110 * Context: Takes and release devlink->lock <mutex>.
1111 */
1112struct devlink_region *
1113devlink_port_region_create(struct devlink_port *port,
1114 const struct devlink_port_region_ops *ops,
1115 u32 region_max_snapshots, u64 region_size)
1116{
1117 struct devlink *devlink = port->devlink;
1118 struct devlink_region *region;
1119 int err = 0;
1120
1121 ASSERT_DEVLINK_PORT_INITIALIZED(port);
1122
1123 if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
1124 return ERR_PTR(error: -EINVAL);
1125
1126 devl_lock(devlink);
1127
1128 if (devlink_port_region_get_by_name(port, region_name: ops->name)) {
1129 err = -EEXIST;
1130 goto unlock;
1131 }
1132
1133 region = kzalloc(size: sizeof(*region), GFP_KERNEL);
1134 if (!region) {
1135 err = -ENOMEM;
1136 goto unlock;
1137 }
1138
1139 region->devlink = devlink;
1140 region->port = port;
1141 region->max_snapshots = region_max_snapshots;
1142 region->port_ops = ops;
1143 region->size = region_size;
1144 INIT_LIST_HEAD(list: &region->snapshot_list);
1145 mutex_init(&region->snapshot_lock);
1146 list_add_tail(new: &region->list, head: &port->region_list);
1147 devlink_nl_region_notify(region, NULL, cmd: DEVLINK_CMD_REGION_NEW);
1148
1149 devl_unlock(devlink);
1150 return region;
1151
1152unlock:
1153 devl_unlock(devlink);
1154 return ERR_PTR(error: err);
1155}
1156EXPORT_SYMBOL_GPL(devlink_port_region_create);
1157
1158/**
1159 * devl_region_destroy - destroy address region
1160 *
1161 * @region: devlink region to destroy
1162 */
1163void devl_region_destroy(struct devlink_region *region)
1164{
1165 struct devlink *devlink = region->devlink;
1166 struct devlink_snapshot *snapshot, *ts;
1167
1168 devl_assert_locked(devlink);
1169
1170 /* Free all snapshots of region */
1171 mutex_lock(&region->snapshot_lock);
1172 list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list)
1173 devlink_region_snapshot_del(region, snapshot);
1174 mutex_unlock(lock: &region->snapshot_lock);
1175
1176 list_del(entry: &region->list);
1177 mutex_destroy(lock: &region->snapshot_lock);
1178
1179 devlink_nl_region_notify(region, NULL, cmd: DEVLINK_CMD_REGION_DEL);
1180 kfree(objp: region);
1181}
1182EXPORT_SYMBOL_GPL(devl_region_destroy);
1183
1184/**
1185 * devlink_region_destroy - destroy address region
1186 *
1187 * @region: devlink region to destroy
1188 *
1189 * Context: Takes and release devlink->lock <mutex>.
1190 */
1191void devlink_region_destroy(struct devlink_region *region)
1192{
1193 struct devlink *devlink = region->devlink;
1194
1195 devl_lock(devlink);
1196 devl_region_destroy(region);
1197 devl_unlock(devlink);
1198}
1199EXPORT_SYMBOL_GPL(devlink_region_destroy);
1200
1201/**
1202 * devlink_region_snapshot_id_get - get snapshot ID
1203 *
1204 * This callback should be called when adding a new snapshot,
1205 * Driver should use the same id for multiple snapshots taken
1206 * on multiple regions at the same time/by the same trigger.
1207 *
1208 * The caller of this function must use devlink_region_snapshot_id_put
1209 * when finished creating regions using this id.
1210 *
1211 * Returns zero on success, or a negative error code on failure.
1212 *
1213 * @devlink: devlink
1214 * @id: storage to return id
1215 */
1216int devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
1217{
1218 return __devlink_region_snapshot_id_get(devlink, id);
1219}
1220EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get);
1221
1222/**
1223 * devlink_region_snapshot_id_put - put snapshot ID reference
1224 *
1225 * This should be called by a driver after finishing creating snapshots
1226 * with an id. Doing so ensures that the ID can later be released in the
1227 * event that all snapshots using it have been destroyed.
1228 *
1229 * @devlink: devlink
1230 * @id: id to release reference on
1231 */
1232void devlink_region_snapshot_id_put(struct devlink *devlink, u32 id)
1233{
1234 __devlink_snapshot_id_decrement(devlink, id);
1235}
1236EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_put);
1237
1238/**
1239 * devlink_region_snapshot_create - create a new snapshot
1240 * This will add a new snapshot of a region. The snapshot
1241 * will be stored on the region struct and can be accessed
1242 * from devlink. This is useful for future analyses of snapshots.
1243 * Multiple snapshots can be created on a region.
1244 * The @snapshot_id should be obtained using the getter function.
1245 *
1246 * @region: devlink region of the snapshot
1247 * @data: snapshot data
1248 * @snapshot_id: snapshot id to be created
1249 */
1250int devlink_region_snapshot_create(struct devlink_region *region,
1251 u8 *data, u32 snapshot_id)
1252{
1253 int err;
1254
1255 mutex_lock(&region->snapshot_lock);
1256 err = __devlink_region_snapshot_create(region, data, snapshot_id);
1257 mutex_unlock(lock: &region->snapshot_lock);
1258 return err;
1259}
1260EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);
1261

source code of linux/net/devlink/region.c