printf: Remove unused 'bprintf'
[drm/drm-misc.git] / net / devlink / region.c
blob63fb297f6d6785cd2d7f488b563e3a2f7dc3fefd
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 */
7 #include "devl_internal.h"
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;
17 struct mutex snapshot_lock; /* protects snapshot_list,
18 * max_snapshots and cur_snapshots
19 * consistency.
21 struct list_head snapshot_list;
22 u32 max_snapshots;
23 u32 cur_snapshots;
24 u64 size;
27 struct devlink_snapshot {
28 struct list_head list;
29 struct devlink_region *region;
30 u8 *data;
31 u32 id;
34 static struct devlink_region *
35 devlink_region_get_by_name(struct devlink *devlink, const char *region_name)
37 struct devlink_region *region;
39 list_for_each_entry(region, &devlink->region_list, list)
40 if (!strcmp(region->ops->name, region_name))
41 return region;
43 return NULL;
46 static struct devlink_region *
47 devlink_port_region_get_by_name(struct devlink_port *port,
48 const char *region_name)
50 struct devlink_region *region;
52 list_for_each_entry(region, &port->region_list, list)
53 if (!strcmp(region->ops->name, region_name))
54 return region;
56 return NULL;
59 static struct devlink_snapshot *
60 devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id)
62 struct devlink_snapshot *snapshot;
64 list_for_each_entry(snapshot, &region->snapshot_list, list)
65 if (snapshot->id == id)
66 return snapshot;
68 return NULL;
71 static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg,
72 struct devlink *devlink,
73 struct devlink_snapshot *snapshot)
75 struct nlattr *snap_attr;
76 int err;
78 snap_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_SNAPSHOT);
79 if (!snap_attr)
80 return -EMSGSIZE;
82 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id);
83 if (err)
84 goto nla_put_failure;
86 nla_nest_end(msg, snap_attr);
87 return 0;
89 nla_put_failure:
90 nla_nest_cancel(msg, snap_attr);
91 return err;
94 static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg,
95 struct devlink *devlink,
96 struct devlink_region *region)
98 struct devlink_snapshot *snapshot;
99 struct nlattr *snapshots_attr;
100 int err;
102 snapshots_attr = nla_nest_start_noflag(msg,
103 DEVLINK_ATTR_REGION_SNAPSHOTS);
104 if (!snapshots_attr)
105 return -EMSGSIZE;
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;
113 nla_nest_end(msg, snapshots_attr);
114 return 0;
116 nla_put_failure:
117 nla_nest_cancel(msg, snapshots_attr);
118 return err;
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)
126 void *hdr;
127 int err;
129 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
130 if (!hdr)
131 return -EMSGSIZE;
133 err = devlink_nl_put_handle(msg, devlink);
134 if (err)
135 goto nla_put_failure;
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;
144 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->ops->name);
145 if (err)
146 goto nla_put_failure;
148 err = devlink_nl_put_u64(msg, DEVLINK_ATTR_REGION_SIZE, region->size);
149 if (err)
150 goto nla_put_failure;
152 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_MAX_SNAPSHOTS,
153 region->max_snapshots);
154 if (err)
155 goto nla_put_failure;
157 err = devlink_nl_region_snapshots_id_put(msg, devlink, region);
158 if (err)
159 goto nla_put_failure;
161 genlmsg_end(msg, hdr);
162 return 0;
164 nla_put_failure:
165 genlmsg_cancel(msg, hdr);
166 return err;
169 static struct sk_buff *
170 devlink_nl_region_notify_build(struct devlink_region *region,
171 struct devlink_snapshot *snapshot,
172 enum devlink_command cmd, u32 portid, u32 seq)
174 struct devlink *devlink = region->devlink;
175 struct sk_buff *msg;
176 void *hdr;
177 int err;
179 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
180 if (!msg)
181 return ERR_PTR(-ENOMEM);
183 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, 0, cmd);
184 if (!hdr) {
185 err = -EMSGSIZE;
186 goto out_free_msg;
189 err = devlink_nl_put_handle(msg, devlink);
190 if (err)
191 goto out_cancel_msg;
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;
200 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME,
201 region->ops->name);
202 if (err)
203 goto out_cancel_msg;
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;
216 genlmsg_end(msg, hdr);
218 return msg;
220 out_cancel_msg:
221 genlmsg_cancel(msg, hdr);
222 out_free_msg:
223 nlmsg_free(msg);
224 return ERR_PTR(err);
227 static void devlink_nl_region_notify(struct devlink_region *region,
228 struct devlink_snapshot *snapshot,
229 enum devlink_command cmd)
231 struct devlink *devlink = region->devlink;
232 struct sk_buff *msg;
234 WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL);
236 if (!__devl_is_registered(devlink) || !devlink_nl_notify_need(devlink))
237 return;
239 msg = devlink_nl_region_notify_build(region, snapshot, cmd, 0, 0);
240 if (IS_ERR(msg))
241 return;
243 devlink_nl_notify_send(devlink, msg);
246 void devlink_regions_notify_register(struct devlink *devlink)
248 struct devlink_region *region;
250 list_for_each_entry(region, &devlink->region_list, list)
251 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
254 void devlink_regions_notify_unregister(struct devlink *devlink)
256 struct devlink_region *region;
258 list_for_each_entry_reverse(region, &devlink->region_list, list)
259 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
263 * __devlink_snapshot_id_increment - Increment number of snapshots using an id
264 * @devlink: devlink instance
265 * @id: the snapshot id
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.
270 * Called when a new snapshot is created with the given id.
272 * The id *must* have been previously allocated by
273 * devlink_region_snapshot_id_get().
275 * Returns 0 on success, or an error on failure.
277 static int __devlink_snapshot_id_increment(struct devlink *devlink, u32 id)
279 unsigned long count;
280 void *p;
281 int err;
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;
290 if (WARN_ON(!xa_is_value(p))) {
291 err = -EINVAL;
292 goto unlock;
295 count = xa_to_value(p);
296 count++;
298 err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
299 GFP_ATOMIC));
300 unlock:
301 xa_unlock(&devlink->snapshot_ids);
302 return err;
306 * __devlink_snapshot_id_decrement - Decrease number of snapshots using an id
307 * @devlink: devlink instance
308 * @id: the snapshot id
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.
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().
317 * Called when a snapshot using the given id is deleted, and when the
318 * initial allocator of the id is finished using it.
320 static void __devlink_snapshot_id_decrement(struct devlink *devlink, u32 id)
322 unsigned long count;
323 void *p;
325 xa_lock(&devlink->snapshot_ids);
326 p = xa_load(&devlink->snapshot_ids, id);
327 if (WARN_ON(!p))
328 goto unlock;
330 if (WARN_ON(!xa_is_value(p)))
331 goto unlock;
333 count = xa_to_value(p);
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);
343 unlock:
344 xa_unlock(&devlink->snapshot_ids);
348 * __devlink_snapshot_id_insert - Insert a specific snapshot ID
349 * @devlink: devlink instance
350 * @id: the snapshot id
352 * Mark the given snapshot id as used by inserting a zero value into the
353 * snapshot xarray.
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.
360 * Returns zero on success, or an error code if the snapshot id could not
361 * be inserted.
363 static int __devlink_snapshot_id_insert(struct devlink *devlink, u32 id)
365 int err;
367 xa_lock(&devlink->snapshot_ids);
368 if (xa_load(&devlink->snapshot_ids, id)) {
369 xa_unlock(&devlink->snapshot_ids);
370 return -EEXIST;
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;
379 * __devlink_region_snapshot_id_get - get snapshot ID
380 * @devlink: devlink instance
381 * @id: storage to return snapshot id
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.
387 * Snapshot IDs are tracked using an xarray which stores the number of
388 * users of the snapshot id.
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.
394 static int __devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
396 return xa_alloc(&devlink->snapshot_ids, id, xa_mk_value(1),
397 xa_limit_32b, GFP_KERNEL);
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.
408 * Must be called only while holding the region snapshot lock.
410 * @region: devlink region of the snapshot
411 * @data: snapshot data
412 * @snapshot_id: snapshot id to be created
414 static int
415 __devlink_region_snapshot_create(struct devlink_region *region,
416 u8 *data, u32 snapshot_id)
418 struct devlink *devlink = region->devlink;
419 struct devlink_snapshot *snapshot;
420 int err;
422 lockdep_assert_held(&region->snapshot_lock);
424 /* check if region can hold one more snapshot */
425 if (region->cur_snapshots == region->max_snapshots)
426 return -ENOSPC;
428 if (devlink_region_snapshot_get_by_id(region, snapshot_id))
429 return -EEXIST;
431 snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL);
432 if (!snapshot)
433 return -ENOMEM;
435 err = __devlink_snapshot_id_increment(devlink, snapshot_id);
436 if (err)
437 goto err_snapshot_id_increment;
439 snapshot->id = snapshot_id;
440 snapshot->region = region;
441 snapshot->data = data;
443 list_add_tail(&snapshot->list, &region->snapshot_list);
445 region->cur_snapshots++;
447 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW);
448 return 0;
450 err_snapshot_id_increment:
451 kfree(snapshot);
452 return err;
455 static void devlink_region_snapshot_del(struct devlink_region *region,
456 struct devlink_snapshot *snapshot)
458 struct devlink *devlink = region->devlink;
460 lockdep_assert_held(&region->snapshot_lock);
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);
470 int devlink_nl_region_get_doit(struct sk_buff *skb, struct genl_info *info)
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;
480 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME))
481 return -EINVAL;
483 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
484 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
486 port = devlink_port_get_by_index(devlink, index);
487 if (!port)
488 return -ENODEV;
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);
497 if (!region)
498 return -EINVAL;
500 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
501 if (!msg)
502 return -ENOMEM;
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;
512 return genlmsg_reply(msg, info);
515 static 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)
520 struct devlink_region *region;
521 int err = 0;
523 list_for_each_entry(region, &port->region_list, list) {
524 if (*idx < start) {
525 (*idx)++;
526 continue;
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)++;
538 out:
539 return err;
542 static int devlink_nl_region_get_dump_one(struct sk_buff *msg,
543 struct devlink *devlink,
544 struct netlink_callback *cb,
545 int flags)
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;
554 list_for_each_entry(region, &devlink->region_list, list) {
555 if (idx < state->idx) {
556 idx++;
557 continue;
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;
568 idx++;
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;
580 return 0;
583 int devlink_nl_region_get_dumpit(struct sk_buff *skb,
584 struct netlink_callback *cb)
586 return devlink_nl_dumpit(skb, cb, devlink_nl_region_get_dump_one);
589 int devlink_nl_region_del_doit(struct sk_buff *skb, struct genl_info *info)
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;
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;
603 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
604 snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
606 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
607 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
609 port = devlink_port_get_by_index(devlink, index);
610 if (!port)
611 return -ENODEV;
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);
619 if (!region)
620 return -EINVAL;
622 mutex_lock(&region->snapshot_lock);
623 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
624 if (!snapshot) {
625 mutex_unlock(&region->snapshot_lock);
626 return -EINVAL;
629 devlink_region_snapshot_del(region, snapshot);
630 mutex_unlock(&region->snapshot_lock);
631 return 0;
634 int devlink_nl_region_new_doit(struct sk_buff *skb, struct genl_info *info)
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;
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;
652 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
654 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
655 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
657 port = devlink_port_get_by_index(devlink, index);
658 if (!port)
659 return -ENODEV;
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);
667 if (!region) {
668 NL_SET_ERR_MSG(info->extack, "The requested region does not exist");
669 return -EINVAL;
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;
677 mutex_lock(&region->snapshot_lock);
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;
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);
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;
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;
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;
715 err = __devlink_region_snapshot_create(region, data, snapshot_id);
716 if (err)
717 goto err_snapshot_create;
719 if (!snapshot_id_attr) {
720 struct sk_buff *msg;
722 snapshot = devlink_region_snapshot_get_by_id(region,
723 snapshot_id);
724 if (WARN_ON(!snapshot)) {
725 err = -EINVAL;
726 goto unlock;
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;
737 err = genlmsg_reply(msg, info);
738 if (err)
739 goto err_notify;
742 mutex_unlock(&region->snapshot_lock);
743 return 0;
745 err_snapshot_create:
746 region->ops->destructor(data);
747 err_snapshot_capture:
748 __devlink_snapshot_id_decrement(devlink, snapshot_id);
749 mutex_unlock(&region->snapshot_lock);
750 return err;
752 err_notify:
753 devlink_region_snapshot_del(region, snapshot);
754 unlock:
755 mutex_unlock(&region->snapshot_lock);
756 return err;
759 static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg,
760 u8 *chunk, u32 chunk_size,
761 u64 addr)
763 struct nlattr *chunk_attr;
764 int err;
766 chunk_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_CHUNK);
767 if (!chunk_attr)
768 return -EINVAL;
770 err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk);
771 if (err)
772 goto nla_put_failure;
774 err = devlink_nl_put_u64(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr);
775 if (err)
776 goto nla_put_failure;
778 nla_nest_end(msg, chunk_attr);
779 return 0;
781 nla_put_failure:
782 nla_nest_cancel(msg, chunk_attr);
783 return err;
786 #define DEVLINK_REGION_READ_CHUNK_SIZE 256
788 typedef int devlink_chunk_fill_t(void *cb_priv, u8 *chunk, u32 chunk_size,
789 u64 curr_offset,
790 struct netlink_ext_ack *extack);
792 static int
793 devlink_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)
797 u64 curr_offset = start_offset;
798 int err = 0;
799 u8 *data;
801 /* Allocate and re-use a single buffer */
802 data = kmalloc(DEVLINK_REGION_READ_CHUNK_SIZE, GFP_KERNEL);
803 if (!data)
804 return -ENOMEM;
806 *new_offset = start_offset;
808 while (curr_offset < end_offset) {
809 u32 data_size;
811 data_size = min_t(u32, end_offset - curr_offset,
812 DEVLINK_REGION_READ_CHUNK_SIZE);
814 err = cb(cb_priv, data, data_size, curr_offset, extack);
815 if (err)
816 break;
818 err = devlink_nl_cmd_region_read_chunk_fill(skb, data, data_size, curr_offset);
819 if (err)
820 break;
822 curr_offset += data_size;
824 *new_offset = curr_offset;
826 kfree(data);
828 return err;
831 static int
832 devlink_region_snapshot_fill(void *cb_priv, u8 *chunk, u32 chunk_size,
833 u64 curr_offset,
834 struct netlink_ext_ack __always_unused *extack)
836 struct devlink_snapshot *snapshot = cb_priv;
838 memcpy(chunk, &snapshot->data[curr_offset], chunk_size);
840 return 0;
843 static int
844 devlink_region_port_direct_fill(void *cb_priv, u8 *chunk, u32 chunk_size,
845 u64 curr_offset, struct netlink_ext_ack *extack)
847 struct devlink_region *region = cb_priv;
849 return region->port_ops->read(region->port, region->port_ops, extack,
850 curr_offset, chunk_size, chunk);
853 static int
854 devlink_region_direct_fill(void *cb_priv, u8 *chunk, u32 chunk_size,
855 u64 curr_offset, struct netlink_ext_ack *extack)
857 struct devlink_region *region = cb_priv;
859 return region->ops->read(region->devlink, region->ops, extack,
860 curr_offset, chunk_size, chunk);
863 int devlink_nl_region_read_dumpit(struct sk_buff *skb,
864 struct netlink_callback *cb)
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;
881 start_offset = state->start_offset;
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);
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;
894 if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
895 index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
897 port = devlink_port_get_by_index(devlink, index);
898 if (!port) {
899 err = -ENODEV;
900 goto out_unlock;
904 region_attr = attrs[DEVLINK_ATTR_REGION_NAME];
905 region_name = nla_data(region_attr);
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);
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;
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;
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;
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;
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;
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;
954 region_cb = &devlink_region_snapshot_fill;
955 region_cb_priv = snapshot;
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]);
964 end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
965 end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]);
968 if (end_offset > region->size)
969 end_offset = region->size;
971 /* return 0 if there is no further data to read */
972 if (start_offset == end_offset) {
973 err = 0;
974 goto out_unlock;
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;
985 err = devlink_nl_put_handle(skb, devlink);
986 if (err)
987 goto nla_put_failure;
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;
996 err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
997 if (err)
998 goto nla_put_failure;
1000 chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS);
1001 if (!chunks_attr) {
1002 err = -EMSGSIZE;
1003 goto nla_put_failure;
1006 err = devlink_nl_region_read_fill(skb, region_cb, region_cb_priv,
1007 start_offset, end_offset, &ret_offset,
1008 cb->extack);
1010 if (err && err != -EMSGSIZE)
1011 goto nla_put_failure;
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;
1019 state->start_offset = ret_offset;
1021 nla_nest_end(skb, chunks_attr);
1022 genlmsg_end(skb, hdr);
1023 devl_unlock(devlink);
1024 devlink_put(devlink);
1025 return skb->len;
1027 nla_put_failure:
1028 genlmsg_cancel(skb, hdr);
1029 out_unlock:
1030 devl_unlock(devlink);
1031 devlink_put(devlink);
1032 return err;
1036 * devl_region_create - create a new address region
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
1043 struct devlink_region *devl_region_create(struct devlink *devlink,
1044 const struct devlink_region_ops *ops,
1045 u32 region_max_snapshots,
1046 u64 region_size)
1048 struct devlink_region *region;
1050 devl_assert_locked(devlink);
1052 if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
1053 return ERR_PTR(-EINVAL);
1055 if (devlink_region_get_by_name(devlink, ops->name))
1056 return ERR_PTR(-EEXIST);
1058 region = kzalloc(sizeof(*region), GFP_KERNEL);
1059 if (!region)
1060 return ERR_PTR(-ENOMEM);
1062 region->devlink = devlink;
1063 region->max_snapshots = region_max_snapshots;
1064 region->ops = ops;
1065 region->size = region_size;
1066 INIT_LIST_HEAD(&region->snapshot_list);
1067 mutex_init(&region->snapshot_lock);
1068 list_add_tail(&region->list, &devlink->region_list);
1069 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
1071 return region;
1073 EXPORT_SYMBOL_GPL(devl_region_create);
1076 * devlink_region_create - create a new address region
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
1083 * Context: Takes and release devlink->lock <mutex>.
1085 struct devlink_region *
1086 devlink_region_create(struct devlink *devlink,
1087 const struct devlink_region_ops *ops,
1088 u32 region_max_snapshots, u64 region_size)
1090 struct devlink_region *region;
1092 devl_lock(devlink);
1093 region = devl_region_create(devlink, ops, region_max_snapshots,
1094 region_size);
1095 devl_unlock(devlink);
1096 return region;
1098 EXPORT_SYMBOL_GPL(devlink_region_create);
1101 * devlink_port_region_create - create a new address region for a port
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
1108 * Context: Takes and release devlink->lock <mutex>.
1110 struct devlink_region *
1111 devlink_port_region_create(struct devlink_port *port,
1112 const struct devlink_port_region_ops *ops,
1113 u32 region_max_snapshots, u64 region_size)
1115 struct devlink *devlink = port->devlink;
1116 struct devlink_region *region;
1117 int err = 0;
1119 ASSERT_DEVLINK_PORT_INITIALIZED(port);
1121 if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
1122 return ERR_PTR(-EINVAL);
1124 devl_lock(devlink);
1126 if (devlink_port_region_get_by_name(port, ops->name)) {
1127 err = -EEXIST;
1128 goto unlock;
1131 region = kzalloc(sizeof(*region), GFP_KERNEL);
1132 if (!region) {
1133 err = -ENOMEM;
1134 goto unlock;
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(&region->snapshot_list);
1143 mutex_init(&region->snapshot_lock);
1144 list_add_tail(&region->list, &port->region_list);
1145 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
1147 devl_unlock(devlink);
1148 return region;
1150 unlock:
1151 devl_unlock(devlink);
1152 return ERR_PTR(err);
1154 EXPORT_SYMBOL_GPL(devlink_port_region_create);
1157 * devl_region_destroy - destroy address region
1159 * @region: devlink region to destroy
1161 void devl_region_destroy(struct devlink_region *region)
1163 struct devlink *devlink = region->devlink;
1164 struct devlink_snapshot *snapshot, *ts;
1166 devl_assert_locked(devlink);
1168 /* Free all snapshots of region */
1169 mutex_lock(&region->snapshot_lock);
1170 list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list)
1171 devlink_region_snapshot_del(region, snapshot);
1172 mutex_unlock(&region->snapshot_lock);
1174 list_del(&region->list);
1175 mutex_destroy(&region->snapshot_lock);
1177 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
1178 kfree(region);
1180 EXPORT_SYMBOL_GPL(devl_region_destroy);
1183 * devlink_region_destroy - destroy address region
1185 * @region: devlink region to destroy
1187 * Context: Takes and release devlink->lock <mutex>.
1189 void devlink_region_destroy(struct devlink_region *region)
1191 struct devlink *devlink = region->devlink;
1193 devl_lock(devlink);
1194 devl_region_destroy(region);
1195 devl_unlock(devlink);
1197 EXPORT_SYMBOL_GPL(devlink_region_destroy);
1200 * devlink_region_snapshot_id_get - get snapshot ID
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.
1206 * The caller of this function must use devlink_region_snapshot_id_put
1207 * when finished creating regions using this id.
1209 * Returns zero on success, or a negative error code on failure.
1211 * @devlink: devlink
1212 * @id: storage to return id
1214 int devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
1216 return __devlink_region_snapshot_id_get(devlink, id);
1218 EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get);
1221 * devlink_region_snapshot_id_put - put snapshot ID reference
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.
1227 * @devlink: devlink
1228 * @id: id to release reference on
1230 void devlink_region_snapshot_id_put(struct devlink *devlink, u32 id)
1232 __devlink_snapshot_id_decrement(devlink, id);
1234 EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_put);
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.
1244 * @region: devlink region of the snapshot
1245 * @data: snapshot data
1246 * @snapshot_id: snapshot id to be created
1248 int devlink_region_snapshot_create(struct devlink_region *region,
1249 u8 *data, u32 snapshot_id)
1251 int err;
1253 mutex_lock(&region->snapshot_lock);
1254 err = __devlink_region_snapshot_create(region, data, snapshot_id);
1255 mutex_unlock(&region->snapshot_lock);
1256 return err;
1258 EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);