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