xref: /kernel/linux/linux-6.6/net/devlink/region.c (revision 62306a36)
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(msg, DEVLINK_ATTR_REGION_SNAPSHOT);
79	if (!snap_attr)
80		return -EINVAL;
81
82	err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id);
83	if (err)
84		goto nla_put_failure;
85
86	nla_nest_end(msg, snap_attr);
87	return 0;
88
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 -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(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 = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
149				region->size,
150				DEVLINK_ATTR_PAD);
151	if (err)
152		goto nla_put_failure;
153
154	err = nla_put_u32(msg, DEVLINK_ATTR_REGION_MAX_SNAPSHOTS,
155			  region->max_snapshots);
156	if (err)
157		goto nla_put_failure;
158
159	err = devlink_nl_region_snapshots_id_put(msg, devlink, region);
160	if (err)
161		goto nla_put_failure;
162
163	genlmsg_end(msg, hdr);
164	return 0;
165
166nla_put_failure:
167	genlmsg_cancel(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(-ENOMEM);
184
185	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, 0, cmd);
186	if (!hdr) {
187		err = -EMSGSIZE;
188		goto out_free_msg;
189	}
190
191	err = devlink_nl_put_handle(msg, devlink);
192	if (err)
193		goto out_cancel_msg;
194
195	if (region->port) {
196		err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
197				  region->port->index);
198		if (err)
199			goto out_cancel_msg;
200	}
201
202	err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME,
203			     region->ops->name);
204	if (err)
205		goto out_cancel_msg;
206
207	if (snapshot) {
208		err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID,
209				  snapshot->id);
210		if (err)
211			goto out_cancel_msg;
212	} else {
213		err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
214					region->size, DEVLINK_ATTR_PAD);
215		if (err)
216			goto out_cancel_msg;
217	}
218	genlmsg_end(msg, hdr);
219
220	return msg;
221
222out_cancel_msg:
223	genlmsg_cancel(msg, hdr);
224out_free_msg:
225	nlmsg_free(msg);
226	return ERR_PTR(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, devlink->index, DEVLINK_REGISTERED))
238		return;
239
240	msg = devlink_nl_region_notify_build(region, snapshot, cmd, 0, 0);
241	if (IS_ERR(msg))
242		return;
243
244	genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), msg,
245				0, 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, 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, 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, id);
287	if (WARN_ON(!p)) {
288		err = -EINVAL;
289		goto unlock;
290	}
291
292	if (WARN_ON(!xa_is_value(p))) {
293		err = -EINVAL;
294		goto unlock;
295	}
296
297	count = xa_to_value(p);
298	count++;
299
300	err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
301				GFP_ATOMIC));
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, id);
329	if (WARN_ON(!p))
330		goto unlock;
331
332	if (WARN_ON(!xa_is_value(p)))
333		goto unlock;
334
335	count = xa_to_value(p);
336
337	if (count > 1) {
338		count--;
339		__xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
340			   GFP_ATOMIC);
341	} else {
342		/* If this was the last user, we can erase this id */
343		__xa_erase(&devlink->snapshot_ids, id);
344	}
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, id)) {
371		xa_unlock(&devlink->snapshot_ids);
372		return -EEXIST;
373	}
374	err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(0),
375				GFP_ATOMIC));
376	xa_unlock(&devlink->snapshot_ids);
377	return err;
378}
379
380/**
381 *	__devlink_region_snapshot_id_get - get snapshot ID
382 *	@devlink: devlink instance
383 *	@id: storage to return snapshot id
384 *
385 *	Allocates a new snapshot id. Returns zero on success, or a negative
386 *	error on failure. Must be called while holding the devlink instance
387 *	lock.
388 *
389 *	Snapshot IDs are tracked using an xarray which stores the number of
390 *	users of the snapshot id.
391 *
392 *	Note that the caller of this function counts as a 'user', in order to
393 *	avoid race conditions. The caller must release its hold on the
394 *	snapshot by using devlink_region_snapshot_id_put.
395 */
396static int __devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
397{
398	return xa_alloc(&devlink->snapshot_ids, id, xa_mk_value(1),
399			xa_limit_32b, GFP_KERNEL);
400}
401
402/**
403 *	__devlink_region_snapshot_create - create a new snapshot
404 *	This will add a new snapshot of a region. The snapshot
405 *	will be stored on the region struct and can be accessed
406 *	from devlink. This is useful for future analyses of snapshots.
407 *	Multiple snapshots can be created on a region.
408 *	The @snapshot_id should be obtained using the getter function.
409 *
410 *	Must be called only while holding the region snapshot lock.
411 *
412 *	@region: devlink region of the snapshot
413 *	@data: snapshot data
414 *	@snapshot_id: snapshot id to be created
415 */
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, snapshot_id))
431		return -EEXIST;
432
433	snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL);
434	if (!snapshot)
435		return -ENOMEM;
436
437	err = __devlink_snapshot_id_increment(devlink, snapshot_id);
438	if (err)
439		goto err_snapshot_id_increment;
440
441	snapshot->id = snapshot_id;
442	snapshot->region = region;
443	snapshot->data = data;
444
445	list_add_tail(&snapshot->list, &region->snapshot_list);
446
447	region->cur_snapshots++;
448
449	devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW);
450	return 0;
451
452err_snapshot_id_increment:
453	kfree(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, DEVLINK_CMD_REGION_DEL);
465	region->cur_snapshots--;
466	list_del(&snapshot->list);
467	region->ops->destructor(snapshot->data);
468	__devlink_snapshot_id_decrement(devlink, snapshot->id);
469	kfree(snapshot);
470}
471
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(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
487
488		port = devlink_port_get_by_index(devlink, index);
489		if (!port)
490			return -ENODEV;
491	}
492
493	region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
494	if (port)
495		region = devlink_port_region_get_by_name(port, region_name);
496	else
497		region = devlink_region_get_by_name(devlink, region_name);
498
499	if (!region)
500		return -EINVAL;
501
502	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
503	if (!msg)
504		return -ENOMEM;
505
506	err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET,
507				     info->snd_portid, info->snd_seq, 0,
508				     region);
509	if (err) {
510		nlmsg_free(msg);
511		return err;
512	}
513
514	return genlmsg_reply(msg, info);
515}
516
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, port->devlink,
531					     DEVLINK_CMD_REGION_GET,
532					     NETLINK_CB(cb->skb).portid,
533					     cb->nlh->nlmsg_seq,
534					     flags, region);
535		if (err)
536			goto out;
537		(*idx)++;
538	}
539
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					     DEVLINK_CMD_REGION_GET,
563					     NETLINK_CB(cb->skb).portid,
564					     cb->nlh->nlmsg_seq, flags,
565					     region);
566		if (err) {
567			state->idx = idx;
568			return err;
569		}
570		idx++;
571	}
572
573	xa_for_each(&devlink->ports, port_index, port) {
574		err = devlink_nl_cmd_region_get_port_dumpit(msg, cb, port, &idx,
575							    state->idx, flags);
576		if (err) {
577			state->idx = idx;
578			return err;
579		}
580	}
581
582	return 0;
583}
584
585int devlink_nl_region_get_dumpit(struct sk_buff *skb,
586				 struct netlink_callback *cb)
587{
588	return devlink_nl_dumpit(skb, cb, devlink_nl_region_get_dump_one);
589}
590
591int devlink_nl_cmd_region_del(struct sk_buff *skb, struct genl_info *info)
592{
593	struct devlink *devlink = info->user_ptr[0];
594	struct devlink_snapshot *snapshot;
595	struct devlink_port *port = NULL;
596	struct devlink_region *region;
597	const char *region_name;
598	unsigned int index;
599	u32 snapshot_id;
600
601	if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME) ||
602	    GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_SNAPSHOT_ID))
603		return -EINVAL;
604
605	region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
606	snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
607
608	if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
609		index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
610
611		port = devlink_port_get_by_index(devlink, index);
612		if (!port)
613			return -ENODEV;
614	}
615
616	if (port)
617		region = devlink_port_region_get_by_name(port, region_name);
618	else
619		region = devlink_region_get_by_name(devlink, region_name);
620
621	if (!region)
622		return -EINVAL;
623
624	mutex_lock(&region->snapshot_lock);
625	snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
626	if (!snapshot) {
627		mutex_unlock(&region->snapshot_lock);
628		return -EINVAL;
629	}
630
631	devlink_region_snapshot_del(region, snapshot);
632	mutex_unlock(&region->snapshot_lock);
633	return 0;
634}
635
636int devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info)
637{
638	struct devlink *devlink = info->user_ptr[0];
639	struct devlink_snapshot *snapshot;
640	struct devlink_port *port = NULL;
641	struct nlattr *snapshot_id_attr;
642	struct devlink_region *region;
643	const char *region_name;
644	unsigned int index;
645	u32 snapshot_id;
646	u8 *data;
647	int err;
648
649	if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME)) {
650		NL_SET_ERR_MSG(info->extack, "No region name provided");
651		return -EINVAL;
652	}
653
654	region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
655
656	if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
657		index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
658
659		port = devlink_port_get_by_index(devlink, index);
660		if (!port)
661			return -ENODEV;
662	}
663
664	if (port)
665		region = devlink_port_region_get_by_name(port, region_name);
666	else
667		region = devlink_region_get_by_name(devlink, region_name);
668
669	if (!region) {
670		NL_SET_ERR_MSG(info->extack, "The requested region does not exist");
671		return -EINVAL;
672	}
673
674	if (!region->ops->snapshot) {
675		NL_SET_ERR_MSG(info->extack, "The requested region does not support taking an immediate snapshot");
676		return -EOPNOTSUPP;
677	}
678
679	mutex_lock(&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(snapshot_id_attr);
690
691		if (devlink_region_snapshot_get_by_id(region, snapshot_id)) {
692			NL_SET_ERR_MSG(info->extack, "The requested snapshot id is already in use");
693			err = -EEXIST;
694			goto unlock;
695		}
696
697		err = __devlink_snapshot_id_insert(devlink, snapshot_id);
698		if (err)
699			goto unlock;
700	} else {
701		err = __devlink_region_snapshot_id_get(devlink, &snapshot_id);
702		if (err) {
703			NL_SET_ERR_MSG(info->extack, "Failed to allocate a new snapshot id");
704			goto unlock;
705		}
706	}
707
708	if (port)
709		err = region->port_ops->snapshot(port, region->port_ops,
710						 info->extack, &data);
711	else
712		err = region->ops->snapshot(devlink, region->ops,
713					    info->extack, &data);
714	if (err)
715		goto err_snapshot_capture;
716
717	err = __devlink_region_snapshot_create(region, data, snapshot_id);
718	if (err)
719		goto err_snapshot_create;
720
721	if (!snapshot_id_attr) {
722		struct sk_buff *msg;
723
724		snapshot = devlink_region_snapshot_get_by_id(region,
725							     snapshot_id);
726		if (WARN_ON(!snapshot)) {
727			err = -EINVAL;
728			goto unlock;
729		}
730
731		msg = devlink_nl_region_notify_build(region, snapshot,
732						     DEVLINK_CMD_REGION_NEW,
733						     info->snd_portid,
734						     info->snd_seq);
735		err = PTR_ERR_OR_ZERO(msg);
736		if (err)
737			goto err_notify;
738
739		err = genlmsg_reply(msg, info);
740		if (err)
741			goto err_notify;
742	}
743
744	mutex_unlock(&region->snapshot_lock);
745	return 0;
746
747err_snapshot_create:
748	region->ops->destructor(data);
749err_snapshot_capture:
750	__devlink_snapshot_id_decrement(devlink, snapshot_id);
751	mutex_unlock(&region->snapshot_lock);
752	return err;
753
754err_notify:
755	devlink_region_snapshot_del(region, snapshot);
756unlock:
757	mutex_unlock(&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(msg, DEVLINK_ATTR_REGION_CHUNK);
769	if (!chunk_attr)
770		return -EINVAL;
771
772	err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk);
773	if (err)
774		goto nla_put_failure;
775
776	err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr,
777				DEVLINK_ATTR_PAD);
778	if (err)
779		goto nla_put_failure;
780
781	nla_nest_end(msg, chunk_attr);
782	return 0;
783
784nla_put_failure:
785	nla_nest_cancel(msg, 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(skb, data, data_size, curr_offset);
822		if (err)
823			break;
824
825		curr_offset += data_size;
826	}
827	*new_offset = curr_offset;
828
829	kfree(data);
830
831	return err;
832}
833
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_cmd_region_read_dumpit(struct sk_buff *skb,
867				      struct netlink_callback *cb)
868{
869	const struct genl_dumpit_info *info = genl_dumpit_info(cb);
870	struct devlink_nl_dump_state *state = devlink_dump_state(cb);
871	struct nlattr *chunks_attr, *region_attr, *snapshot_attr;
872	u64 ret_offset, start_offset, end_offset = U64_MAX;
873	struct nlattr **attrs = info->info.attrs;
874	struct devlink_port *port = NULL;
875	devlink_chunk_fill_t *region_cb;
876	struct devlink_region *region;
877	const char *region_name;
878	struct devlink *devlink;
879	unsigned int index;
880	void *region_cb_priv;
881	void *hdr;
882	int err;
883
884	start_offset = state->start_offset;
885
886	devlink = devlink_get_from_attrs_lock(sock_net(cb->skb->sk), attrs);
887	if (IS_ERR(devlink))
888		return PTR_ERR(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(attrs[DEVLINK_ATTR_PORT_INDEX]);
898
899		port = devlink_port_get_by_index(devlink, 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(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(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(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(snapshot_attr);
950		snapshot = devlink_region_snapshot_get_by_id(region, 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(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
965
966		end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
967		end_offset += nla_get_u64(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, cb->nlh->nlmsg_seq,
980			  &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
981			  DEVLINK_CMD_REGION_READ);
982	if (!hdr) {
983		err = -EMSGSIZE;
984		goto out_unlock;
985	}
986
987	err = devlink_nl_put_handle(skb, devlink);
988	if (err)
989		goto nla_put_failure;
990
991	if (region->port) {
992		err = nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX,
993				  region->port->index);
994		if (err)
995			goto nla_put_failure;
996	}
997
998	err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
999	if (err)
1000		goto nla_put_failure;
1001
1002	chunks_attr = nla_nest_start_noflag(skb, 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, region_cb, region_cb_priv,
1009					  start_offset, end_offset, &ret_offset,
1010					  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, 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(-EINVAL);
1056
1057	if (devlink_region_get_by_name(devlink, ops->name))
1058		return ERR_PTR(-EEXIST);
1059
1060	region = kzalloc(sizeof(*region), GFP_KERNEL);
1061	if (!region)
1062		return ERR_PTR(-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(&region->snapshot_list);
1069	mutex_init(&region->snapshot_lock);
1070	list_add_tail(&region->list, &devlink->region_list);
1071	devlink_nl_region_notify(region, NULL, 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(-EINVAL);
1125
1126	devl_lock(devlink);
1127
1128	if (devlink_port_region_get_by_name(port, ops->name)) {
1129		err = -EEXIST;
1130		goto unlock;
1131	}
1132
1133	region = kzalloc(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(&region->snapshot_list);
1145	mutex_init(&region->snapshot_lock);
1146	list_add_tail(&region->list, &port->region_list);
1147	devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
1148
1149	devl_unlock(devlink);
1150	return region;
1151
1152unlock:
1153	devl_unlock(devlink);
1154	return ERR_PTR(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(&region->snapshot_lock);
1175
1176	list_del(&region->list);
1177	mutex_destroy(&region->snapshot_lock);
1178
1179	devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
1180	kfree(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(&region->snapshot_lock);
1258	return err;
1259}
1260EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);
1261