1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * net/core/devlink.c - Network physical/parent device Netlink interface
4  *
5  * Heavily inspired by net/wireless/
6  * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
7  * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
8  */
9 
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/types.h>
13 #include <linux/slab.h>
14 #include <linux/gfp.h>
15 #include <linux/device.h>
16 #include <linux/list.h>
17 #include <linux/netdevice.h>
18 #include <linux/spinlock.h>
19 #include <linux/refcount.h>
20 #include <linux/workqueue.h>
21 #include <linux/u64_stats_sync.h>
22 #include <linux/timekeeping.h>
23 #include <rdma/ib_verbs.h>
24 #include <net/netlink.h>
25 #include <net/genetlink.h>
26 #include <net/rtnetlink.h>
27 #include <net/net_namespace.h>
28 #include <net/sock.h>
29 #include <net/devlink.h>
30 #include <net/drop_monitor.h>
31 #define CREATE_TRACE_POINTS
32 #include <trace/events/devlink.h>
33 
34 static struct devlink_dpipe_field devlink_dpipe_fields_ethernet[] = {
35 	{
36 		.name = "destination mac",
37 		.id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC,
38 		.bitwidth = 48,
39 	},
40 };
41 
42 struct devlink_dpipe_header devlink_dpipe_header_ethernet = {
43 	.name = "ethernet",
44 	.id = DEVLINK_DPIPE_HEADER_ETHERNET,
45 	.fields = devlink_dpipe_fields_ethernet,
46 	.fields_count = ARRAY_SIZE(devlink_dpipe_fields_ethernet),
47 	.global = true,
48 };
49 EXPORT_SYMBOL(devlink_dpipe_header_ethernet);
50 
51 static struct devlink_dpipe_field devlink_dpipe_fields_ipv4[] = {
52 	{
53 		.name = "destination ip",
54 		.id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP,
55 		.bitwidth = 32,
56 	},
57 };
58 
59 struct devlink_dpipe_header devlink_dpipe_header_ipv4 = {
60 	.name = "ipv4",
61 	.id = DEVLINK_DPIPE_HEADER_IPV4,
62 	.fields = devlink_dpipe_fields_ipv4,
63 	.fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv4),
64 	.global = true,
65 };
66 EXPORT_SYMBOL(devlink_dpipe_header_ipv4);
67 
68 static struct devlink_dpipe_field devlink_dpipe_fields_ipv6[] = {
69 	{
70 		.name = "destination ip",
71 		.id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP,
72 		.bitwidth = 128,
73 	},
74 };
75 
76 struct devlink_dpipe_header devlink_dpipe_header_ipv6 = {
77 	.name = "ipv6",
78 	.id = DEVLINK_DPIPE_HEADER_IPV6,
79 	.fields = devlink_dpipe_fields_ipv6,
80 	.fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv6),
81 	.global = true,
82 };
83 EXPORT_SYMBOL(devlink_dpipe_header_ipv6);
84 
85 EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg);
86 EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwerr);
87 
88 static LIST_HEAD(devlink_list);
89 
90 /* devlink_mutex
91  *
92  * An overall lock guarding every operation coming from userspace.
93  * It also guards devlink devices list and it is taken when
94  * driver registers/unregisters it.
95  */
96 static DEFINE_MUTEX(devlink_mutex);
97 
devlink_net(const struct devlink * devlink)98 static struct net *devlink_net(const struct devlink *devlink)
99 {
100 	return read_pnet(&devlink->_net);
101 }
102 
devlink_net_set(struct devlink * devlink,struct net * net)103 static void devlink_net_set(struct devlink *devlink, struct net *net)
104 {
105 	write_pnet(&devlink->_net, net);
106 }
107 
devlink_get_from_attrs(struct net * net,struct nlattr ** attrs)108 static struct devlink *devlink_get_from_attrs(struct net *net,
109 					      struct nlattr **attrs)
110 {
111 	struct devlink *devlink;
112 	char *busname;
113 	char *devname;
114 
115 	if (!attrs[DEVLINK_ATTR_BUS_NAME] || !attrs[DEVLINK_ATTR_DEV_NAME])
116 		return ERR_PTR(-EINVAL);
117 
118 	busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]);
119 	devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
120 
121 	lockdep_assert_held(&devlink_mutex);
122 
123 	list_for_each_entry(devlink, &devlink_list, list) {
124 		if (strcmp(devlink->dev->bus->name, busname) == 0 &&
125 		    strcmp(dev_name(devlink->dev), devname) == 0 &&
126 		    net_eq(devlink_net(devlink), net))
127 			return devlink;
128 	}
129 
130 	return ERR_PTR(-ENODEV);
131 }
132 
devlink_get_from_info(struct genl_info * info)133 static struct devlink *devlink_get_from_info(struct genl_info *info)
134 {
135 	return devlink_get_from_attrs(genl_info_net(info), info->attrs);
136 }
137 
devlink_port_get_by_index(struct devlink * devlink,unsigned int port_index)138 static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink,
139 						      unsigned int port_index)
140 {
141 	struct devlink_port *devlink_port;
142 
143 	list_for_each_entry(devlink_port, &devlink->port_list, list) {
144 		if (devlink_port->index == port_index)
145 			return devlink_port;
146 	}
147 	return NULL;
148 }
149 
devlink_port_index_exists(struct devlink * devlink,unsigned int port_index)150 static bool devlink_port_index_exists(struct devlink *devlink,
151 				      unsigned int port_index)
152 {
153 	return devlink_port_get_by_index(devlink, port_index);
154 }
155 
devlink_port_get_from_attrs(struct devlink * devlink,struct nlattr ** attrs)156 static struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink,
157 							struct nlattr **attrs)
158 {
159 	if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
160 		u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
161 		struct devlink_port *devlink_port;
162 
163 		devlink_port = devlink_port_get_by_index(devlink, port_index);
164 		if (!devlink_port)
165 			return ERR_PTR(-ENODEV);
166 		return devlink_port;
167 	}
168 	return ERR_PTR(-EINVAL);
169 }
170 
devlink_port_get_from_info(struct devlink * devlink,struct genl_info * info)171 static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink,
172 						       struct genl_info *info)
173 {
174 	return devlink_port_get_from_attrs(devlink, info->attrs);
175 }
176 
177 struct devlink_sb {
178 	struct list_head list;
179 	unsigned int index;
180 	u32 size;
181 	u16 ingress_pools_count;
182 	u16 egress_pools_count;
183 	u16 ingress_tc_count;
184 	u16 egress_tc_count;
185 };
186 
devlink_sb_pool_count(struct devlink_sb * devlink_sb)187 static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb)
188 {
189 	return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count;
190 }
191 
devlink_sb_get_by_index(struct devlink * devlink,unsigned int sb_index)192 static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink,
193 						  unsigned int sb_index)
194 {
195 	struct devlink_sb *devlink_sb;
196 
197 	list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
198 		if (devlink_sb->index == sb_index)
199 			return devlink_sb;
200 	}
201 	return NULL;
202 }
203 
devlink_sb_index_exists(struct devlink * devlink,unsigned int sb_index)204 static bool devlink_sb_index_exists(struct devlink *devlink,
205 				    unsigned int sb_index)
206 {
207 	return devlink_sb_get_by_index(devlink, sb_index);
208 }
209 
devlink_sb_get_from_attrs(struct devlink * devlink,struct nlattr ** attrs)210 static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink,
211 						    struct nlattr **attrs)
212 {
213 	if (attrs[DEVLINK_ATTR_SB_INDEX]) {
214 		u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]);
215 		struct devlink_sb *devlink_sb;
216 
217 		devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
218 		if (!devlink_sb)
219 			return ERR_PTR(-ENODEV);
220 		return devlink_sb;
221 	}
222 	return ERR_PTR(-EINVAL);
223 }
224 
devlink_sb_get_from_info(struct devlink * devlink,struct genl_info * info)225 static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink,
226 						   struct genl_info *info)
227 {
228 	return devlink_sb_get_from_attrs(devlink, info->attrs);
229 }
230 
devlink_sb_pool_index_get_from_attrs(struct devlink_sb * devlink_sb,struct nlattr ** attrs,u16 * p_pool_index)231 static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb,
232 						struct nlattr **attrs,
233 						u16 *p_pool_index)
234 {
235 	u16 val;
236 
237 	if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX])
238 		return -EINVAL;
239 
240 	val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]);
241 	if (val >= devlink_sb_pool_count(devlink_sb))
242 		return -EINVAL;
243 	*p_pool_index = val;
244 	return 0;
245 }
246 
devlink_sb_pool_index_get_from_info(struct devlink_sb * devlink_sb,struct genl_info * info,u16 * p_pool_index)247 static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb,
248 					       struct genl_info *info,
249 					       u16 *p_pool_index)
250 {
251 	return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs,
252 						    p_pool_index);
253 }
254 
255 static int
devlink_sb_pool_type_get_from_attrs(struct nlattr ** attrs,enum devlink_sb_pool_type * p_pool_type)256 devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs,
257 				    enum devlink_sb_pool_type *p_pool_type)
258 {
259 	u8 val;
260 
261 	if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE])
262 		return -EINVAL;
263 
264 	val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]);
265 	if (val != DEVLINK_SB_POOL_TYPE_INGRESS &&
266 	    val != DEVLINK_SB_POOL_TYPE_EGRESS)
267 		return -EINVAL;
268 	*p_pool_type = val;
269 	return 0;
270 }
271 
272 static int
devlink_sb_pool_type_get_from_info(struct genl_info * info,enum devlink_sb_pool_type * p_pool_type)273 devlink_sb_pool_type_get_from_info(struct genl_info *info,
274 				   enum devlink_sb_pool_type *p_pool_type)
275 {
276 	return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type);
277 }
278 
279 static int
devlink_sb_th_type_get_from_attrs(struct nlattr ** attrs,enum devlink_sb_threshold_type * p_th_type)280 devlink_sb_th_type_get_from_attrs(struct nlattr **attrs,
281 				  enum devlink_sb_threshold_type *p_th_type)
282 {
283 	u8 val;
284 
285 	if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE])
286 		return -EINVAL;
287 
288 	val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]);
289 	if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC &&
290 	    val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC)
291 		return -EINVAL;
292 	*p_th_type = val;
293 	return 0;
294 }
295 
296 static int
devlink_sb_th_type_get_from_info(struct genl_info * info,enum devlink_sb_threshold_type * p_th_type)297 devlink_sb_th_type_get_from_info(struct genl_info *info,
298 				 enum devlink_sb_threshold_type *p_th_type)
299 {
300 	return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type);
301 }
302 
303 static int
devlink_sb_tc_index_get_from_attrs(struct devlink_sb * devlink_sb,struct nlattr ** attrs,enum devlink_sb_pool_type pool_type,u16 * p_tc_index)304 devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb,
305 				   struct nlattr **attrs,
306 				   enum devlink_sb_pool_type pool_type,
307 				   u16 *p_tc_index)
308 {
309 	u16 val;
310 
311 	if (!attrs[DEVLINK_ATTR_SB_TC_INDEX])
312 		return -EINVAL;
313 
314 	val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]);
315 	if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS &&
316 	    val >= devlink_sb->ingress_tc_count)
317 		return -EINVAL;
318 	if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS &&
319 	    val >= devlink_sb->egress_tc_count)
320 		return -EINVAL;
321 	*p_tc_index = val;
322 	return 0;
323 }
324 
325 static int
devlink_sb_tc_index_get_from_info(struct devlink_sb * devlink_sb,struct genl_info * info,enum devlink_sb_pool_type pool_type,u16 * p_tc_index)326 devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb,
327 				  struct genl_info *info,
328 				  enum devlink_sb_pool_type pool_type,
329 				  u16 *p_tc_index)
330 {
331 	return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs,
332 						  pool_type, p_tc_index);
333 }
334 
335 struct devlink_region {
336 	struct devlink *devlink;
337 	struct list_head list;
338 	const char *name;
339 	struct list_head snapshot_list;
340 	u32 max_snapshots;
341 	u32 cur_snapshots;
342 	u64 size;
343 };
344 
345 struct devlink_snapshot {
346 	struct list_head list;
347 	struct devlink_region *region;
348 	devlink_snapshot_data_dest_t *data_destructor;
349 	u8 *data;
350 	u32 id;
351 };
352 
353 static struct devlink_region *
devlink_region_get_by_name(struct devlink * devlink,const char * region_name)354 devlink_region_get_by_name(struct devlink *devlink, const char *region_name)
355 {
356 	struct devlink_region *region;
357 
358 	list_for_each_entry(region, &devlink->region_list, list)
359 		if (!strcmp(region->name, region_name))
360 			return region;
361 
362 	return NULL;
363 }
364 
365 static struct devlink_snapshot *
devlink_region_snapshot_get_by_id(struct devlink_region * region,u32 id)366 devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id)
367 {
368 	struct devlink_snapshot *snapshot;
369 
370 	list_for_each_entry(snapshot, &region->snapshot_list, list)
371 		if (snapshot->id == id)
372 			return snapshot;
373 
374 	return NULL;
375 }
376 
377 #define DEVLINK_NL_FLAG_NEED_DEVLINK	BIT(0)
378 #define DEVLINK_NL_FLAG_NEED_PORT	BIT(1)
379 #define DEVLINK_NL_FLAG_NEED_SB		BIT(2)
380 
381 /* The per devlink instance lock is taken by default in the pre-doit
382  * operation, yet several commands do not require this. The global
383  * devlink lock is taken and protects from disruption by user-calls.
384  */
385 #define DEVLINK_NL_FLAG_NO_LOCK		BIT(3)
386 
devlink_nl_pre_doit(const struct genl_ops * ops,struct sk_buff * skb,struct genl_info * info)387 static int devlink_nl_pre_doit(const struct genl_ops *ops,
388 			       struct sk_buff *skb, struct genl_info *info)
389 {
390 	struct devlink *devlink;
391 	int err;
392 
393 	mutex_lock(&devlink_mutex);
394 	devlink = devlink_get_from_info(info);
395 	if (IS_ERR(devlink)) {
396 		mutex_unlock(&devlink_mutex);
397 		return PTR_ERR(devlink);
398 	}
399 	if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
400 		mutex_lock(&devlink->lock);
401 	if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) {
402 		info->user_ptr[0] = devlink;
403 	} else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) {
404 		struct devlink_port *devlink_port;
405 
406 		devlink_port = devlink_port_get_from_info(devlink, info);
407 		if (IS_ERR(devlink_port)) {
408 			err = PTR_ERR(devlink_port);
409 			goto unlock;
410 		}
411 		info->user_ptr[0] = devlink_port;
412 	}
413 	if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) {
414 		struct devlink_sb *devlink_sb;
415 
416 		devlink_sb = devlink_sb_get_from_info(devlink, info);
417 		if (IS_ERR(devlink_sb)) {
418 			err = PTR_ERR(devlink_sb);
419 			goto unlock;
420 		}
421 		info->user_ptr[1] = devlink_sb;
422 	}
423 	return 0;
424 
425 unlock:
426 	if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
427 		mutex_unlock(&devlink->lock);
428 	mutex_unlock(&devlink_mutex);
429 	return err;
430 }
431 
devlink_nl_post_doit(const struct genl_ops * ops,struct sk_buff * skb,struct genl_info * info)432 static void devlink_nl_post_doit(const struct genl_ops *ops,
433 				 struct sk_buff *skb, struct genl_info *info)
434 {
435 	struct devlink *devlink;
436 
437 	devlink = devlink_get_from_info(info);
438 	if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
439 		mutex_unlock(&devlink->lock);
440 	mutex_unlock(&devlink_mutex);
441 }
442 
443 static struct genl_family devlink_nl_family;
444 
445 enum devlink_multicast_groups {
446 	DEVLINK_MCGRP_CONFIG,
447 };
448 
449 static const struct genl_multicast_group devlink_nl_mcgrps[] = {
450 	[DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME },
451 };
452 
devlink_nl_put_handle(struct sk_buff * msg,struct devlink * devlink)453 static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
454 {
455 	if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
456 		return -EMSGSIZE;
457 	if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
458 		return -EMSGSIZE;
459 	return 0;
460 }
461 
devlink_nl_fill(struct sk_buff * msg,struct devlink * devlink,enum devlink_command cmd,u32 portid,u32 seq,int flags)462 static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
463 			   enum devlink_command cmd, u32 portid,
464 			   u32 seq, int flags)
465 {
466 	void *hdr;
467 
468 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
469 	if (!hdr)
470 		return -EMSGSIZE;
471 
472 	if (devlink_nl_put_handle(msg, devlink))
473 		goto nla_put_failure;
474 	if (nla_put_u8(msg, DEVLINK_ATTR_RELOAD_FAILED, devlink->reload_failed))
475 		goto nla_put_failure;
476 
477 	genlmsg_end(msg, hdr);
478 	return 0;
479 
480 nla_put_failure:
481 	genlmsg_cancel(msg, hdr);
482 	return -EMSGSIZE;
483 }
484 
devlink_notify(struct devlink * devlink,enum devlink_command cmd)485 static void devlink_notify(struct devlink *devlink, enum devlink_command cmd)
486 {
487 	struct sk_buff *msg;
488 	int err;
489 
490 	WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL);
491 
492 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
493 	if (!msg)
494 		return;
495 
496 	err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0);
497 	if (err) {
498 		nlmsg_free(msg);
499 		return;
500 	}
501 
502 	genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
503 				msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
504 }
505 
devlink_nl_port_attrs_put(struct sk_buff * msg,struct devlink_port * devlink_port)506 static int devlink_nl_port_attrs_put(struct sk_buff *msg,
507 				     struct devlink_port *devlink_port)
508 {
509 	struct devlink_port_attrs *attrs = &devlink_port->attrs;
510 
511 	if (!attrs->set)
512 		return 0;
513 	if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour))
514 		return -EMSGSIZE;
515 	switch (devlink_port->attrs.flavour) {
516 	case DEVLINK_PORT_FLAVOUR_PCI_PF:
517 		if (nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER,
518 				attrs->pci_pf.pf))
519 			return -EMSGSIZE;
520 		break;
521 	case DEVLINK_PORT_FLAVOUR_PCI_VF:
522 		if (nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER,
523 				attrs->pci_vf.pf) ||
524 		    nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_VF_NUMBER,
525 				attrs->pci_vf.vf))
526 			return -EMSGSIZE;
527 		break;
528 	case DEVLINK_PORT_FLAVOUR_PHYSICAL:
529 	case DEVLINK_PORT_FLAVOUR_CPU:
530 	case DEVLINK_PORT_FLAVOUR_DSA:
531 		if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER,
532 				attrs->phys.port_number))
533 			return -EMSGSIZE;
534 		if (!attrs->split)
535 			return 0;
536 		if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP,
537 				attrs->phys.port_number))
538 			return -EMSGSIZE;
539 		if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER,
540 				attrs->phys.split_subport_number))
541 			return -EMSGSIZE;
542 		break;
543 	default:
544 		break;
545 	}
546 	return 0;
547 }
548 
devlink_nl_port_fill(struct sk_buff * msg,struct devlink * devlink,struct devlink_port * devlink_port,enum devlink_command cmd,u32 portid,u32 seq,int flags)549 static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
550 				struct devlink_port *devlink_port,
551 				enum devlink_command cmd, u32 portid,
552 				u32 seq, int flags)
553 {
554 	void *hdr;
555 
556 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
557 	if (!hdr)
558 		return -EMSGSIZE;
559 
560 	if (devlink_nl_put_handle(msg, devlink))
561 		goto nla_put_failure;
562 	if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
563 		goto nla_put_failure;
564 
565 	spin_lock_bh(&devlink_port->type_lock);
566 	if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type))
567 		goto nla_put_failure_type_locked;
568 	if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET &&
569 	    nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE,
570 			devlink_port->desired_type))
571 		goto nla_put_failure_type_locked;
572 	if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) {
573 		struct net_device *netdev = devlink_port->type_dev;
574 
575 		if (netdev &&
576 		    (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX,
577 				 netdev->ifindex) ||
578 		     nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME,
579 				    netdev->name)))
580 			goto nla_put_failure_type_locked;
581 	}
582 	if (devlink_port->type == DEVLINK_PORT_TYPE_IB) {
583 		struct ib_device *ibdev = devlink_port->type_dev;
584 
585 		if (ibdev &&
586 		    nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME,
587 				   ibdev->name))
588 			goto nla_put_failure_type_locked;
589 	}
590 	spin_unlock_bh(&devlink_port->type_lock);
591 	if (devlink_nl_port_attrs_put(msg, devlink_port))
592 		goto nla_put_failure;
593 
594 	genlmsg_end(msg, hdr);
595 	return 0;
596 
597 nla_put_failure_type_locked:
598 	spin_unlock_bh(&devlink_port->type_lock);
599 nla_put_failure:
600 	genlmsg_cancel(msg, hdr);
601 	return -EMSGSIZE;
602 }
603 
devlink_port_notify(struct devlink_port * devlink_port,enum devlink_command cmd)604 static void devlink_port_notify(struct devlink_port *devlink_port,
605 				enum devlink_command cmd)
606 {
607 	struct devlink *devlink = devlink_port->devlink;
608 	struct sk_buff *msg;
609 	int err;
610 
611 	if (!devlink_port->registered)
612 		return;
613 
614 	WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL);
615 
616 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
617 	if (!msg)
618 		return;
619 
620 	err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0);
621 	if (err) {
622 		nlmsg_free(msg);
623 		return;
624 	}
625 
626 	genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
627 				msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
628 }
629 
devlink_nl_cmd_get_doit(struct sk_buff * skb,struct genl_info * info)630 static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info)
631 {
632 	struct devlink *devlink = info->user_ptr[0];
633 	struct sk_buff *msg;
634 	int err;
635 
636 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
637 	if (!msg)
638 		return -ENOMEM;
639 
640 	err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
641 			      info->snd_portid, info->snd_seq, 0);
642 	if (err) {
643 		nlmsg_free(msg);
644 		return err;
645 	}
646 
647 	return genlmsg_reply(msg, info);
648 }
649 
devlink_nl_cmd_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)650 static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg,
651 				     struct netlink_callback *cb)
652 {
653 	struct devlink *devlink;
654 	int start = cb->args[0];
655 	int idx = 0;
656 	int err;
657 
658 	mutex_lock(&devlink_mutex);
659 	list_for_each_entry(devlink, &devlink_list, list) {
660 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
661 			continue;
662 		if (idx < start) {
663 			idx++;
664 			continue;
665 		}
666 		err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
667 				      NETLINK_CB(cb->skb).portid,
668 				      cb->nlh->nlmsg_seq, NLM_F_MULTI);
669 		if (err)
670 			goto out;
671 		idx++;
672 	}
673 out:
674 	mutex_unlock(&devlink_mutex);
675 
676 	cb->args[0] = idx;
677 	return msg->len;
678 }
679 
devlink_nl_cmd_port_get_doit(struct sk_buff * skb,struct genl_info * info)680 static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb,
681 					struct genl_info *info)
682 {
683 	struct devlink_port *devlink_port = info->user_ptr[0];
684 	struct devlink *devlink = devlink_port->devlink;
685 	struct sk_buff *msg;
686 	int err;
687 
688 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
689 	if (!msg)
690 		return -ENOMEM;
691 
692 	err = devlink_nl_port_fill(msg, devlink, devlink_port,
693 				   DEVLINK_CMD_PORT_NEW,
694 				   info->snd_portid, info->snd_seq, 0);
695 	if (err) {
696 		nlmsg_free(msg);
697 		return err;
698 	}
699 
700 	return genlmsg_reply(msg, info);
701 }
702 
devlink_nl_cmd_port_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)703 static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg,
704 					  struct netlink_callback *cb)
705 {
706 	struct devlink *devlink;
707 	struct devlink_port *devlink_port;
708 	int start = cb->args[0];
709 	int idx = 0;
710 	int err;
711 
712 	mutex_lock(&devlink_mutex);
713 	list_for_each_entry(devlink, &devlink_list, list) {
714 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
715 			continue;
716 		mutex_lock(&devlink->lock);
717 		list_for_each_entry(devlink_port, &devlink->port_list, list) {
718 			if (idx < start) {
719 				idx++;
720 				continue;
721 			}
722 			err = devlink_nl_port_fill(msg, devlink, devlink_port,
723 						   DEVLINK_CMD_NEW,
724 						   NETLINK_CB(cb->skb).portid,
725 						   cb->nlh->nlmsg_seq,
726 						   NLM_F_MULTI);
727 			if (err) {
728 				mutex_unlock(&devlink->lock);
729 				goto out;
730 			}
731 			idx++;
732 		}
733 		mutex_unlock(&devlink->lock);
734 	}
735 out:
736 	mutex_unlock(&devlink_mutex);
737 
738 	cb->args[0] = idx;
739 	return msg->len;
740 }
741 
devlink_port_type_set(struct devlink * devlink,struct devlink_port * devlink_port,enum devlink_port_type port_type)742 static int devlink_port_type_set(struct devlink *devlink,
743 				 struct devlink_port *devlink_port,
744 				 enum devlink_port_type port_type)
745 
746 {
747 	int err;
748 
749 	if (devlink->ops->port_type_set) {
750 		if (port_type == DEVLINK_PORT_TYPE_NOTSET)
751 			return -EINVAL;
752 		if (port_type == devlink_port->type)
753 			return 0;
754 		err = devlink->ops->port_type_set(devlink_port, port_type);
755 		if (err)
756 			return err;
757 		devlink_port->desired_type = port_type;
758 		devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
759 		return 0;
760 	}
761 	return -EOPNOTSUPP;
762 }
763 
devlink_nl_cmd_port_set_doit(struct sk_buff * skb,struct genl_info * info)764 static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb,
765 					struct genl_info *info)
766 {
767 	struct devlink_port *devlink_port = info->user_ptr[0];
768 	struct devlink *devlink = devlink_port->devlink;
769 	int err;
770 
771 	if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) {
772 		enum devlink_port_type port_type;
773 
774 		port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]);
775 		err = devlink_port_type_set(devlink, devlink_port, port_type);
776 		if (err)
777 			return err;
778 	}
779 	return 0;
780 }
781 
devlink_port_split(struct devlink * devlink,u32 port_index,u32 count,struct netlink_ext_ack * extack)782 static int devlink_port_split(struct devlink *devlink, u32 port_index,
783 			      u32 count, struct netlink_ext_ack *extack)
784 
785 {
786 	if (devlink->ops->port_split)
787 		return devlink->ops->port_split(devlink, port_index, count,
788 						extack);
789 	return -EOPNOTSUPP;
790 }
791 
devlink_nl_cmd_port_split_doit(struct sk_buff * skb,struct genl_info * info)792 static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb,
793 					  struct genl_info *info)
794 {
795 	struct devlink *devlink = info->user_ptr[0];
796 	u32 port_index;
797 	u32 count;
798 
799 	if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] ||
800 	    !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT])
801 		return -EINVAL;
802 
803 	port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
804 	count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]);
805 	return devlink_port_split(devlink, port_index, count, info->extack);
806 }
807 
devlink_port_unsplit(struct devlink * devlink,u32 port_index,struct netlink_ext_ack * extack)808 static int devlink_port_unsplit(struct devlink *devlink, u32 port_index,
809 				struct netlink_ext_ack *extack)
810 
811 {
812 	if (devlink->ops->port_unsplit)
813 		return devlink->ops->port_unsplit(devlink, port_index, extack);
814 	return -EOPNOTSUPP;
815 }
816 
devlink_nl_cmd_port_unsplit_doit(struct sk_buff * skb,struct genl_info * info)817 static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb,
818 					    struct genl_info *info)
819 {
820 	struct devlink *devlink = info->user_ptr[0];
821 	u32 port_index;
822 
823 	if (!info->attrs[DEVLINK_ATTR_PORT_INDEX])
824 		return -EINVAL;
825 
826 	port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
827 	return devlink_port_unsplit(devlink, port_index, info->extack);
828 }
829 
devlink_nl_sb_fill(struct sk_buff * msg,struct devlink * devlink,struct devlink_sb * devlink_sb,enum devlink_command cmd,u32 portid,u32 seq,int flags)830 static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink,
831 			      struct devlink_sb *devlink_sb,
832 			      enum devlink_command cmd, u32 portid,
833 			      u32 seq, int flags)
834 {
835 	void *hdr;
836 
837 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
838 	if (!hdr)
839 		return -EMSGSIZE;
840 
841 	if (devlink_nl_put_handle(msg, devlink))
842 		goto nla_put_failure;
843 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
844 		goto nla_put_failure;
845 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size))
846 		goto nla_put_failure;
847 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT,
848 			devlink_sb->ingress_pools_count))
849 		goto nla_put_failure;
850 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT,
851 			devlink_sb->egress_pools_count))
852 		goto nla_put_failure;
853 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT,
854 			devlink_sb->ingress_tc_count))
855 		goto nla_put_failure;
856 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT,
857 			devlink_sb->egress_tc_count))
858 		goto nla_put_failure;
859 
860 	genlmsg_end(msg, hdr);
861 	return 0;
862 
863 nla_put_failure:
864 	genlmsg_cancel(msg, hdr);
865 	return -EMSGSIZE;
866 }
867 
devlink_nl_cmd_sb_get_doit(struct sk_buff * skb,struct genl_info * info)868 static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb,
869 				      struct genl_info *info)
870 {
871 	struct devlink *devlink = info->user_ptr[0];
872 	struct devlink_sb *devlink_sb = info->user_ptr[1];
873 	struct sk_buff *msg;
874 	int err;
875 
876 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
877 	if (!msg)
878 		return -ENOMEM;
879 
880 	err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
881 				 DEVLINK_CMD_SB_NEW,
882 				 info->snd_portid, info->snd_seq, 0);
883 	if (err) {
884 		nlmsg_free(msg);
885 		return err;
886 	}
887 
888 	return genlmsg_reply(msg, info);
889 }
890 
devlink_nl_cmd_sb_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)891 static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg,
892 					struct netlink_callback *cb)
893 {
894 	struct devlink *devlink;
895 	struct devlink_sb *devlink_sb;
896 	int start = cb->args[0];
897 	int idx = 0;
898 	int err;
899 
900 	mutex_lock(&devlink_mutex);
901 	list_for_each_entry(devlink, &devlink_list, list) {
902 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
903 			continue;
904 		mutex_lock(&devlink->lock);
905 		list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
906 			if (idx < start) {
907 				idx++;
908 				continue;
909 			}
910 			err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
911 						 DEVLINK_CMD_SB_NEW,
912 						 NETLINK_CB(cb->skb).portid,
913 						 cb->nlh->nlmsg_seq,
914 						 NLM_F_MULTI);
915 			if (err) {
916 				mutex_unlock(&devlink->lock);
917 				goto out;
918 			}
919 			idx++;
920 		}
921 		mutex_unlock(&devlink->lock);
922 	}
923 out:
924 	mutex_unlock(&devlink_mutex);
925 
926 	cb->args[0] = idx;
927 	return msg->len;
928 }
929 
devlink_nl_sb_pool_fill(struct sk_buff * msg,struct devlink * devlink,struct devlink_sb * devlink_sb,u16 pool_index,enum devlink_command cmd,u32 portid,u32 seq,int flags)930 static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink,
931 				   struct devlink_sb *devlink_sb,
932 				   u16 pool_index, enum devlink_command cmd,
933 				   u32 portid, u32 seq, int flags)
934 {
935 	struct devlink_sb_pool_info pool_info;
936 	void *hdr;
937 	int err;
938 
939 	err = devlink->ops->sb_pool_get(devlink, devlink_sb->index,
940 					pool_index, &pool_info);
941 	if (err)
942 		return err;
943 
944 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
945 	if (!hdr)
946 		return -EMSGSIZE;
947 
948 	if (devlink_nl_put_handle(msg, devlink))
949 		goto nla_put_failure;
950 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
951 		goto nla_put_failure;
952 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
953 		goto nla_put_failure;
954 	if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type))
955 		goto nla_put_failure;
956 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size))
957 		goto nla_put_failure;
958 	if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE,
959 		       pool_info.threshold_type))
960 		goto nla_put_failure;
961 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_CELL_SIZE,
962 			pool_info.cell_size))
963 		goto nla_put_failure;
964 
965 	genlmsg_end(msg, hdr);
966 	return 0;
967 
968 nla_put_failure:
969 	genlmsg_cancel(msg, hdr);
970 	return -EMSGSIZE;
971 }
972 
devlink_nl_cmd_sb_pool_get_doit(struct sk_buff * skb,struct genl_info * info)973 static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb,
974 					   struct genl_info *info)
975 {
976 	struct devlink *devlink = info->user_ptr[0];
977 	struct devlink_sb *devlink_sb = info->user_ptr[1];
978 	struct sk_buff *msg;
979 	u16 pool_index;
980 	int err;
981 
982 	err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
983 						  &pool_index);
984 	if (err)
985 		return err;
986 
987 	if (!devlink->ops->sb_pool_get)
988 		return -EOPNOTSUPP;
989 
990 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
991 	if (!msg)
992 		return -ENOMEM;
993 
994 	err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index,
995 				      DEVLINK_CMD_SB_POOL_NEW,
996 				      info->snd_portid, info->snd_seq, 0);
997 	if (err) {
998 		nlmsg_free(msg);
999 		return err;
1000 	}
1001 
1002 	return genlmsg_reply(msg, info);
1003 }
1004 
__sb_pool_get_dumpit(struct sk_buff * msg,int start,int * p_idx,struct devlink * devlink,struct devlink_sb * devlink_sb,u32 portid,u32 seq)1005 static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
1006 				struct devlink *devlink,
1007 				struct devlink_sb *devlink_sb,
1008 				u32 portid, u32 seq)
1009 {
1010 	u16 pool_count = devlink_sb_pool_count(devlink_sb);
1011 	u16 pool_index;
1012 	int err;
1013 
1014 	for (pool_index = 0; pool_index < pool_count; pool_index++) {
1015 		if (*p_idx < start) {
1016 			(*p_idx)++;
1017 			continue;
1018 		}
1019 		err = devlink_nl_sb_pool_fill(msg, devlink,
1020 					      devlink_sb,
1021 					      pool_index,
1022 					      DEVLINK_CMD_SB_POOL_NEW,
1023 					      portid, seq, NLM_F_MULTI);
1024 		if (err)
1025 			return err;
1026 		(*p_idx)++;
1027 	}
1028 	return 0;
1029 }
1030 
devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)1031 static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg,
1032 					     struct netlink_callback *cb)
1033 {
1034 	struct devlink *devlink;
1035 	struct devlink_sb *devlink_sb;
1036 	int start = cb->args[0];
1037 	int idx = 0;
1038 	int err;
1039 
1040 	mutex_lock(&devlink_mutex);
1041 	list_for_each_entry(devlink, &devlink_list, list) {
1042 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1043 		    !devlink->ops->sb_pool_get)
1044 			continue;
1045 		mutex_lock(&devlink->lock);
1046 		list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1047 			err = __sb_pool_get_dumpit(msg, start, &idx, devlink,
1048 						   devlink_sb,
1049 						   NETLINK_CB(cb->skb).portid,
1050 						   cb->nlh->nlmsg_seq);
1051 			if (err && err != -EOPNOTSUPP) {
1052 				mutex_unlock(&devlink->lock);
1053 				goto out;
1054 			}
1055 		}
1056 		mutex_unlock(&devlink->lock);
1057 	}
1058 out:
1059 	mutex_unlock(&devlink_mutex);
1060 
1061 	cb->args[0] = idx;
1062 	return msg->len;
1063 }
1064 
devlink_sb_pool_set(struct devlink * devlink,unsigned int sb_index,u16 pool_index,u32 size,enum devlink_sb_threshold_type threshold_type,struct netlink_ext_ack * extack)1065 static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index,
1066 			       u16 pool_index, u32 size,
1067 			       enum devlink_sb_threshold_type threshold_type,
1068 			       struct netlink_ext_ack *extack)
1069 
1070 {
1071 	const struct devlink_ops *ops = devlink->ops;
1072 
1073 	if (ops->sb_pool_set)
1074 		return ops->sb_pool_set(devlink, sb_index, pool_index,
1075 					size, threshold_type, extack);
1076 	return -EOPNOTSUPP;
1077 }
1078 
devlink_nl_cmd_sb_pool_set_doit(struct sk_buff * skb,struct genl_info * info)1079 static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb,
1080 					   struct genl_info *info)
1081 {
1082 	struct devlink *devlink = info->user_ptr[0];
1083 	struct devlink_sb *devlink_sb = info->user_ptr[1];
1084 	enum devlink_sb_threshold_type threshold_type;
1085 	u16 pool_index;
1086 	u32 size;
1087 	int err;
1088 
1089 	err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1090 						  &pool_index);
1091 	if (err)
1092 		return err;
1093 
1094 	err = devlink_sb_th_type_get_from_info(info, &threshold_type);
1095 	if (err)
1096 		return err;
1097 
1098 	if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE])
1099 		return -EINVAL;
1100 
1101 	size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]);
1102 	return devlink_sb_pool_set(devlink, devlink_sb->index,
1103 				   pool_index, size, threshold_type,
1104 				   info->extack);
1105 }
1106 
devlink_nl_sb_port_pool_fill(struct sk_buff * msg,struct devlink * devlink,struct devlink_port * devlink_port,struct devlink_sb * devlink_sb,u16 pool_index,enum devlink_command cmd,u32 portid,u32 seq,int flags)1107 static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
1108 					struct devlink *devlink,
1109 					struct devlink_port *devlink_port,
1110 					struct devlink_sb *devlink_sb,
1111 					u16 pool_index,
1112 					enum devlink_command cmd,
1113 					u32 portid, u32 seq, int flags)
1114 {
1115 	const struct devlink_ops *ops = devlink->ops;
1116 	u32 threshold;
1117 	void *hdr;
1118 	int err;
1119 
1120 	err = ops->sb_port_pool_get(devlink_port, devlink_sb->index,
1121 				    pool_index, &threshold);
1122 	if (err)
1123 		return err;
1124 
1125 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1126 	if (!hdr)
1127 		return -EMSGSIZE;
1128 
1129 	if (devlink_nl_put_handle(msg, devlink))
1130 		goto nla_put_failure;
1131 	if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1132 		goto nla_put_failure;
1133 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1134 		goto nla_put_failure;
1135 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
1136 		goto nla_put_failure;
1137 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1138 		goto nla_put_failure;
1139 
1140 	if (ops->sb_occ_port_pool_get) {
1141 		u32 cur;
1142 		u32 max;
1143 
1144 		err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index,
1145 						pool_index, &cur, &max);
1146 		if (err && err != -EOPNOTSUPP)
1147 			return err;
1148 		if (!err) {
1149 			if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
1150 				goto nla_put_failure;
1151 			if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
1152 				goto nla_put_failure;
1153 		}
1154 	}
1155 
1156 	genlmsg_end(msg, hdr);
1157 	return 0;
1158 
1159 nla_put_failure:
1160 	genlmsg_cancel(msg, hdr);
1161 	return -EMSGSIZE;
1162 }
1163 
devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff * skb,struct genl_info * info)1164 static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb,
1165 						struct genl_info *info)
1166 {
1167 	struct devlink_port *devlink_port = info->user_ptr[0];
1168 	struct devlink *devlink = devlink_port->devlink;
1169 	struct devlink_sb *devlink_sb = info->user_ptr[1];
1170 	struct sk_buff *msg;
1171 	u16 pool_index;
1172 	int err;
1173 
1174 	err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1175 						  &pool_index);
1176 	if (err)
1177 		return err;
1178 
1179 	if (!devlink->ops->sb_port_pool_get)
1180 		return -EOPNOTSUPP;
1181 
1182 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1183 	if (!msg)
1184 		return -ENOMEM;
1185 
1186 	err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port,
1187 					   devlink_sb, pool_index,
1188 					   DEVLINK_CMD_SB_PORT_POOL_NEW,
1189 					   info->snd_portid, info->snd_seq, 0);
1190 	if (err) {
1191 		nlmsg_free(msg);
1192 		return err;
1193 	}
1194 
1195 	return genlmsg_reply(msg, info);
1196 }
1197 
__sb_port_pool_get_dumpit(struct sk_buff * msg,int start,int * p_idx,struct devlink * devlink,struct devlink_sb * devlink_sb,u32 portid,u32 seq)1198 static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
1199 				     struct devlink *devlink,
1200 				     struct devlink_sb *devlink_sb,
1201 				     u32 portid, u32 seq)
1202 {
1203 	struct devlink_port *devlink_port;
1204 	u16 pool_count = devlink_sb_pool_count(devlink_sb);
1205 	u16 pool_index;
1206 	int err;
1207 
1208 	list_for_each_entry(devlink_port, &devlink->port_list, list) {
1209 		for (pool_index = 0; pool_index < pool_count; pool_index++) {
1210 			if (*p_idx < start) {
1211 				(*p_idx)++;
1212 				continue;
1213 			}
1214 			err = devlink_nl_sb_port_pool_fill(msg, devlink,
1215 							   devlink_port,
1216 							   devlink_sb,
1217 							   pool_index,
1218 							   DEVLINK_CMD_SB_PORT_POOL_NEW,
1219 							   portid, seq,
1220 							   NLM_F_MULTI);
1221 			if (err)
1222 				return err;
1223 			(*p_idx)++;
1224 		}
1225 	}
1226 	return 0;
1227 }
1228 
devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)1229 static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg,
1230 						  struct netlink_callback *cb)
1231 {
1232 	struct devlink *devlink;
1233 	struct devlink_sb *devlink_sb;
1234 	int start = cb->args[0];
1235 	int idx = 0;
1236 	int err;
1237 
1238 	mutex_lock(&devlink_mutex);
1239 	list_for_each_entry(devlink, &devlink_list, list) {
1240 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1241 		    !devlink->ops->sb_port_pool_get)
1242 			continue;
1243 		mutex_lock(&devlink->lock);
1244 		list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1245 			err = __sb_port_pool_get_dumpit(msg, start, &idx,
1246 							devlink, devlink_sb,
1247 							NETLINK_CB(cb->skb).portid,
1248 							cb->nlh->nlmsg_seq);
1249 			if (err && err != -EOPNOTSUPP) {
1250 				mutex_unlock(&devlink->lock);
1251 				goto out;
1252 			}
1253 		}
1254 		mutex_unlock(&devlink->lock);
1255 	}
1256 out:
1257 	mutex_unlock(&devlink_mutex);
1258 
1259 	cb->args[0] = idx;
1260 	return msg->len;
1261 }
1262 
devlink_sb_port_pool_set(struct devlink_port * devlink_port,unsigned int sb_index,u16 pool_index,u32 threshold,struct netlink_ext_ack * extack)1263 static int devlink_sb_port_pool_set(struct devlink_port *devlink_port,
1264 				    unsigned int sb_index, u16 pool_index,
1265 				    u32 threshold,
1266 				    struct netlink_ext_ack *extack)
1267 
1268 {
1269 	const struct devlink_ops *ops = devlink_port->devlink->ops;
1270 
1271 	if (ops->sb_port_pool_set)
1272 		return ops->sb_port_pool_set(devlink_port, sb_index,
1273 					     pool_index, threshold, extack);
1274 	return -EOPNOTSUPP;
1275 }
1276 
devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff * skb,struct genl_info * info)1277 static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb,
1278 						struct genl_info *info)
1279 {
1280 	struct devlink_port *devlink_port = info->user_ptr[0];
1281 	struct devlink_sb *devlink_sb = info->user_ptr[1];
1282 	u16 pool_index;
1283 	u32 threshold;
1284 	int err;
1285 
1286 	err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1287 						  &pool_index);
1288 	if (err)
1289 		return err;
1290 
1291 	if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1292 		return -EINVAL;
1293 
1294 	threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1295 	return devlink_sb_port_pool_set(devlink_port, devlink_sb->index,
1296 					pool_index, threshold, info->extack);
1297 }
1298 
1299 static int
devlink_nl_sb_tc_pool_bind_fill(struct sk_buff * msg,struct devlink * devlink,struct devlink_port * devlink_port,struct devlink_sb * devlink_sb,u16 tc_index,enum devlink_sb_pool_type pool_type,enum devlink_command cmd,u32 portid,u32 seq,int flags)1300 devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink,
1301 				struct devlink_port *devlink_port,
1302 				struct devlink_sb *devlink_sb, u16 tc_index,
1303 				enum devlink_sb_pool_type pool_type,
1304 				enum devlink_command cmd,
1305 				u32 portid, u32 seq, int flags)
1306 {
1307 	const struct devlink_ops *ops = devlink->ops;
1308 	u16 pool_index;
1309 	u32 threshold;
1310 	void *hdr;
1311 	int err;
1312 
1313 	err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index,
1314 				       tc_index, pool_type,
1315 				       &pool_index, &threshold);
1316 	if (err)
1317 		return err;
1318 
1319 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1320 	if (!hdr)
1321 		return -EMSGSIZE;
1322 
1323 	if (devlink_nl_put_handle(msg, devlink))
1324 		goto nla_put_failure;
1325 	if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1326 		goto nla_put_failure;
1327 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1328 		goto nla_put_failure;
1329 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index))
1330 		goto nla_put_failure;
1331 	if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type))
1332 		goto nla_put_failure;
1333 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
1334 		goto nla_put_failure;
1335 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1336 		goto nla_put_failure;
1337 
1338 	if (ops->sb_occ_tc_port_bind_get) {
1339 		u32 cur;
1340 		u32 max;
1341 
1342 		err = ops->sb_occ_tc_port_bind_get(devlink_port,
1343 						   devlink_sb->index,
1344 						   tc_index, pool_type,
1345 						   &cur, &max);
1346 		if (err && err != -EOPNOTSUPP)
1347 			return err;
1348 		if (!err) {
1349 			if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
1350 				goto nla_put_failure;
1351 			if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
1352 				goto nla_put_failure;
1353 		}
1354 	}
1355 
1356 	genlmsg_end(msg, hdr);
1357 	return 0;
1358 
1359 nla_put_failure:
1360 	genlmsg_cancel(msg, hdr);
1361 	return -EMSGSIZE;
1362 }
1363 
devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff * skb,struct genl_info * info)1364 static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb,
1365 						   struct genl_info *info)
1366 {
1367 	struct devlink_port *devlink_port = info->user_ptr[0];
1368 	struct devlink *devlink = devlink_port->devlink;
1369 	struct devlink_sb *devlink_sb = info->user_ptr[1];
1370 	struct sk_buff *msg;
1371 	enum devlink_sb_pool_type pool_type;
1372 	u16 tc_index;
1373 	int err;
1374 
1375 	err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1376 	if (err)
1377 		return err;
1378 
1379 	err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1380 						pool_type, &tc_index);
1381 	if (err)
1382 		return err;
1383 
1384 	if (!devlink->ops->sb_tc_pool_bind_get)
1385 		return -EOPNOTSUPP;
1386 
1387 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1388 	if (!msg)
1389 		return -ENOMEM;
1390 
1391 	err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port,
1392 					      devlink_sb, tc_index, pool_type,
1393 					      DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1394 					      info->snd_portid,
1395 					      info->snd_seq, 0);
1396 	if (err) {
1397 		nlmsg_free(msg);
1398 		return err;
1399 	}
1400 
1401 	return genlmsg_reply(msg, info);
1402 }
1403 
__sb_tc_pool_bind_get_dumpit(struct sk_buff * msg,int start,int * p_idx,struct devlink * devlink,struct devlink_sb * devlink_sb,u32 portid,u32 seq)1404 static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1405 					int start, int *p_idx,
1406 					struct devlink *devlink,
1407 					struct devlink_sb *devlink_sb,
1408 					u32 portid, u32 seq)
1409 {
1410 	struct devlink_port *devlink_port;
1411 	u16 tc_index;
1412 	int err;
1413 
1414 	list_for_each_entry(devlink_port, &devlink->port_list, list) {
1415 		for (tc_index = 0;
1416 		     tc_index < devlink_sb->ingress_tc_count; tc_index++) {
1417 			if (*p_idx < start) {
1418 				(*p_idx)++;
1419 				continue;
1420 			}
1421 			err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1422 							      devlink_port,
1423 							      devlink_sb,
1424 							      tc_index,
1425 							      DEVLINK_SB_POOL_TYPE_INGRESS,
1426 							      DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1427 							      portid, seq,
1428 							      NLM_F_MULTI);
1429 			if (err)
1430 				return err;
1431 			(*p_idx)++;
1432 		}
1433 		for (tc_index = 0;
1434 		     tc_index < devlink_sb->egress_tc_count; tc_index++) {
1435 			if (*p_idx < start) {
1436 				(*p_idx)++;
1437 				continue;
1438 			}
1439 			err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1440 							      devlink_port,
1441 							      devlink_sb,
1442 							      tc_index,
1443 							      DEVLINK_SB_POOL_TYPE_EGRESS,
1444 							      DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1445 							      portid, seq,
1446 							      NLM_F_MULTI);
1447 			if (err)
1448 				return err;
1449 			(*p_idx)++;
1450 		}
1451 	}
1452 	return 0;
1453 }
1454 
1455 static int
devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)1456 devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1457 					  struct netlink_callback *cb)
1458 {
1459 	struct devlink *devlink;
1460 	struct devlink_sb *devlink_sb;
1461 	int start = cb->args[0];
1462 	int idx = 0;
1463 	int err;
1464 
1465 	mutex_lock(&devlink_mutex);
1466 	list_for_each_entry(devlink, &devlink_list, list) {
1467 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1468 		    !devlink->ops->sb_tc_pool_bind_get)
1469 			continue;
1470 
1471 		mutex_lock(&devlink->lock);
1472 		list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1473 			err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx,
1474 							   devlink,
1475 							   devlink_sb,
1476 							   NETLINK_CB(cb->skb).portid,
1477 							   cb->nlh->nlmsg_seq);
1478 			if (err && err != -EOPNOTSUPP) {
1479 				mutex_unlock(&devlink->lock);
1480 				goto out;
1481 			}
1482 		}
1483 		mutex_unlock(&devlink->lock);
1484 	}
1485 out:
1486 	mutex_unlock(&devlink_mutex);
1487 
1488 	cb->args[0] = idx;
1489 	return msg->len;
1490 }
1491 
devlink_sb_tc_pool_bind_set(struct devlink_port * devlink_port,unsigned int sb_index,u16 tc_index,enum devlink_sb_pool_type pool_type,u16 pool_index,u32 threshold,struct netlink_ext_ack * extack)1492 static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
1493 				       unsigned int sb_index, u16 tc_index,
1494 				       enum devlink_sb_pool_type pool_type,
1495 				       u16 pool_index, u32 threshold,
1496 				       struct netlink_ext_ack *extack)
1497 
1498 {
1499 	const struct devlink_ops *ops = devlink_port->devlink->ops;
1500 
1501 	if (ops->sb_tc_pool_bind_set)
1502 		return ops->sb_tc_pool_bind_set(devlink_port, sb_index,
1503 						tc_index, pool_type,
1504 						pool_index, threshold, extack);
1505 	return -EOPNOTSUPP;
1506 }
1507 
devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff * skb,struct genl_info * info)1508 static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb,
1509 						   struct genl_info *info)
1510 {
1511 	struct devlink_port *devlink_port = info->user_ptr[0];
1512 	struct devlink_sb *devlink_sb = info->user_ptr[1];
1513 	enum devlink_sb_pool_type pool_type;
1514 	u16 tc_index;
1515 	u16 pool_index;
1516 	u32 threshold;
1517 	int err;
1518 
1519 	err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1520 	if (err)
1521 		return err;
1522 
1523 	err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1524 						pool_type, &tc_index);
1525 	if (err)
1526 		return err;
1527 
1528 	err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1529 						  &pool_index);
1530 	if (err)
1531 		return err;
1532 
1533 	if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1534 		return -EINVAL;
1535 
1536 	threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1537 	return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index,
1538 					   tc_index, pool_type,
1539 					   pool_index, threshold, info->extack);
1540 }
1541 
devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff * skb,struct genl_info * info)1542 static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb,
1543 					       struct genl_info *info)
1544 {
1545 	struct devlink *devlink = info->user_ptr[0];
1546 	struct devlink_sb *devlink_sb = info->user_ptr[1];
1547 	const struct devlink_ops *ops = devlink->ops;
1548 
1549 	if (ops->sb_occ_snapshot)
1550 		return ops->sb_occ_snapshot(devlink, devlink_sb->index);
1551 	return -EOPNOTSUPP;
1552 }
1553 
devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff * skb,struct genl_info * info)1554 static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb,
1555 						struct genl_info *info)
1556 {
1557 	struct devlink *devlink = info->user_ptr[0];
1558 	struct devlink_sb *devlink_sb = info->user_ptr[1];
1559 	const struct devlink_ops *ops = devlink->ops;
1560 
1561 	if (ops->sb_occ_max_clear)
1562 		return ops->sb_occ_max_clear(devlink, devlink_sb->index);
1563 	return -EOPNOTSUPP;
1564 }
1565 
devlink_nl_eswitch_fill(struct sk_buff * msg,struct devlink * devlink,enum devlink_command cmd,u32 portid,u32 seq,int flags)1566 static int devlink_nl_eswitch_fill(struct sk_buff *msg, struct devlink *devlink,
1567 				   enum devlink_command cmd, u32 portid,
1568 				   u32 seq, int flags)
1569 {
1570 	const struct devlink_ops *ops = devlink->ops;
1571 	enum devlink_eswitch_encap_mode encap_mode;
1572 	u8 inline_mode;
1573 	void *hdr;
1574 	int err = 0;
1575 	u16 mode;
1576 
1577 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1578 	if (!hdr)
1579 		return -EMSGSIZE;
1580 
1581 	err = devlink_nl_put_handle(msg, devlink);
1582 	if (err)
1583 		goto nla_put_failure;
1584 
1585 	if (ops->eswitch_mode_get) {
1586 		err = ops->eswitch_mode_get(devlink, &mode);
1587 		if (err)
1588 			goto nla_put_failure;
1589 		err = nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode);
1590 		if (err)
1591 			goto nla_put_failure;
1592 	}
1593 
1594 	if (ops->eswitch_inline_mode_get) {
1595 		err = ops->eswitch_inline_mode_get(devlink, &inline_mode);
1596 		if (err)
1597 			goto nla_put_failure;
1598 		err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE,
1599 				 inline_mode);
1600 		if (err)
1601 			goto nla_put_failure;
1602 	}
1603 
1604 	if (ops->eswitch_encap_mode_get) {
1605 		err = ops->eswitch_encap_mode_get(devlink, &encap_mode);
1606 		if (err)
1607 			goto nla_put_failure;
1608 		err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, encap_mode);
1609 		if (err)
1610 			goto nla_put_failure;
1611 	}
1612 
1613 	genlmsg_end(msg, hdr);
1614 	return 0;
1615 
1616 nla_put_failure:
1617 	genlmsg_cancel(msg, hdr);
1618 	return err;
1619 }
1620 
devlink_nl_cmd_eswitch_get_doit(struct sk_buff * skb,struct genl_info * info)1621 static int devlink_nl_cmd_eswitch_get_doit(struct sk_buff *skb,
1622 					   struct genl_info *info)
1623 {
1624 	struct devlink *devlink = info->user_ptr[0];
1625 	struct sk_buff *msg;
1626 	int err;
1627 
1628 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1629 	if (!msg)
1630 		return -ENOMEM;
1631 
1632 	err = devlink_nl_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_GET,
1633 				      info->snd_portid, info->snd_seq, 0);
1634 
1635 	if (err) {
1636 		nlmsg_free(msg);
1637 		return err;
1638 	}
1639 
1640 	return genlmsg_reply(msg, info);
1641 }
1642 
devlink_nl_cmd_eswitch_set_doit(struct sk_buff * skb,struct genl_info * info)1643 static int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb,
1644 					   struct genl_info *info)
1645 {
1646 	struct devlink *devlink = info->user_ptr[0];
1647 	const struct devlink_ops *ops = devlink->ops;
1648 	enum devlink_eswitch_encap_mode encap_mode;
1649 	u8 inline_mode;
1650 	int err = 0;
1651 	u16 mode;
1652 
1653 	if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) {
1654 		if (!ops->eswitch_mode_set)
1655 			return -EOPNOTSUPP;
1656 		mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]);
1657 		err = ops->eswitch_mode_set(devlink, mode, info->extack);
1658 		if (err)
1659 			return err;
1660 	}
1661 
1662 	if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) {
1663 		if (!ops->eswitch_inline_mode_set)
1664 			return -EOPNOTSUPP;
1665 		inline_mode = nla_get_u8(
1666 				info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]);
1667 		err = ops->eswitch_inline_mode_set(devlink, inline_mode,
1668 						   info->extack);
1669 		if (err)
1670 			return err;
1671 	}
1672 
1673 	if (info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]) {
1674 		if (!ops->eswitch_encap_mode_set)
1675 			return -EOPNOTSUPP;
1676 		encap_mode = nla_get_u8(info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]);
1677 		err = ops->eswitch_encap_mode_set(devlink, encap_mode,
1678 						  info->extack);
1679 		if (err)
1680 			return err;
1681 	}
1682 
1683 	return 0;
1684 }
1685 
devlink_dpipe_match_put(struct sk_buff * skb,struct devlink_dpipe_match * match)1686 int devlink_dpipe_match_put(struct sk_buff *skb,
1687 			    struct devlink_dpipe_match *match)
1688 {
1689 	struct devlink_dpipe_header *header = match->header;
1690 	struct devlink_dpipe_field *field = &header->fields[match->field_id];
1691 	struct nlattr *match_attr;
1692 
1693 	match_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_MATCH);
1694 	if (!match_attr)
1695 		return -EMSGSIZE;
1696 
1697 	if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_MATCH_TYPE, match->type) ||
1698 	    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, match->header_index) ||
1699 	    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
1700 	    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
1701 	    nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
1702 		goto nla_put_failure;
1703 
1704 	nla_nest_end(skb, match_attr);
1705 	return 0;
1706 
1707 nla_put_failure:
1708 	nla_nest_cancel(skb, match_attr);
1709 	return -EMSGSIZE;
1710 }
1711 EXPORT_SYMBOL_GPL(devlink_dpipe_match_put);
1712 
devlink_dpipe_matches_put(struct devlink_dpipe_table * table,struct sk_buff * skb)1713 static int devlink_dpipe_matches_put(struct devlink_dpipe_table *table,
1714 				     struct sk_buff *skb)
1715 {
1716 	struct nlattr *matches_attr;
1717 
1718 	matches_attr = nla_nest_start_noflag(skb,
1719 					     DEVLINK_ATTR_DPIPE_TABLE_MATCHES);
1720 	if (!matches_attr)
1721 		return -EMSGSIZE;
1722 
1723 	if (table->table_ops->matches_dump(table->priv, skb))
1724 		goto nla_put_failure;
1725 
1726 	nla_nest_end(skb, matches_attr);
1727 	return 0;
1728 
1729 nla_put_failure:
1730 	nla_nest_cancel(skb, matches_attr);
1731 	return -EMSGSIZE;
1732 }
1733 
devlink_dpipe_action_put(struct sk_buff * skb,struct devlink_dpipe_action * action)1734 int devlink_dpipe_action_put(struct sk_buff *skb,
1735 			     struct devlink_dpipe_action *action)
1736 {
1737 	struct devlink_dpipe_header *header = action->header;
1738 	struct devlink_dpipe_field *field = &header->fields[action->field_id];
1739 	struct nlattr *action_attr;
1740 
1741 	action_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ACTION);
1742 	if (!action_attr)
1743 		return -EMSGSIZE;
1744 
1745 	if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_ACTION_TYPE, action->type) ||
1746 	    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, action->header_index) ||
1747 	    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
1748 	    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
1749 	    nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
1750 		goto nla_put_failure;
1751 
1752 	nla_nest_end(skb, action_attr);
1753 	return 0;
1754 
1755 nla_put_failure:
1756 	nla_nest_cancel(skb, action_attr);
1757 	return -EMSGSIZE;
1758 }
1759 EXPORT_SYMBOL_GPL(devlink_dpipe_action_put);
1760 
devlink_dpipe_actions_put(struct devlink_dpipe_table * table,struct sk_buff * skb)1761 static int devlink_dpipe_actions_put(struct devlink_dpipe_table *table,
1762 				     struct sk_buff *skb)
1763 {
1764 	struct nlattr *actions_attr;
1765 
1766 	actions_attr = nla_nest_start_noflag(skb,
1767 					     DEVLINK_ATTR_DPIPE_TABLE_ACTIONS);
1768 	if (!actions_attr)
1769 		return -EMSGSIZE;
1770 
1771 	if (table->table_ops->actions_dump(table->priv, skb))
1772 		goto nla_put_failure;
1773 
1774 	nla_nest_end(skb, actions_attr);
1775 	return 0;
1776 
1777 nla_put_failure:
1778 	nla_nest_cancel(skb, actions_attr);
1779 	return -EMSGSIZE;
1780 }
1781 
devlink_dpipe_table_put(struct sk_buff * skb,struct devlink_dpipe_table * table)1782 static int devlink_dpipe_table_put(struct sk_buff *skb,
1783 				   struct devlink_dpipe_table *table)
1784 {
1785 	struct nlattr *table_attr;
1786 	u64 table_size;
1787 
1788 	table_size = table->table_ops->size_get(table->priv);
1789 	table_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLE);
1790 	if (!table_attr)
1791 		return -EMSGSIZE;
1792 
1793 	if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) ||
1794 	    nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table_size,
1795 			      DEVLINK_ATTR_PAD))
1796 		goto nla_put_failure;
1797 	if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED,
1798 		       table->counters_enabled))
1799 		goto nla_put_failure;
1800 
1801 	if (table->resource_valid) {
1802 		if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID,
1803 				      table->resource_id, DEVLINK_ATTR_PAD) ||
1804 		    nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS,
1805 				      table->resource_units, DEVLINK_ATTR_PAD))
1806 			goto nla_put_failure;
1807 	}
1808 	if (devlink_dpipe_matches_put(table, skb))
1809 		goto nla_put_failure;
1810 
1811 	if (devlink_dpipe_actions_put(table, skb))
1812 		goto nla_put_failure;
1813 
1814 	nla_nest_end(skb, table_attr);
1815 	return 0;
1816 
1817 nla_put_failure:
1818 	nla_nest_cancel(skb, table_attr);
1819 	return -EMSGSIZE;
1820 }
1821 
devlink_dpipe_send_and_alloc_skb(struct sk_buff ** pskb,struct genl_info * info)1822 static int devlink_dpipe_send_and_alloc_skb(struct sk_buff **pskb,
1823 					    struct genl_info *info)
1824 {
1825 	int err;
1826 
1827 	if (*pskb) {
1828 		err = genlmsg_reply(*pskb, info);
1829 		if (err)
1830 			return err;
1831 	}
1832 	*pskb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
1833 	if (!*pskb)
1834 		return -ENOMEM;
1835 	return 0;
1836 }
1837 
devlink_dpipe_tables_fill(struct genl_info * info,enum devlink_command cmd,int flags,struct list_head * dpipe_tables,const char * table_name)1838 static int devlink_dpipe_tables_fill(struct genl_info *info,
1839 				     enum devlink_command cmd, int flags,
1840 				     struct list_head *dpipe_tables,
1841 				     const char *table_name)
1842 {
1843 	struct devlink *devlink = info->user_ptr[0];
1844 	struct devlink_dpipe_table *table;
1845 	struct nlattr *tables_attr;
1846 	struct sk_buff *skb = NULL;
1847 	struct nlmsghdr *nlh;
1848 	bool incomplete;
1849 	void *hdr;
1850 	int i;
1851 	int err;
1852 
1853 	table = list_first_entry(dpipe_tables,
1854 				 struct devlink_dpipe_table, list);
1855 start_again:
1856 	err = devlink_dpipe_send_and_alloc_skb(&skb, info);
1857 	if (err)
1858 		return err;
1859 
1860 	hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
1861 			  &devlink_nl_family, NLM_F_MULTI, cmd);
1862 	if (!hdr) {
1863 		nlmsg_free(skb);
1864 		return -EMSGSIZE;
1865 	}
1866 
1867 	if (devlink_nl_put_handle(skb, devlink))
1868 		goto nla_put_failure;
1869 	tables_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLES);
1870 	if (!tables_attr)
1871 		goto nla_put_failure;
1872 
1873 	i = 0;
1874 	incomplete = false;
1875 	list_for_each_entry_from(table, dpipe_tables, list) {
1876 		if (!table_name) {
1877 			err = devlink_dpipe_table_put(skb, table);
1878 			if (err) {
1879 				if (!i)
1880 					goto err_table_put;
1881 				incomplete = true;
1882 				break;
1883 			}
1884 		} else {
1885 			if (!strcmp(table->name, table_name)) {
1886 				err = devlink_dpipe_table_put(skb, table);
1887 				if (err)
1888 					break;
1889 			}
1890 		}
1891 		i++;
1892 	}
1893 
1894 	nla_nest_end(skb, tables_attr);
1895 	genlmsg_end(skb, hdr);
1896 	if (incomplete)
1897 		goto start_again;
1898 
1899 send_done:
1900 	nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
1901 			NLMSG_DONE, 0, flags | NLM_F_MULTI);
1902 	if (!nlh) {
1903 		err = devlink_dpipe_send_and_alloc_skb(&skb, info);
1904 		if (err)
1905 			return err;
1906 		goto send_done;
1907 	}
1908 
1909 	return genlmsg_reply(skb, info);
1910 
1911 nla_put_failure:
1912 	err = -EMSGSIZE;
1913 err_table_put:
1914 	nlmsg_free(skb);
1915 	return err;
1916 }
1917 
devlink_nl_cmd_dpipe_table_get(struct sk_buff * skb,struct genl_info * info)1918 static int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb,
1919 					  struct genl_info *info)
1920 {
1921 	struct devlink *devlink = info->user_ptr[0];
1922 	const char *table_name =  NULL;
1923 
1924 	if (info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME])
1925 		table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
1926 
1927 	return devlink_dpipe_tables_fill(info, DEVLINK_CMD_DPIPE_TABLE_GET, 0,
1928 					 &devlink->dpipe_table_list,
1929 					 table_name);
1930 }
1931 
devlink_dpipe_value_put(struct sk_buff * skb,struct devlink_dpipe_value * value)1932 static int devlink_dpipe_value_put(struct sk_buff *skb,
1933 				   struct devlink_dpipe_value *value)
1934 {
1935 	if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE,
1936 		    value->value_size, value->value))
1937 		return -EMSGSIZE;
1938 	if (value->mask)
1939 		if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE_MASK,
1940 			    value->value_size, value->mask))
1941 			return -EMSGSIZE;
1942 	if (value->mapping_valid)
1943 		if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_VALUE_MAPPING,
1944 				value->mapping_value))
1945 			return -EMSGSIZE;
1946 	return 0;
1947 }
1948 
devlink_dpipe_action_value_put(struct sk_buff * skb,struct devlink_dpipe_value * value)1949 static int devlink_dpipe_action_value_put(struct sk_buff *skb,
1950 					  struct devlink_dpipe_value *value)
1951 {
1952 	if (!value->action)
1953 		return -EINVAL;
1954 	if (devlink_dpipe_action_put(skb, value->action))
1955 		return -EMSGSIZE;
1956 	if (devlink_dpipe_value_put(skb, value))
1957 		return -EMSGSIZE;
1958 	return 0;
1959 }
1960 
devlink_dpipe_action_values_put(struct sk_buff * skb,struct devlink_dpipe_value * values,unsigned int values_count)1961 static int devlink_dpipe_action_values_put(struct sk_buff *skb,
1962 					   struct devlink_dpipe_value *values,
1963 					   unsigned int values_count)
1964 {
1965 	struct nlattr *action_attr;
1966 	int i;
1967 	int err;
1968 
1969 	for (i = 0; i < values_count; i++) {
1970 		action_attr = nla_nest_start_noflag(skb,
1971 						    DEVLINK_ATTR_DPIPE_ACTION_VALUE);
1972 		if (!action_attr)
1973 			return -EMSGSIZE;
1974 		err = devlink_dpipe_action_value_put(skb, &values[i]);
1975 		if (err)
1976 			goto err_action_value_put;
1977 		nla_nest_end(skb, action_attr);
1978 	}
1979 	return 0;
1980 
1981 err_action_value_put:
1982 	nla_nest_cancel(skb, action_attr);
1983 	return err;
1984 }
1985 
devlink_dpipe_match_value_put(struct sk_buff * skb,struct devlink_dpipe_value * value)1986 static int devlink_dpipe_match_value_put(struct sk_buff *skb,
1987 					 struct devlink_dpipe_value *value)
1988 {
1989 	if (!value->match)
1990 		return -EINVAL;
1991 	if (devlink_dpipe_match_put(skb, value->match))
1992 		return -EMSGSIZE;
1993 	if (devlink_dpipe_value_put(skb, value))
1994 		return -EMSGSIZE;
1995 	return 0;
1996 }
1997 
devlink_dpipe_match_values_put(struct sk_buff * skb,struct devlink_dpipe_value * values,unsigned int values_count)1998 static int devlink_dpipe_match_values_put(struct sk_buff *skb,
1999 					  struct devlink_dpipe_value *values,
2000 					  unsigned int values_count)
2001 {
2002 	struct nlattr *match_attr;
2003 	int i;
2004 	int err;
2005 
2006 	for (i = 0; i < values_count; i++) {
2007 		match_attr = nla_nest_start_noflag(skb,
2008 						   DEVLINK_ATTR_DPIPE_MATCH_VALUE);
2009 		if (!match_attr)
2010 			return -EMSGSIZE;
2011 		err = devlink_dpipe_match_value_put(skb, &values[i]);
2012 		if (err)
2013 			goto err_match_value_put;
2014 		nla_nest_end(skb, match_attr);
2015 	}
2016 	return 0;
2017 
2018 err_match_value_put:
2019 	nla_nest_cancel(skb, match_attr);
2020 	return err;
2021 }
2022 
devlink_dpipe_entry_put(struct sk_buff * skb,struct devlink_dpipe_entry * entry)2023 static int devlink_dpipe_entry_put(struct sk_buff *skb,
2024 				   struct devlink_dpipe_entry *entry)
2025 {
2026 	struct nlattr *entry_attr, *matches_attr, *actions_attr;
2027 	int err;
2028 
2029 	entry_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ENTRY);
2030 	if (!entry_attr)
2031 		return  -EMSGSIZE;
2032 
2033 	if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_INDEX, entry->index,
2034 			      DEVLINK_ATTR_PAD))
2035 		goto nla_put_failure;
2036 	if (entry->counter_valid)
2037 		if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_COUNTER,
2038 				      entry->counter, DEVLINK_ATTR_PAD))
2039 			goto nla_put_failure;
2040 
2041 	matches_attr = nla_nest_start_noflag(skb,
2042 					     DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES);
2043 	if (!matches_attr)
2044 		goto nla_put_failure;
2045 
2046 	err = devlink_dpipe_match_values_put(skb, entry->match_values,
2047 					     entry->match_values_count);
2048 	if (err) {
2049 		nla_nest_cancel(skb, matches_attr);
2050 		goto err_match_values_put;
2051 	}
2052 	nla_nest_end(skb, matches_attr);
2053 
2054 	actions_attr = nla_nest_start_noflag(skb,
2055 					     DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES);
2056 	if (!actions_attr)
2057 		goto nla_put_failure;
2058 
2059 	err = devlink_dpipe_action_values_put(skb, entry->action_values,
2060 					      entry->action_values_count);
2061 	if (err) {
2062 		nla_nest_cancel(skb, actions_attr);
2063 		goto err_action_values_put;
2064 	}
2065 	nla_nest_end(skb, actions_attr);
2066 
2067 	nla_nest_end(skb, entry_attr);
2068 	return 0;
2069 
2070 nla_put_failure:
2071 	err = -EMSGSIZE;
2072 err_match_values_put:
2073 err_action_values_put:
2074 	nla_nest_cancel(skb, entry_attr);
2075 	return err;
2076 }
2077 
2078 static struct devlink_dpipe_table *
devlink_dpipe_table_find(struct list_head * dpipe_tables,const char * table_name)2079 devlink_dpipe_table_find(struct list_head *dpipe_tables,
2080 			 const char *table_name)
2081 {
2082 	struct devlink_dpipe_table *table;
2083 
2084 	list_for_each_entry_rcu(table, dpipe_tables, list) {
2085 		if (!strcmp(table->name, table_name))
2086 			return table;
2087 	}
2088 	return NULL;
2089 }
2090 
devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx * dump_ctx)2091 int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx)
2092 {
2093 	struct devlink *devlink;
2094 	int err;
2095 
2096 	err = devlink_dpipe_send_and_alloc_skb(&dump_ctx->skb,
2097 					       dump_ctx->info);
2098 	if (err)
2099 		return err;
2100 
2101 	dump_ctx->hdr = genlmsg_put(dump_ctx->skb,
2102 				    dump_ctx->info->snd_portid,
2103 				    dump_ctx->info->snd_seq,
2104 				    &devlink_nl_family, NLM_F_MULTI,
2105 				    dump_ctx->cmd);
2106 	if (!dump_ctx->hdr)
2107 		goto nla_put_failure;
2108 
2109 	devlink = dump_ctx->info->user_ptr[0];
2110 	if (devlink_nl_put_handle(dump_ctx->skb, devlink))
2111 		goto nla_put_failure;
2112 	dump_ctx->nest = nla_nest_start_noflag(dump_ctx->skb,
2113 					       DEVLINK_ATTR_DPIPE_ENTRIES);
2114 	if (!dump_ctx->nest)
2115 		goto nla_put_failure;
2116 	return 0;
2117 
2118 nla_put_failure:
2119 	nlmsg_free(dump_ctx->skb);
2120 	return -EMSGSIZE;
2121 }
2122 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_prepare);
2123 
devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx * dump_ctx,struct devlink_dpipe_entry * entry)2124 int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx,
2125 				   struct devlink_dpipe_entry *entry)
2126 {
2127 	return devlink_dpipe_entry_put(dump_ctx->skb, entry);
2128 }
2129 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_append);
2130 
devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx * dump_ctx)2131 int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx)
2132 {
2133 	nla_nest_end(dump_ctx->skb, dump_ctx->nest);
2134 	genlmsg_end(dump_ctx->skb, dump_ctx->hdr);
2135 	return 0;
2136 }
2137 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close);
2138 
devlink_dpipe_entry_clear(struct devlink_dpipe_entry * entry)2139 void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry)
2140 
2141 {
2142 	unsigned int value_count, value_index;
2143 	struct devlink_dpipe_value *value;
2144 
2145 	value = entry->action_values;
2146 	value_count = entry->action_values_count;
2147 	for (value_index = 0; value_index < value_count; value_index++) {
2148 		kfree(value[value_index].value);
2149 		kfree(value[value_index].mask);
2150 	}
2151 
2152 	value = entry->match_values;
2153 	value_count = entry->match_values_count;
2154 	for (value_index = 0; value_index < value_count; value_index++) {
2155 		kfree(value[value_index].value);
2156 		kfree(value[value_index].mask);
2157 	}
2158 }
2159 EXPORT_SYMBOL(devlink_dpipe_entry_clear);
2160 
devlink_dpipe_entries_fill(struct genl_info * info,enum devlink_command cmd,int flags,struct devlink_dpipe_table * table)2161 static int devlink_dpipe_entries_fill(struct genl_info *info,
2162 				      enum devlink_command cmd, int flags,
2163 				      struct devlink_dpipe_table *table)
2164 {
2165 	struct devlink_dpipe_dump_ctx dump_ctx;
2166 	struct nlmsghdr *nlh;
2167 	int err;
2168 
2169 	dump_ctx.skb = NULL;
2170 	dump_ctx.cmd = cmd;
2171 	dump_ctx.info = info;
2172 
2173 	err = table->table_ops->entries_dump(table->priv,
2174 					     table->counters_enabled,
2175 					     &dump_ctx);
2176 	if (err)
2177 		return err;
2178 
2179 send_done:
2180 	nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq,
2181 			NLMSG_DONE, 0, flags | NLM_F_MULTI);
2182 	if (!nlh) {
2183 		err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info);
2184 		if (err)
2185 			return err;
2186 		goto send_done;
2187 	}
2188 	return genlmsg_reply(dump_ctx.skb, info);
2189 }
2190 
devlink_nl_cmd_dpipe_entries_get(struct sk_buff * skb,struct genl_info * info)2191 static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb,
2192 					    struct genl_info *info)
2193 {
2194 	struct devlink *devlink = info->user_ptr[0];
2195 	struct devlink_dpipe_table *table;
2196 	const char *table_name;
2197 
2198 	if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME])
2199 		return -EINVAL;
2200 
2201 	table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
2202 	table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2203 					 table_name);
2204 	if (!table)
2205 		return -EINVAL;
2206 
2207 	if (!table->table_ops->entries_dump)
2208 		return -EINVAL;
2209 
2210 	return devlink_dpipe_entries_fill(info, DEVLINK_CMD_DPIPE_ENTRIES_GET,
2211 					  0, table);
2212 }
2213 
devlink_dpipe_fields_put(struct sk_buff * skb,const struct devlink_dpipe_header * header)2214 static int devlink_dpipe_fields_put(struct sk_buff *skb,
2215 				    const struct devlink_dpipe_header *header)
2216 {
2217 	struct devlink_dpipe_field *field;
2218 	struct nlattr *field_attr;
2219 	int i;
2220 
2221 	for (i = 0; i < header->fields_count; i++) {
2222 		field = &header->fields[i];
2223 		field_attr = nla_nest_start_noflag(skb,
2224 						   DEVLINK_ATTR_DPIPE_FIELD);
2225 		if (!field_attr)
2226 			return -EMSGSIZE;
2227 		if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_FIELD_NAME, field->name) ||
2228 		    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
2229 		    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, field->bitwidth) ||
2230 		    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, field->mapping_type))
2231 			goto nla_put_failure;
2232 		nla_nest_end(skb, field_attr);
2233 	}
2234 	return 0;
2235 
2236 nla_put_failure:
2237 	nla_nest_cancel(skb, field_attr);
2238 	return -EMSGSIZE;
2239 }
2240 
devlink_dpipe_header_put(struct sk_buff * skb,struct devlink_dpipe_header * header)2241 static int devlink_dpipe_header_put(struct sk_buff *skb,
2242 				    struct devlink_dpipe_header *header)
2243 {
2244 	struct nlattr *fields_attr, *header_attr;
2245 	int err;
2246 
2247 	header_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADER);
2248 	if (!header_attr)
2249 		return -EMSGSIZE;
2250 
2251 	if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_HEADER_NAME, header->name) ||
2252 	    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
2253 	    nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
2254 		goto nla_put_failure;
2255 
2256 	fields_attr = nla_nest_start_noflag(skb,
2257 					    DEVLINK_ATTR_DPIPE_HEADER_FIELDS);
2258 	if (!fields_attr)
2259 		goto nla_put_failure;
2260 
2261 	err = devlink_dpipe_fields_put(skb, header);
2262 	if (err) {
2263 		nla_nest_cancel(skb, fields_attr);
2264 		goto nla_put_failure;
2265 	}
2266 	nla_nest_end(skb, fields_attr);
2267 	nla_nest_end(skb, header_attr);
2268 	return 0;
2269 
2270 nla_put_failure:
2271 	err = -EMSGSIZE;
2272 	nla_nest_cancel(skb, header_attr);
2273 	return err;
2274 }
2275 
devlink_dpipe_headers_fill(struct genl_info * info,enum devlink_command cmd,int flags,struct devlink_dpipe_headers * dpipe_headers)2276 static int devlink_dpipe_headers_fill(struct genl_info *info,
2277 				      enum devlink_command cmd, int flags,
2278 				      struct devlink_dpipe_headers *
2279 				      dpipe_headers)
2280 {
2281 	struct devlink *devlink = info->user_ptr[0];
2282 	struct nlattr *headers_attr;
2283 	struct sk_buff *skb = NULL;
2284 	struct nlmsghdr *nlh;
2285 	void *hdr;
2286 	int i, j;
2287 	int err;
2288 
2289 	i = 0;
2290 start_again:
2291 	err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2292 	if (err)
2293 		return err;
2294 
2295 	hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
2296 			  &devlink_nl_family, NLM_F_MULTI, cmd);
2297 	if (!hdr) {
2298 		nlmsg_free(skb);
2299 		return -EMSGSIZE;
2300 	}
2301 
2302 	if (devlink_nl_put_handle(skb, devlink))
2303 		goto nla_put_failure;
2304 	headers_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADERS);
2305 	if (!headers_attr)
2306 		goto nla_put_failure;
2307 
2308 	j = 0;
2309 	for (; i < dpipe_headers->headers_count; i++) {
2310 		err = devlink_dpipe_header_put(skb, dpipe_headers->headers[i]);
2311 		if (err) {
2312 			if (!j)
2313 				goto err_table_put;
2314 			break;
2315 		}
2316 		j++;
2317 	}
2318 	nla_nest_end(skb, headers_attr);
2319 	genlmsg_end(skb, hdr);
2320 	if (i != dpipe_headers->headers_count)
2321 		goto start_again;
2322 
2323 send_done:
2324 	nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
2325 			NLMSG_DONE, 0, flags | NLM_F_MULTI);
2326 	if (!nlh) {
2327 		err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2328 		if (err)
2329 			return err;
2330 		goto send_done;
2331 	}
2332 	return genlmsg_reply(skb, info);
2333 
2334 nla_put_failure:
2335 	err = -EMSGSIZE;
2336 err_table_put:
2337 	nlmsg_free(skb);
2338 	return err;
2339 }
2340 
devlink_nl_cmd_dpipe_headers_get(struct sk_buff * skb,struct genl_info * info)2341 static int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb,
2342 					    struct genl_info *info)
2343 {
2344 	struct devlink *devlink = info->user_ptr[0];
2345 
2346 	if (!devlink->dpipe_headers)
2347 		return -EOPNOTSUPP;
2348 	return devlink_dpipe_headers_fill(info, DEVLINK_CMD_DPIPE_HEADERS_GET,
2349 					  0, devlink->dpipe_headers);
2350 }
2351 
devlink_dpipe_table_counters_set(struct devlink * devlink,const char * table_name,bool enable)2352 static int devlink_dpipe_table_counters_set(struct devlink *devlink,
2353 					    const char *table_name,
2354 					    bool enable)
2355 {
2356 	struct devlink_dpipe_table *table;
2357 
2358 	table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2359 					 table_name);
2360 	if (!table)
2361 		return -EINVAL;
2362 
2363 	if (table->counter_control_extern)
2364 		return -EOPNOTSUPP;
2365 
2366 	if (!(table->counters_enabled ^ enable))
2367 		return 0;
2368 
2369 	table->counters_enabled = enable;
2370 	if (table->table_ops->counters_set_update)
2371 		table->table_ops->counters_set_update(table->priv, enable);
2372 	return 0;
2373 }
2374 
devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff * skb,struct genl_info * info)2375 static int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb,
2376 						   struct genl_info *info)
2377 {
2378 	struct devlink *devlink = info->user_ptr[0];
2379 	const char *table_name;
2380 	bool counters_enable;
2381 
2382 	if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME] ||
2383 	    !info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED])
2384 		return -EINVAL;
2385 
2386 	table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
2387 	counters_enable = !!nla_get_u8(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]);
2388 
2389 	return devlink_dpipe_table_counters_set(devlink, table_name,
2390 						counters_enable);
2391 }
2392 
2393 static struct devlink_resource *
devlink_resource_find(struct devlink * devlink,struct devlink_resource * resource,u64 resource_id)2394 devlink_resource_find(struct devlink *devlink,
2395 		      struct devlink_resource *resource, u64 resource_id)
2396 {
2397 	struct list_head *resource_list;
2398 
2399 	if (resource)
2400 		resource_list = &resource->resource_list;
2401 	else
2402 		resource_list = &devlink->resource_list;
2403 
2404 	list_for_each_entry(resource, resource_list, list) {
2405 		struct devlink_resource *child_resource;
2406 
2407 		if (resource->id == resource_id)
2408 			return resource;
2409 
2410 		child_resource = devlink_resource_find(devlink, resource,
2411 						       resource_id);
2412 		if (child_resource)
2413 			return child_resource;
2414 	}
2415 	return NULL;
2416 }
2417 
2418 static void
devlink_resource_validate_children(struct devlink_resource * resource)2419 devlink_resource_validate_children(struct devlink_resource *resource)
2420 {
2421 	struct devlink_resource *child_resource;
2422 	bool size_valid = true;
2423 	u64 parts_size = 0;
2424 
2425 	if (list_empty(&resource->resource_list))
2426 		goto out;
2427 
2428 	list_for_each_entry(child_resource, &resource->resource_list, list)
2429 		parts_size += child_resource->size_new;
2430 
2431 	if (parts_size > resource->size_new)
2432 		size_valid = false;
2433 out:
2434 	resource->size_valid = size_valid;
2435 }
2436 
2437 static int
devlink_resource_validate_size(struct devlink_resource * resource,u64 size,struct netlink_ext_ack * extack)2438 devlink_resource_validate_size(struct devlink_resource *resource, u64 size,
2439 			       struct netlink_ext_ack *extack)
2440 {
2441 	u64 reminder;
2442 	int err = 0;
2443 
2444 	if (size > resource->size_params.size_max) {
2445 		NL_SET_ERR_MSG_MOD(extack, "Size larger than maximum");
2446 		err = -EINVAL;
2447 	}
2448 
2449 	if (size < resource->size_params.size_min) {
2450 		NL_SET_ERR_MSG_MOD(extack, "Size smaller than minimum");
2451 		err = -EINVAL;
2452 	}
2453 
2454 	div64_u64_rem(size, resource->size_params.size_granularity, &reminder);
2455 	if (reminder) {
2456 		NL_SET_ERR_MSG_MOD(extack, "Wrong granularity");
2457 		err = -EINVAL;
2458 	}
2459 
2460 	return err;
2461 }
2462 
devlink_nl_cmd_resource_set(struct sk_buff * skb,struct genl_info * info)2463 static int devlink_nl_cmd_resource_set(struct sk_buff *skb,
2464 				       struct genl_info *info)
2465 {
2466 	struct devlink *devlink = info->user_ptr[0];
2467 	struct devlink_resource *resource;
2468 	u64 resource_id;
2469 	u64 size;
2470 	int err;
2471 
2472 	if (!info->attrs[DEVLINK_ATTR_RESOURCE_ID] ||
2473 	    !info->attrs[DEVLINK_ATTR_RESOURCE_SIZE])
2474 		return -EINVAL;
2475 	resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]);
2476 
2477 	resource = devlink_resource_find(devlink, NULL, resource_id);
2478 	if (!resource)
2479 		return -EINVAL;
2480 
2481 	size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]);
2482 	err = devlink_resource_validate_size(resource, size, info->extack);
2483 	if (err)
2484 		return err;
2485 
2486 	resource->size_new = size;
2487 	devlink_resource_validate_children(resource);
2488 	if (resource->parent)
2489 		devlink_resource_validate_children(resource->parent);
2490 	return 0;
2491 }
2492 
2493 static int
devlink_resource_size_params_put(struct devlink_resource * resource,struct sk_buff * skb)2494 devlink_resource_size_params_put(struct devlink_resource *resource,
2495 				 struct sk_buff *skb)
2496 {
2497 	struct devlink_resource_size_params *size_params;
2498 
2499 	size_params = &resource->size_params;
2500 	if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN,
2501 			      size_params->size_granularity, DEVLINK_ATTR_PAD) ||
2502 	    nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX,
2503 			      size_params->size_max, DEVLINK_ATTR_PAD) ||
2504 	    nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN,
2505 			      size_params->size_min, DEVLINK_ATTR_PAD) ||
2506 	    nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit))
2507 		return -EMSGSIZE;
2508 	return 0;
2509 }
2510 
devlink_resource_occ_put(struct devlink_resource * resource,struct sk_buff * skb)2511 static int devlink_resource_occ_put(struct devlink_resource *resource,
2512 				    struct sk_buff *skb)
2513 {
2514 	if (!resource->occ_get)
2515 		return 0;
2516 	return nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC,
2517 				 resource->occ_get(resource->occ_get_priv),
2518 				 DEVLINK_ATTR_PAD);
2519 }
2520 
devlink_resource_put(struct devlink * devlink,struct sk_buff * skb,struct devlink_resource * resource)2521 static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb,
2522 				struct devlink_resource *resource)
2523 {
2524 	struct devlink_resource *child_resource;
2525 	struct nlattr *child_resource_attr;
2526 	struct nlattr *resource_attr;
2527 
2528 	resource_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_RESOURCE);
2529 	if (!resource_attr)
2530 		return -EMSGSIZE;
2531 
2532 	if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) ||
2533 	    nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size,
2534 			      DEVLINK_ATTR_PAD) ||
2535 	    nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id,
2536 			      DEVLINK_ATTR_PAD))
2537 		goto nla_put_failure;
2538 	if (resource->size != resource->size_new)
2539 		nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW,
2540 				  resource->size_new, DEVLINK_ATTR_PAD);
2541 	if (devlink_resource_occ_put(resource, skb))
2542 		goto nla_put_failure;
2543 	if (devlink_resource_size_params_put(resource, skb))
2544 		goto nla_put_failure;
2545 	if (list_empty(&resource->resource_list))
2546 		goto out;
2547 
2548 	if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID,
2549 		       resource->size_valid))
2550 		goto nla_put_failure;
2551 
2552 	child_resource_attr = nla_nest_start_noflag(skb,
2553 						    DEVLINK_ATTR_RESOURCE_LIST);
2554 	if (!child_resource_attr)
2555 		goto nla_put_failure;
2556 
2557 	list_for_each_entry(child_resource, &resource->resource_list, list) {
2558 		if (devlink_resource_put(devlink, skb, child_resource))
2559 			goto resource_put_failure;
2560 	}
2561 
2562 	nla_nest_end(skb, child_resource_attr);
2563 out:
2564 	nla_nest_end(skb, resource_attr);
2565 	return 0;
2566 
2567 resource_put_failure:
2568 	nla_nest_cancel(skb, child_resource_attr);
2569 nla_put_failure:
2570 	nla_nest_cancel(skb, resource_attr);
2571 	return -EMSGSIZE;
2572 }
2573 
devlink_resource_fill(struct genl_info * info,enum devlink_command cmd,int flags)2574 static int devlink_resource_fill(struct genl_info *info,
2575 				 enum devlink_command cmd, int flags)
2576 {
2577 	struct devlink *devlink = info->user_ptr[0];
2578 	struct devlink_resource *resource;
2579 	struct nlattr *resources_attr;
2580 	struct sk_buff *skb = NULL;
2581 	struct nlmsghdr *nlh;
2582 	bool incomplete;
2583 	void *hdr;
2584 	int i;
2585 	int err;
2586 
2587 	resource = list_first_entry(&devlink->resource_list,
2588 				    struct devlink_resource, list);
2589 start_again:
2590 	err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2591 	if (err)
2592 		return err;
2593 
2594 	hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
2595 			  &devlink_nl_family, NLM_F_MULTI, cmd);
2596 	if (!hdr) {
2597 		nlmsg_free(skb);
2598 		return -EMSGSIZE;
2599 	}
2600 
2601 	if (devlink_nl_put_handle(skb, devlink))
2602 		goto nla_put_failure;
2603 
2604 	resources_attr = nla_nest_start_noflag(skb,
2605 					       DEVLINK_ATTR_RESOURCE_LIST);
2606 	if (!resources_attr)
2607 		goto nla_put_failure;
2608 
2609 	incomplete = false;
2610 	i = 0;
2611 	list_for_each_entry_from(resource, &devlink->resource_list, list) {
2612 		err = devlink_resource_put(devlink, skb, resource);
2613 		if (err) {
2614 			if (!i)
2615 				goto err_resource_put;
2616 			incomplete = true;
2617 			break;
2618 		}
2619 		i++;
2620 	}
2621 	nla_nest_end(skb, resources_attr);
2622 	genlmsg_end(skb, hdr);
2623 	if (incomplete)
2624 		goto start_again;
2625 send_done:
2626 	nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
2627 			NLMSG_DONE, 0, flags | NLM_F_MULTI);
2628 	if (!nlh) {
2629 		err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2630 		if (err)
2631 			return err;
2632 		goto send_done;
2633 	}
2634 	return genlmsg_reply(skb, info);
2635 
2636 nla_put_failure:
2637 	err = -EMSGSIZE;
2638 err_resource_put:
2639 	nlmsg_free(skb);
2640 	return err;
2641 }
2642 
devlink_nl_cmd_resource_dump(struct sk_buff * skb,struct genl_info * info)2643 static int devlink_nl_cmd_resource_dump(struct sk_buff *skb,
2644 					struct genl_info *info)
2645 {
2646 	struct devlink *devlink = info->user_ptr[0];
2647 
2648 	if (list_empty(&devlink->resource_list))
2649 		return -EOPNOTSUPP;
2650 
2651 	return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0);
2652 }
2653 
2654 static int
devlink_resources_validate(struct devlink * devlink,struct devlink_resource * resource,struct genl_info * info)2655 devlink_resources_validate(struct devlink *devlink,
2656 			   struct devlink_resource *resource,
2657 			   struct genl_info *info)
2658 {
2659 	struct list_head *resource_list;
2660 	int err = 0;
2661 
2662 	if (resource)
2663 		resource_list = &resource->resource_list;
2664 	else
2665 		resource_list = &devlink->resource_list;
2666 
2667 	list_for_each_entry(resource, resource_list, list) {
2668 		if (!resource->size_valid)
2669 			return -EINVAL;
2670 		err = devlink_resources_validate(devlink, resource, info);
2671 		if (err)
2672 			return err;
2673 	}
2674 	return err;
2675 }
2676 
devlink_reload_supported(struct devlink * devlink)2677 static bool devlink_reload_supported(struct devlink *devlink)
2678 {
2679 	return devlink->ops->reload_down && devlink->ops->reload_up;
2680 }
2681 
devlink_reload_failed_set(struct devlink * devlink,bool reload_failed)2682 static void devlink_reload_failed_set(struct devlink *devlink,
2683 				      bool reload_failed)
2684 {
2685 	if (devlink->reload_failed == reload_failed)
2686 		return;
2687 	devlink->reload_failed = reload_failed;
2688 	devlink_notify(devlink, DEVLINK_CMD_NEW);
2689 }
2690 
devlink_is_reload_failed(const struct devlink * devlink)2691 bool devlink_is_reload_failed(const struct devlink *devlink)
2692 {
2693 	return devlink->reload_failed;
2694 }
2695 EXPORT_SYMBOL_GPL(devlink_is_reload_failed);
2696 
devlink_nl_cmd_reload(struct sk_buff * skb,struct genl_info * info)2697 static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
2698 {
2699 	struct devlink *devlink = info->user_ptr[0];
2700 	int err;
2701 
2702 	if (!devlink_reload_supported(devlink) || !devlink->reload_enabled)
2703 		return -EOPNOTSUPP;
2704 
2705 	err = devlink_resources_validate(devlink, NULL, info);
2706 	if (err) {
2707 		NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed");
2708 		return err;
2709 	}
2710 	err = devlink->ops->reload_down(devlink, info->extack);
2711 	if (err)
2712 		return err;
2713 	err = devlink->ops->reload_up(devlink, info->extack);
2714 	devlink_reload_failed_set(devlink, !!err);
2715 	return err;
2716 }
2717 
devlink_nl_flash_update_fill(struct sk_buff * msg,struct devlink * devlink,enum devlink_command cmd,const char * status_msg,const char * component,unsigned long done,unsigned long total)2718 static int devlink_nl_flash_update_fill(struct sk_buff *msg,
2719 					struct devlink *devlink,
2720 					enum devlink_command cmd,
2721 					const char *status_msg,
2722 					const char *component,
2723 					unsigned long done, unsigned long total)
2724 {
2725 	void *hdr;
2726 
2727 	hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd);
2728 	if (!hdr)
2729 		return -EMSGSIZE;
2730 
2731 	if (devlink_nl_put_handle(msg, devlink))
2732 		goto nla_put_failure;
2733 
2734 	if (cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS)
2735 		goto out;
2736 
2737 	if (status_msg &&
2738 	    nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_MSG,
2739 			   status_msg))
2740 		goto nla_put_failure;
2741 	if (component &&
2742 	    nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_COMPONENT,
2743 			   component))
2744 		goto nla_put_failure;
2745 	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_DONE,
2746 			      done, DEVLINK_ATTR_PAD))
2747 		goto nla_put_failure;
2748 	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TOTAL,
2749 			      total, DEVLINK_ATTR_PAD))
2750 		goto nla_put_failure;
2751 
2752 out:
2753 	genlmsg_end(msg, hdr);
2754 	return 0;
2755 
2756 nla_put_failure:
2757 	genlmsg_cancel(msg, hdr);
2758 	return -EMSGSIZE;
2759 }
2760 
__devlink_flash_update_notify(struct devlink * devlink,enum devlink_command cmd,const char * status_msg,const char * component,unsigned long done,unsigned long total)2761 static void __devlink_flash_update_notify(struct devlink *devlink,
2762 					  enum devlink_command cmd,
2763 					  const char *status_msg,
2764 					  const char *component,
2765 					  unsigned long done,
2766 					  unsigned long total)
2767 {
2768 	struct sk_buff *msg;
2769 	int err;
2770 
2771 	WARN_ON(cmd != DEVLINK_CMD_FLASH_UPDATE &&
2772 		cmd != DEVLINK_CMD_FLASH_UPDATE_END &&
2773 		cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS);
2774 
2775 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2776 	if (!msg)
2777 		return;
2778 
2779 	err = devlink_nl_flash_update_fill(msg, devlink, cmd, status_msg,
2780 					   component, done, total);
2781 	if (err)
2782 		goto out_free_msg;
2783 
2784 	genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
2785 				msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
2786 	return;
2787 
2788 out_free_msg:
2789 	nlmsg_free(msg);
2790 }
2791 
devlink_flash_update_begin_notify(struct devlink * devlink)2792 void devlink_flash_update_begin_notify(struct devlink *devlink)
2793 {
2794 	__devlink_flash_update_notify(devlink,
2795 				      DEVLINK_CMD_FLASH_UPDATE,
2796 				      NULL, NULL, 0, 0);
2797 }
2798 EXPORT_SYMBOL_GPL(devlink_flash_update_begin_notify);
2799 
devlink_flash_update_end_notify(struct devlink * devlink)2800 void devlink_flash_update_end_notify(struct devlink *devlink)
2801 {
2802 	__devlink_flash_update_notify(devlink,
2803 				      DEVLINK_CMD_FLASH_UPDATE_END,
2804 				      NULL, NULL, 0, 0);
2805 }
2806 EXPORT_SYMBOL_GPL(devlink_flash_update_end_notify);
2807 
devlink_flash_update_status_notify(struct devlink * devlink,const char * status_msg,const char * component,unsigned long done,unsigned long total)2808 void devlink_flash_update_status_notify(struct devlink *devlink,
2809 					const char *status_msg,
2810 					const char *component,
2811 					unsigned long done,
2812 					unsigned long total)
2813 {
2814 	__devlink_flash_update_notify(devlink,
2815 				      DEVLINK_CMD_FLASH_UPDATE_STATUS,
2816 				      status_msg, component, done, total);
2817 }
2818 EXPORT_SYMBOL_GPL(devlink_flash_update_status_notify);
2819 
devlink_nl_cmd_flash_update(struct sk_buff * skb,struct genl_info * info)2820 static int devlink_nl_cmd_flash_update(struct sk_buff *skb,
2821 				       struct genl_info *info)
2822 {
2823 	struct devlink *devlink = info->user_ptr[0];
2824 	const char *file_name, *component;
2825 	struct nlattr *nla_component;
2826 
2827 	if (!devlink->ops->flash_update)
2828 		return -EOPNOTSUPP;
2829 
2830 	if (!info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME])
2831 		return -EINVAL;
2832 	file_name = nla_data(info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME]);
2833 
2834 	nla_component = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT];
2835 	component = nla_component ? nla_data(nla_component) : NULL;
2836 
2837 	return devlink->ops->flash_update(devlink, file_name, component,
2838 					  info->extack);
2839 }
2840 
2841 static const struct devlink_param devlink_param_generic[] = {
2842 	{
2843 		.id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET,
2844 		.name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME,
2845 		.type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE,
2846 	},
2847 	{
2848 		.id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
2849 		.name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME,
2850 		.type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE,
2851 	},
2852 	{
2853 		.id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV,
2854 		.name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME,
2855 		.type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE,
2856 	},
2857 	{
2858 		.id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT,
2859 		.name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME,
2860 		.type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE,
2861 	},
2862 	{
2863 		.id = DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI,
2864 		.name = DEVLINK_PARAM_GENERIC_IGNORE_ARI_NAME,
2865 		.type = DEVLINK_PARAM_GENERIC_IGNORE_ARI_TYPE,
2866 	},
2867 	{
2868 		.id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
2869 		.name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_NAME,
2870 		.type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_TYPE,
2871 	},
2872 	{
2873 		.id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
2874 		.name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_NAME,
2875 		.type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_TYPE,
2876 	},
2877 	{
2878 		.id = DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY,
2879 		.name = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME,
2880 		.type = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE,
2881 	},
2882 	{
2883 		.id = DEVLINK_PARAM_GENERIC_ID_RESET_DEV_ON_DRV_PROBE,
2884 		.name = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_NAME,
2885 		.type = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_TYPE,
2886 	},
2887 };
2888 
devlink_param_generic_verify(const struct devlink_param * param)2889 static int devlink_param_generic_verify(const struct devlink_param *param)
2890 {
2891 	/* verify it match generic parameter by id and name */
2892 	if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX)
2893 		return -EINVAL;
2894 	if (strcmp(param->name, devlink_param_generic[param->id].name))
2895 		return -ENOENT;
2896 
2897 	WARN_ON(param->type != devlink_param_generic[param->id].type);
2898 
2899 	return 0;
2900 }
2901 
devlink_param_driver_verify(const struct devlink_param * param)2902 static int devlink_param_driver_verify(const struct devlink_param *param)
2903 {
2904 	int i;
2905 
2906 	if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX)
2907 		return -EINVAL;
2908 	/* verify no such name in generic params */
2909 	for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++)
2910 		if (!strcmp(param->name, devlink_param_generic[i].name))
2911 			return -EEXIST;
2912 
2913 	return 0;
2914 }
2915 
2916 static struct devlink_param_item *
devlink_param_find_by_name(struct list_head * param_list,const char * param_name)2917 devlink_param_find_by_name(struct list_head *param_list,
2918 			   const char *param_name)
2919 {
2920 	struct devlink_param_item *param_item;
2921 
2922 	list_for_each_entry(param_item, param_list, list)
2923 		if (!strcmp(param_item->param->name, param_name))
2924 			return param_item;
2925 	return NULL;
2926 }
2927 
2928 static struct devlink_param_item *
devlink_param_find_by_id(struct list_head * param_list,u32 param_id)2929 devlink_param_find_by_id(struct list_head *param_list, u32 param_id)
2930 {
2931 	struct devlink_param_item *param_item;
2932 
2933 	list_for_each_entry(param_item, param_list, list)
2934 		if (param_item->param->id == param_id)
2935 			return param_item;
2936 	return NULL;
2937 }
2938 
2939 static bool
devlink_param_cmode_is_supported(const struct devlink_param * param,enum devlink_param_cmode cmode)2940 devlink_param_cmode_is_supported(const struct devlink_param *param,
2941 				 enum devlink_param_cmode cmode)
2942 {
2943 	return test_bit(cmode, &param->supported_cmodes);
2944 }
2945 
devlink_param_get(struct devlink * devlink,const struct devlink_param * param,struct devlink_param_gset_ctx * ctx)2946 static int devlink_param_get(struct devlink *devlink,
2947 			     const struct devlink_param *param,
2948 			     struct devlink_param_gset_ctx *ctx)
2949 {
2950 	if (!param->get)
2951 		return -EOPNOTSUPP;
2952 	return param->get(devlink, param->id, ctx);
2953 }
2954 
devlink_param_set(struct devlink * devlink,const struct devlink_param * param,struct devlink_param_gset_ctx * ctx)2955 static int devlink_param_set(struct devlink *devlink,
2956 			     const struct devlink_param *param,
2957 			     struct devlink_param_gset_ctx *ctx)
2958 {
2959 	if (!param->set)
2960 		return -EOPNOTSUPP;
2961 	return param->set(devlink, param->id, ctx);
2962 }
2963 
2964 static int
devlink_param_type_to_nla_type(enum devlink_param_type param_type)2965 devlink_param_type_to_nla_type(enum devlink_param_type param_type)
2966 {
2967 	switch (param_type) {
2968 	case DEVLINK_PARAM_TYPE_U8:
2969 		return NLA_U8;
2970 	case DEVLINK_PARAM_TYPE_U16:
2971 		return NLA_U16;
2972 	case DEVLINK_PARAM_TYPE_U32:
2973 		return NLA_U32;
2974 	case DEVLINK_PARAM_TYPE_STRING:
2975 		return NLA_STRING;
2976 	case DEVLINK_PARAM_TYPE_BOOL:
2977 		return NLA_FLAG;
2978 	default:
2979 		return -EINVAL;
2980 	}
2981 }
2982 
2983 static int
devlink_nl_param_value_fill_one(struct sk_buff * msg,enum devlink_param_type type,enum devlink_param_cmode cmode,union devlink_param_value val)2984 devlink_nl_param_value_fill_one(struct sk_buff *msg,
2985 				enum devlink_param_type type,
2986 				enum devlink_param_cmode cmode,
2987 				union devlink_param_value val)
2988 {
2989 	struct nlattr *param_value_attr;
2990 
2991 	param_value_attr = nla_nest_start_noflag(msg,
2992 						 DEVLINK_ATTR_PARAM_VALUE);
2993 	if (!param_value_attr)
2994 		goto nla_put_failure;
2995 
2996 	if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
2997 		goto value_nest_cancel;
2998 
2999 	switch (type) {
3000 	case DEVLINK_PARAM_TYPE_U8:
3001 		if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8))
3002 			goto value_nest_cancel;
3003 		break;
3004 	case DEVLINK_PARAM_TYPE_U16:
3005 		if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16))
3006 			goto value_nest_cancel;
3007 		break;
3008 	case DEVLINK_PARAM_TYPE_U32:
3009 		if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32))
3010 			goto value_nest_cancel;
3011 		break;
3012 	case DEVLINK_PARAM_TYPE_STRING:
3013 		if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
3014 				   val.vstr))
3015 			goto value_nest_cancel;
3016 		break;
3017 	case DEVLINK_PARAM_TYPE_BOOL:
3018 		if (val.vbool &&
3019 		    nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA))
3020 			goto value_nest_cancel;
3021 		break;
3022 	}
3023 
3024 	nla_nest_end(msg, param_value_attr);
3025 	return 0;
3026 
3027 value_nest_cancel:
3028 	nla_nest_cancel(msg, param_value_attr);
3029 nla_put_failure:
3030 	return -EMSGSIZE;
3031 }
3032 
devlink_nl_param_fill(struct sk_buff * msg,struct devlink * devlink,unsigned int port_index,struct devlink_param_item * param_item,enum devlink_command cmd,u32 portid,u32 seq,int flags)3033 static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
3034 				 unsigned int port_index,
3035 				 struct devlink_param_item *param_item,
3036 				 enum devlink_command cmd,
3037 				 u32 portid, u32 seq, int flags)
3038 {
3039 	union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
3040 	bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
3041 	const struct devlink_param *param = param_item->param;
3042 	struct devlink_param_gset_ctx ctx;
3043 	struct nlattr *param_values_list;
3044 	struct nlattr *param_attr;
3045 	int nla_type;
3046 	void *hdr;
3047 	int err;
3048 	int i;
3049 
3050 	/* Get value from driver part to driverinit configuration mode */
3051 	for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
3052 		if (!devlink_param_cmode_is_supported(param, i))
3053 			continue;
3054 		if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
3055 			if (!param_item->driverinit_value_valid)
3056 				return -EOPNOTSUPP;
3057 			param_value[i] = param_item->driverinit_value;
3058 		} else {
3059 			if (!param_item->published)
3060 				continue;
3061 			ctx.cmode = i;
3062 			err = devlink_param_get(devlink, param, &ctx);
3063 			if (err)
3064 				return err;
3065 			param_value[i] = ctx.val;
3066 		}
3067 		param_value_set[i] = true;
3068 	}
3069 
3070 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
3071 	if (!hdr)
3072 		return -EMSGSIZE;
3073 
3074 	if (devlink_nl_put_handle(msg, devlink))
3075 		goto genlmsg_cancel;
3076 
3077 	if (cmd == DEVLINK_CMD_PORT_PARAM_GET ||
3078 	    cmd == DEVLINK_CMD_PORT_PARAM_NEW ||
3079 	    cmd == DEVLINK_CMD_PORT_PARAM_DEL)
3080 		if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index))
3081 			goto genlmsg_cancel;
3082 
3083 	param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM);
3084 	if (!param_attr)
3085 		goto genlmsg_cancel;
3086 	if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name))
3087 		goto param_nest_cancel;
3088 	if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC))
3089 		goto param_nest_cancel;
3090 
3091 	nla_type = devlink_param_type_to_nla_type(param->type);
3092 	if (nla_type < 0)
3093 		goto param_nest_cancel;
3094 	if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type))
3095 		goto param_nest_cancel;
3096 
3097 	param_values_list = nla_nest_start_noflag(msg,
3098 						  DEVLINK_ATTR_PARAM_VALUES_LIST);
3099 	if (!param_values_list)
3100 		goto param_nest_cancel;
3101 
3102 	for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
3103 		if (!param_value_set[i])
3104 			continue;
3105 		err = devlink_nl_param_value_fill_one(msg, param->type,
3106 						      i, param_value[i]);
3107 		if (err)
3108 			goto values_list_nest_cancel;
3109 	}
3110 
3111 	nla_nest_end(msg, param_values_list);
3112 	nla_nest_end(msg, param_attr);
3113 	genlmsg_end(msg, hdr);
3114 	return 0;
3115 
3116 values_list_nest_cancel:
3117 	nla_nest_end(msg, param_values_list);
3118 param_nest_cancel:
3119 	nla_nest_cancel(msg, param_attr);
3120 genlmsg_cancel:
3121 	genlmsg_cancel(msg, hdr);
3122 	return -EMSGSIZE;
3123 }
3124 
devlink_param_notify(struct devlink * devlink,unsigned int port_index,struct devlink_param_item * param_item,enum devlink_command cmd)3125 static void devlink_param_notify(struct devlink *devlink,
3126 				 unsigned int port_index,
3127 				 struct devlink_param_item *param_item,
3128 				 enum devlink_command cmd)
3129 {
3130 	struct sk_buff *msg;
3131 	int err;
3132 
3133 	WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL &&
3134 		cmd != DEVLINK_CMD_PORT_PARAM_NEW &&
3135 		cmd != DEVLINK_CMD_PORT_PARAM_DEL);
3136 
3137 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3138 	if (!msg)
3139 		return;
3140 	err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd,
3141 				    0, 0, 0);
3142 	if (err) {
3143 		nlmsg_free(msg);
3144 		return;
3145 	}
3146 
3147 	genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
3148 				msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
3149 }
3150 
devlink_nl_cmd_param_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)3151 static int devlink_nl_cmd_param_get_dumpit(struct sk_buff *msg,
3152 					   struct netlink_callback *cb)
3153 {
3154 	struct devlink_param_item *param_item;
3155 	struct devlink *devlink;
3156 	int start = cb->args[0];
3157 	int idx = 0;
3158 	int err;
3159 
3160 	mutex_lock(&devlink_mutex);
3161 	list_for_each_entry(devlink, &devlink_list, list) {
3162 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3163 			continue;
3164 		mutex_lock(&devlink->lock);
3165 		list_for_each_entry(param_item, &devlink->param_list, list) {
3166 			if (idx < start) {
3167 				idx++;
3168 				continue;
3169 			}
3170 			err = devlink_nl_param_fill(msg, devlink, 0, param_item,
3171 						    DEVLINK_CMD_PARAM_GET,
3172 						    NETLINK_CB(cb->skb).portid,
3173 						    cb->nlh->nlmsg_seq,
3174 						    NLM_F_MULTI);
3175 			if (err && err != -EOPNOTSUPP) {
3176 				mutex_unlock(&devlink->lock);
3177 				goto out;
3178 			}
3179 			idx++;
3180 		}
3181 		mutex_unlock(&devlink->lock);
3182 	}
3183 out:
3184 	mutex_unlock(&devlink_mutex);
3185 
3186 	cb->args[0] = idx;
3187 	return msg->len;
3188 }
3189 
3190 static int
devlink_param_type_get_from_info(struct genl_info * info,enum devlink_param_type * param_type)3191 devlink_param_type_get_from_info(struct genl_info *info,
3192 				 enum devlink_param_type *param_type)
3193 {
3194 	if (!info->attrs[DEVLINK_ATTR_PARAM_TYPE])
3195 		return -EINVAL;
3196 
3197 	switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) {
3198 	case NLA_U8:
3199 		*param_type = DEVLINK_PARAM_TYPE_U8;
3200 		break;
3201 	case NLA_U16:
3202 		*param_type = DEVLINK_PARAM_TYPE_U16;
3203 		break;
3204 	case NLA_U32:
3205 		*param_type = DEVLINK_PARAM_TYPE_U32;
3206 		break;
3207 	case NLA_STRING:
3208 		*param_type = DEVLINK_PARAM_TYPE_STRING;
3209 		break;
3210 	case NLA_FLAG:
3211 		*param_type = DEVLINK_PARAM_TYPE_BOOL;
3212 		break;
3213 	default:
3214 		return -EINVAL;
3215 	}
3216 
3217 	return 0;
3218 }
3219 
3220 static int
devlink_param_value_get_from_info(const struct devlink_param * param,struct genl_info * info,union devlink_param_value * value)3221 devlink_param_value_get_from_info(const struct devlink_param *param,
3222 				  struct genl_info *info,
3223 				  union devlink_param_value *value)
3224 {
3225 	int len;
3226 
3227 	if (param->type != DEVLINK_PARAM_TYPE_BOOL &&
3228 	    !info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])
3229 		return -EINVAL;
3230 
3231 	switch (param->type) {
3232 	case DEVLINK_PARAM_TYPE_U8:
3233 		value->vu8 = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
3234 		break;
3235 	case DEVLINK_PARAM_TYPE_U16:
3236 		value->vu16 = nla_get_u16(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
3237 		break;
3238 	case DEVLINK_PARAM_TYPE_U32:
3239 		value->vu32 = nla_get_u32(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
3240 		break;
3241 	case DEVLINK_PARAM_TYPE_STRING:
3242 		len = strnlen(nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]),
3243 			      nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]));
3244 		if (len == nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) ||
3245 		    len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
3246 			return -EINVAL;
3247 		strcpy(value->vstr,
3248 		       nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]));
3249 		break;
3250 	case DEVLINK_PARAM_TYPE_BOOL:
3251 		value->vbool = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA] ?
3252 			       true : false;
3253 		break;
3254 	}
3255 	return 0;
3256 }
3257 
3258 static struct devlink_param_item *
devlink_param_get_from_info(struct list_head * param_list,struct genl_info * info)3259 devlink_param_get_from_info(struct list_head *param_list,
3260 			    struct genl_info *info)
3261 {
3262 	char *param_name;
3263 
3264 	if (!info->attrs[DEVLINK_ATTR_PARAM_NAME])
3265 		return NULL;
3266 
3267 	param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]);
3268 	return devlink_param_find_by_name(param_list, param_name);
3269 }
3270 
devlink_nl_cmd_param_get_doit(struct sk_buff * skb,struct genl_info * info)3271 static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb,
3272 					 struct genl_info *info)
3273 {
3274 	struct devlink *devlink = info->user_ptr[0];
3275 	struct devlink_param_item *param_item;
3276 	struct sk_buff *msg;
3277 	int err;
3278 
3279 	param_item = devlink_param_get_from_info(&devlink->param_list, info);
3280 	if (!param_item)
3281 		return -EINVAL;
3282 
3283 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3284 	if (!msg)
3285 		return -ENOMEM;
3286 
3287 	err = devlink_nl_param_fill(msg, devlink, 0, param_item,
3288 				    DEVLINK_CMD_PARAM_GET,
3289 				    info->snd_portid, info->snd_seq, 0);
3290 	if (err) {
3291 		nlmsg_free(msg);
3292 		return err;
3293 	}
3294 
3295 	return genlmsg_reply(msg, info);
3296 }
3297 
__devlink_nl_cmd_param_set_doit(struct devlink * devlink,unsigned int port_index,struct list_head * param_list,struct genl_info * info,enum devlink_command cmd)3298 static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
3299 					   unsigned int port_index,
3300 					   struct list_head *param_list,
3301 					   struct genl_info *info,
3302 					   enum devlink_command cmd)
3303 {
3304 	enum devlink_param_type param_type;
3305 	struct devlink_param_gset_ctx ctx;
3306 	enum devlink_param_cmode cmode;
3307 	struct devlink_param_item *param_item;
3308 	const struct devlink_param *param;
3309 	union devlink_param_value value;
3310 	int err = 0;
3311 
3312 	param_item = devlink_param_get_from_info(param_list, info);
3313 	if (!param_item)
3314 		return -EINVAL;
3315 	param = param_item->param;
3316 	err = devlink_param_type_get_from_info(info, &param_type);
3317 	if (err)
3318 		return err;
3319 	if (param_type != param->type)
3320 		return -EINVAL;
3321 	err = devlink_param_value_get_from_info(param, info, &value);
3322 	if (err)
3323 		return err;
3324 	if (param->validate) {
3325 		err = param->validate(devlink, param->id, value, info->extack);
3326 		if (err)
3327 			return err;
3328 	}
3329 
3330 	if (!info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE])
3331 		return -EINVAL;
3332 	cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
3333 	if (!devlink_param_cmode_is_supported(param, cmode))
3334 		return -EOPNOTSUPP;
3335 
3336 	if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
3337 		if (param->type == DEVLINK_PARAM_TYPE_STRING)
3338 			strcpy(param_item->driverinit_value.vstr, value.vstr);
3339 		else
3340 			param_item->driverinit_value = value;
3341 		param_item->driverinit_value_valid = true;
3342 	} else {
3343 		if (!param->set)
3344 			return -EOPNOTSUPP;
3345 		ctx.val = value;
3346 		ctx.cmode = cmode;
3347 		err = devlink_param_set(devlink, param, &ctx);
3348 		if (err)
3349 			return err;
3350 	}
3351 
3352 	devlink_param_notify(devlink, port_index, param_item, cmd);
3353 	return 0;
3354 }
3355 
devlink_nl_cmd_param_set_doit(struct sk_buff * skb,struct genl_info * info)3356 static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb,
3357 					 struct genl_info *info)
3358 {
3359 	struct devlink *devlink = info->user_ptr[0];
3360 
3361 	return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->param_list,
3362 					       info, DEVLINK_CMD_PARAM_NEW);
3363 }
3364 
devlink_param_register_one(struct devlink * devlink,unsigned int port_index,struct list_head * param_list,const struct devlink_param * param,enum devlink_command cmd)3365 static int devlink_param_register_one(struct devlink *devlink,
3366 				      unsigned int port_index,
3367 				      struct list_head *param_list,
3368 				      const struct devlink_param *param,
3369 				      enum devlink_command cmd)
3370 {
3371 	struct devlink_param_item *param_item;
3372 
3373 	if (devlink_param_find_by_name(param_list, param->name))
3374 		return -EEXIST;
3375 
3376 	if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
3377 		WARN_ON(param->get || param->set);
3378 	else
3379 		WARN_ON(!param->get || !param->set);
3380 
3381 	param_item = kzalloc(sizeof(*param_item), GFP_KERNEL);
3382 	if (!param_item)
3383 		return -ENOMEM;
3384 	param_item->param = param;
3385 
3386 	list_add_tail(&param_item->list, param_list);
3387 	devlink_param_notify(devlink, port_index, param_item, cmd);
3388 	return 0;
3389 }
3390 
devlink_param_unregister_one(struct devlink * devlink,unsigned int port_index,struct list_head * param_list,const struct devlink_param * param,enum devlink_command cmd)3391 static void devlink_param_unregister_one(struct devlink *devlink,
3392 					 unsigned int port_index,
3393 					 struct list_head *param_list,
3394 					 const struct devlink_param *param,
3395 					 enum devlink_command cmd)
3396 {
3397 	struct devlink_param_item *param_item;
3398 
3399 	param_item = devlink_param_find_by_name(param_list, param->name);
3400 	WARN_ON(!param_item);
3401 	devlink_param_notify(devlink, port_index, param_item, cmd);
3402 	list_del(&param_item->list);
3403 	kfree(param_item);
3404 }
3405 
devlink_nl_cmd_port_param_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)3406 static int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg,
3407 						struct netlink_callback *cb)
3408 {
3409 	struct devlink_param_item *param_item;
3410 	struct devlink_port *devlink_port;
3411 	struct devlink *devlink;
3412 	int start = cb->args[0];
3413 	int idx = 0;
3414 	int err;
3415 
3416 	mutex_lock(&devlink_mutex);
3417 	list_for_each_entry(devlink, &devlink_list, list) {
3418 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3419 			continue;
3420 		mutex_lock(&devlink->lock);
3421 		list_for_each_entry(devlink_port, &devlink->port_list, list) {
3422 			list_for_each_entry(param_item,
3423 					    &devlink_port->param_list, list) {
3424 				if (idx < start) {
3425 					idx++;
3426 					continue;
3427 				}
3428 				err = devlink_nl_param_fill(msg,
3429 						devlink_port->devlink,
3430 						devlink_port->index, param_item,
3431 						DEVLINK_CMD_PORT_PARAM_GET,
3432 						NETLINK_CB(cb->skb).portid,
3433 						cb->nlh->nlmsg_seq,
3434 						NLM_F_MULTI);
3435 				if (err && err != -EOPNOTSUPP) {
3436 					mutex_unlock(&devlink->lock);
3437 					goto out;
3438 				}
3439 				idx++;
3440 			}
3441 		}
3442 		mutex_unlock(&devlink->lock);
3443 	}
3444 out:
3445 	mutex_unlock(&devlink_mutex);
3446 
3447 	cb->args[0] = idx;
3448 	return msg->len;
3449 }
3450 
devlink_nl_cmd_port_param_get_doit(struct sk_buff * skb,struct genl_info * info)3451 static int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb,
3452 					      struct genl_info *info)
3453 {
3454 	struct devlink_port *devlink_port = info->user_ptr[0];
3455 	struct devlink_param_item *param_item;
3456 	struct sk_buff *msg;
3457 	int err;
3458 
3459 	param_item = devlink_param_get_from_info(&devlink_port->param_list,
3460 						 info);
3461 	if (!param_item)
3462 		return -EINVAL;
3463 
3464 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3465 	if (!msg)
3466 		return -ENOMEM;
3467 
3468 	err = devlink_nl_param_fill(msg, devlink_port->devlink,
3469 				    devlink_port->index, param_item,
3470 				    DEVLINK_CMD_PORT_PARAM_GET,
3471 				    info->snd_portid, info->snd_seq, 0);
3472 	if (err) {
3473 		nlmsg_free(msg);
3474 		return err;
3475 	}
3476 
3477 	return genlmsg_reply(msg, info);
3478 }
3479 
devlink_nl_cmd_port_param_set_doit(struct sk_buff * skb,struct genl_info * info)3480 static int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb,
3481 					      struct genl_info *info)
3482 {
3483 	struct devlink_port *devlink_port = info->user_ptr[0];
3484 
3485 	return __devlink_nl_cmd_param_set_doit(devlink_port->devlink,
3486 					       devlink_port->index,
3487 					       &devlink_port->param_list, info,
3488 					       DEVLINK_CMD_PORT_PARAM_NEW);
3489 }
3490 
devlink_nl_region_snapshot_id_put(struct sk_buff * msg,struct devlink * devlink,struct devlink_snapshot * snapshot)3491 static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg,
3492 					     struct devlink *devlink,
3493 					     struct devlink_snapshot *snapshot)
3494 {
3495 	struct nlattr *snap_attr;
3496 	int err;
3497 
3498 	snap_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_SNAPSHOT);
3499 	if (!snap_attr)
3500 		return -EINVAL;
3501 
3502 	err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id);
3503 	if (err)
3504 		goto nla_put_failure;
3505 
3506 	nla_nest_end(msg, snap_attr);
3507 	return 0;
3508 
3509 nla_put_failure:
3510 	nla_nest_cancel(msg, snap_attr);
3511 	return err;
3512 }
3513 
devlink_nl_region_snapshots_id_put(struct sk_buff * msg,struct devlink * devlink,struct devlink_region * region)3514 static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg,
3515 					      struct devlink *devlink,
3516 					      struct devlink_region *region)
3517 {
3518 	struct devlink_snapshot *snapshot;
3519 	struct nlattr *snapshots_attr;
3520 	int err;
3521 
3522 	snapshots_attr = nla_nest_start_noflag(msg,
3523 					       DEVLINK_ATTR_REGION_SNAPSHOTS);
3524 	if (!snapshots_attr)
3525 		return -EINVAL;
3526 
3527 	list_for_each_entry(snapshot, &region->snapshot_list, list) {
3528 		err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot);
3529 		if (err)
3530 			goto nla_put_failure;
3531 	}
3532 
3533 	nla_nest_end(msg, snapshots_attr);
3534 	return 0;
3535 
3536 nla_put_failure:
3537 	nla_nest_cancel(msg, snapshots_attr);
3538 	return err;
3539 }
3540 
devlink_nl_region_fill(struct sk_buff * msg,struct devlink * devlink,enum devlink_command cmd,u32 portid,u32 seq,int flags,struct devlink_region * region)3541 static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink,
3542 				  enum devlink_command cmd, u32 portid,
3543 				  u32 seq, int flags,
3544 				  struct devlink_region *region)
3545 {
3546 	void *hdr;
3547 	int err;
3548 
3549 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
3550 	if (!hdr)
3551 		return -EMSGSIZE;
3552 
3553 	err = devlink_nl_put_handle(msg, devlink);
3554 	if (err)
3555 		goto nla_put_failure;
3556 
3557 	err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->name);
3558 	if (err)
3559 		goto nla_put_failure;
3560 
3561 	err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
3562 				region->size,
3563 				DEVLINK_ATTR_PAD);
3564 	if (err)
3565 		goto nla_put_failure;
3566 
3567 	err = devlink_nl_region_snapshots_id_put(msg, devlink, region);
3568 	if (err)
3569 		goto nla_put_failure;
3570 
3571 	genlmsg_end(msg, hdr);
3572 	return 0;
3573 
3574 nla_put_failure:
3575 	genlmsg_cancel(msg, hdr);
3576 	return err;
3577 }
3578 
devlink_nl_region_notify(struct devlink_region * region,struct devlink_snapshot * snapshot,enum devlink_command cmd)3579 static void devlink_nl_region_notify(struct devlink_region *region,
3580 				     struct devlink_snapshot *snapshot,
3581 				     enum devlink_command cmd)
3582 {
3583 	struct devlink *devlink = region->devlink;
3584 	struct sk_buff *msg;
3585 	void *hdr;
3586 	int err;
3587 
3588 	WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL);
3589 
3590 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3591 	if (!msg)
3592 		return;
3593 
3594 	hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd);
3595 	if (!hdr)
3596 		goto out_free_msg;
3597 
3598 	err = devlink_nl_put_handle(msg, devlink);
3599 	if (err)
3600 		goto out_cancel_msg;
3601 
3602 	err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME,
3603 			     region->name);
3604 	if (err)
3605 		goto out_cancel_msg;
3606 
3607 	if (snapshot) {
3608 		err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID,
3609 				  snapshot->id);
3610 		if (err)
3611 			goto out_cancel_msg;
3612 	} else {
3613 		err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
3614 					region->size, DEVLINK_ATTR_PAD);
3615 		if (err)
3616 			goto out_cancel_msg;
3617 	}
3618 	genlmsg_end(msg, hdr);
3619 
3620 	genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
3621 				msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
3622 
3623 	return;
3624 
3625 out_cancel_msg:
3626 	genlmsg_cancel(msg, hdr);
3627 out_free_msg:
3628 	nlmsg_free(msg);
3629 }
3630 
devlink_region_snapshot_del(struct devlink_region * region,struct devlink_snapshot * snapshot)3631 static void devlink_region_snapshot_del(struct devlink_region *region,
3632 					struct devlink_snapshot *snapshot)
3633 {
3634 	devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL);
3635 	region->cur_snapshots--;
3636 	list_del(&snapshot->list);
3637 	(*snapshot->data_destructor)(snapshot->data);
3638 	kfree(snapshot);
3639 }
3640 
devlink_nl_cmd_region_get_doit(struct sk_buff * skb,struct genl_info * info)3641 static int devlink_nl_cmd_region_get_doit(struct sk_buff *skb,
3642 					  struct genl_info *info)
3643 {
3644 	struct devlink *devlink = info->user_ptr[0];
3645 	struct devlink_region *region;
3646 	const char *region_name;
3647 	struct sk_buff *msg;
3648 	int err;
3649 
3650 	if (!info->attrs[DEVLINK_ATTR_REGION_NAME])
3651 		return -EINVAL;
3652 
3653 	region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
3654 	region = devlink_region_get_by_name(devlink, region_name);
3655 	if (!region)
3656 		return -EINVAL;
3657 
3658 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3659 	if (!msg)
3660 		return -ENOMEM;
3661 
3662 	err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET,
3663 				     info->snd_portid, info->snd_seq, 0,
3664 				     region);
3665 	if (err) {
3666 		nlmsg_free(msg);
3667 		return err;
3668 	}
3669 
3670 	return genlmsg_reply(msg, info);
3671 }
3672 
devlink_nl_cmd_region_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)3673 static int devlink_nl_cmd_region_get_dumpit(struct sk_buff *msg,
3674 					    struct netlink_callback *cb)
3675 {
3676 	struct devlink_region *region;
3677 	struct devlink *devlink;
3678 	int start = cb->args[0];
3679 	int idx = 0;
3680 	int err;
3681 
3682 	mutex_lock(&devlink_mutex);
3683 	list_for_each_entry(devlink, &devlink_list, list) {
3684 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3685 			continue;
3686 
3687 		mutex_lock(&devlink->lock);
3688 		list_for_each_entry(region, &devlink->region_list, list) {
3689 			if (idx < start) {
3690 				idx++;
3691 				continue;
3692 			}
3693 			err = devlink_nl_region_fill(msg, devlink,
3694 						     DEVLINK_CMD_REGION_GET,
3695 						     NETLINK_CB(cb->skb).portid,
3696 						     cb->nlh->nlmsg_seq,
3697 						     NLM_F_MULTI, region);
3698 			if (err) {
3699 				mutex_unlock(&devlink->lock);
3700 				goto out;
3701 			}
3702 			idx++;
3703 		}
3704 		mutex_unlock(&devlink->lock);
3705 	}
3706 out:
3707 	mutex_unlock(&devlink_mutex);
3708 	cb->args[0] = idx;
3709 	return msg->len;
3710 }
3711 
devlink_nl_cmd_region_del(struct sk_buff * skb,struct genl_info * info)3712 static int devlink_nl_cmd_region_del(struct sk_buff *skb,
3713 				     struct genl_info *info)
3714 {
3715 	struct devlink *devlink = info->user_ptr[0];
3716 	struct devlink_snapshot *snapshot;
3717 	struct devlink_region *region;
3718 	const char *region_name;
3719 	u32 snapshot_id;
3720 
3721 	if (!info->attrs[DEVLINK_ATTR_REGION_NAME] ||
3722 	    !info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID])
3723 		return -EINVAL;
3724 
3725 	region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
3726 	snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
3727 
3728 	region = devlink_region_get_by_name(devlink, region_name);
3729 	if (!region)
3730 		return -EINVAL;
3731 
3732 	snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
3733 	if (!snapshot)
3734 		return -EINVAL;
3735 
3736 	devlink_region_snapshot_del(region, snapshot);
3737 	return 0;
3738 }
3739 
devlink_nl_cmd_region_read_chunk_fill(struct sk_buff * msg,struct devlink * devlink,u8 * chunk,u32 chunk_size,u64 addr)3740 static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg,
3741 						 struct devlink *devlink,
3742 						 u8 *chunk, u32 chunk_size,
3743 						 u64 addr)
3744 {
3745 	struct nlattr *chunk_attr;
3746 	int err;
3747 
3748 	chunk_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_CHUNK);
3749 	if (!chunk_attr)
3750 		return -EINVAL;
3751 
3752 	err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk);
3753 	if (err)
3754 		goto nla_put_failure;
3755 
3756 	err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr,
3757 				DEVLINK_ATTR_PAD);
3758 	if (err)
3759 		goto nla_put_failure;
3760 
3761 	nla_nest_end(msg, chunk_attr);
3762 	return 0;
3763 
3764 nla_put_failure:
3765 	nla_nest_cancel(msg, chunk_attr);
3766 	return err;
3767 }
3768 
3769 #define DEVLINK_REGION_READ_CHUNK_SIZE 256
3770 
devlink_nl_region_read_snapshot_fill(struct sk_buff * skb,struct devlink * devlink,struct devlink_region * region,struct nlattr ** attrs,u64 start_offset,u64 end_offset,bool dump,u64 * new_offset)3771 static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb,
3772 						struct devlink *devlink,
3773 						struct devlink_region *region,
3774 						struct nlattr **attrs,
3775 						u64 start_offset,
3776 						u64 end_offset,
3777 						bool dump,
3778 						u64 *new_offset)
3779 {
3780 	struct devlink_snapshot *snapshot;
3781 	u64 curr_offset = start_offset;
3782 	u32 snapshot_id;
3783 	int err = 0;
3784 
3785 	*new_offset = start_offset;
3786 
3787 	snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
3788 	snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
3789 	if (!snapshot)
3790 		return -EINVAL;
3791 
3792 	if (end_offset > region->size || dump)
3793 		end_offset = region->size;
3794 
3795 	while (curr_offset < end_offset) {
3796 		u32 data_size;
3797 		u8 *data;
3798 
3799 		if (end_offset - curr_offset < DEVLINK_REGION_READ_CHUNK_SIZE)
3800 			data_size = end_offset - curr_offset;
3801 		else
3802 			data_size = DEVLINK_REGION_READ_CHUNK_SIZE;
3803 
3804 		data = &snapshot->data[curr_offset];
3805 		err = devlink_nl_cmd_region_read_chunk_fill(skb, devlink,
3806 							    data, data_size,
3807 							    curr_offset);
3808 		if (err)
3809 			break;
3810 
3811 		curr_offset += data_size;
3812 	}
3813 	*new_offset = curr_offset;
3814 
3815 	return err;
3816 }
3817 
devlink_nl_cmd_region_read_dumpit(struct sk_buff * skb,struct netlink_callback * cb)3818 static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
3819 					     struct netlink_callback *cb)
3820 {
3821 	u64 ret_offset, start_offset, end_offset = 0;
3822 	struct devlink_region *region;
3823 	struct nlattr *chunks_attr;
3824 	const char *region_name;
3825 	struct devlink *devlink;
3826 	struct nlattr **attrs;
3827 	bool dump = true;
3828 	void *hdr;
3829 	int err;
3830 
3831 	start_offset = *((u64 *)&cb->args[0]);
3832 
3833 	attrs = kmalloc_array(DEVLINK_ATTR_MAX + 1, sizeof(*attrs), GFP_KERNEL);
3834 	if (!attrs)
3835 		return -ENOMEM;
3836 
3837 	err = nlmsg_parse_deprecated(cb->nlh,
3838 				     GENL_HDRLEN + devlink_nl_family.hdrsize,
3839 				     attrs, DEVLINK_ATTR_MAX,
3840 				     devlink_nl_family.policy, cb->extack);
3841 	if (err)
3842 		goto out_free;
3843 
3844 	mutex_lock(&devlink_mutex);
3845 	devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
3846 	if (IS_ERR(devlink)) {
3847 		err = PTR_ERR(devlink);
3848 		goto out_dev;
3849 	}
3850 
3851 	mutex_lock(&devlink->lock);
3852 
3853 	if (!attrs[DEVLINK_ATTR_REGION_NAME] ||
3854 	    !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) {
3855 		err = -EINVAL;
3856 		goto out_unlock;
3857 	}
3858 
3859 	region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]);
3860 	region = devlink_region_get_by_name(devlink, region_name);
3861 	if (!region) {
3862 		err = -EINVAL;
3863 		goto out_unlock;
3864 	}
3865 
3866 	hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
3867 			  &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
3868 			  DEVLINK_CMD_REGION_READ);
3869 	if (!hdr) {
3870 		err = -EMSGSIZE;
3871 		goto out_unlock;
3872 	}
3873 
3874 	err = devlink_nl_put_handle(skb, devlink);
3875 	if (err)
3876 		goto nla_put_failure;
3877 
3878 	err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
3879 	if (err)
3880 		goto nla_put_failure;
3881 
3882 	chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS);
3883 	if (!chunks_attr) {
3884 		err = -EMSGSIZE;
3885 		goto nla_put_failure;
3886 	}
3887 
3888 	if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] &&
3889 	    attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) {
3890 		if (!start_offset)
3891 			start_offset =
3892 				nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
3893 
3894 		end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
3895 		end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]);
3896 		dump = false;
3897 	}
3898 
3899 	err = devlink_nl_region_read_snapshot_fill(skb, devlink,
3900 						   region, attrs,
3901 						   start_offset,
3902 						   end_offset, dump,
3903 						   &ret_offset);
3904 
3905 	if (err && err != -EMSGSIZE)
3906 		goto nla_put_failure;
3907 
3908 	/* Check if there was any progress done to prevent infinite loop */
3909 	if (ret_offset == start_offset) {
3910 		err = -EINVAL;
3911 		goto nla_put_failure;
3912 	}
3913 
3914 	*((u64 *)&cb->args[0]) = ret_offset;
3915 
3916 	nla_nest_end(skb, chunks_attr);
3917 	genlmsg_end(skb, hdr);
3918 	mutex_unlock(&devlink->lock);
3919 	mutex_unlock(&devlink_mutex);
3920 	kfree(attrs);
3921 
3922 	return skb->len;
3923 
3924 nla_put_failure:
3925 	genlmsg_cancel(skb, hdr);
3926 out_unlock:
3927 	mutex_unlock(&devlink->lock);
3928 out_dev:
3929 	mutex_unlock(&devlink_mutex);
3930 out_free:
3931 	kfree(attrs);
3932 	return err;
3933 }
3934 
3935 struct devlink_info_req {
3936 	struct sk_buff *msg;
3937 };
3938 
devlink_info_driver_name_put(struct devlink_info_req * req,const char * name)3939 int devlink_info_driver_name_put(struct devlink_info_req *req, const char *name)
3940 {
3941 	return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRIVER_NAME, name);
3942 }
3943 EXPORT_SYMBOL_GPL(devlink_info_driver_name_put);
3944 
devlink_info_serial_number_put(struct devlink_info_req * req,const char * sn)3945 int devlink_info_serial_number_put(struct devlink_info_req *req, const char *sn)
3946 {
3947 	return nla_put_string(req->msg, DEVLINK_ATTR_INFO_SERIAL_NUMBER, sn);
3948 }
3949 EXPORT_SYMBOL_GPL(devlink_info_serial_number_put);
3950 
devlink_info_version_put(struct devlink_info_req * req,int attr,const char * version_name,const char * version_value)3951 static int devlink_info_version_put(struct devlink_info_req *req, int attr,
3952 				    const char *version_name,
3953 				    const char *version_value)
3954 {
3955 	struct nlattr *nest;
3956 	int err;
3957 
3958 	nest = nla_nest_start_noflag(req->msg, attr);
3959 	if (!nest)
3960 		return -EMSGSIZE;
3961 
3962 	err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_NAME,
3963 			     version_name);
3964 	if (err)
3965 		goto nla_put_failure;
3966 
3967 	err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_VALUE,
3968 			     version_value);
3969 	if (err)
3970 		goto nla_put_failure;
3971 
3972 	nla_nest_end(req->msg, nest);
3973 
3974 	return 0;
3975 
3976 nla_put_failure:
3977 	nla_nest_cancel(req->msg, nest);
3978 	return err;
3979 }
3980 
devlink_info_version_fixed_put(struct devlink_info_req * req,const char * version_name,const char * version_value)3981 int devlink_info_version_fixed_put(struct devlink_info_req *req,
3982 				   const char *version_name,
3983 				   const char *version_value)
3984 {
3985 	return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_FIXED,
3986 					version_name, version_value);
3987 }
3988 EXPORT_SYMBOL_GPL(devlink_info_version_fixed_put);
3989 
devlink_info_version_stored_put(struct devlink_info_req * req,const char * version_name,const char * version_value)3990 int devlink_info_version_stored_put(struct devlink_info_req *req,
3991 				    const char *version_name,
3992 				    const char *version_value)
3993 {
3994 	return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_STORED,
3995 					version_name, version_value);
3996 }
3997 EXPORT_SYMBOL_GPL(devlink_info_version_stored_put);
3998 
devlink_info_version_running_put(struct devlink_info_req * req,const char * version_name,const char * version_value)3999 int devlink_info_version_running_put(struct devlink_info_req *req,
4000 				     const char *version_name,
4001 				     const char *version_value)
4002 {
4003 	return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_RUNNING,
4004 					version_name, version_value);
4005 }
4006 EXPORT_SYMBOL_GPL(devlink_info_version_running_put);
4007 
4008 static int
devlink_nl_info_fill(struct sk_buff * msg,struct devlink * devlink,enum devlink_command cmd,u32 portid,u32 seq,int flags,struct netlink_ext_ack * extack)4009 devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
4010 		     enum devlink_command cmd, u32 portid,
4011 		     u32 seq, int flags, struct netlink_ext_ack *extack)
4012 {
4013 	struct devlink_info_req req;
4014 	void *hdr;
4015 	int err;
4016 
4017 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
4018 	if (!hdr)
4019 		return -EMSGSIZE;
4020 
4021 	err = -EMSGSIZE;
4022 	if (devlink_nl_put_handle(msg, devlink))
4023 		goto err_cancel_msg;
4024 
4025 	req.msg = msg;
4026 	err = devlink->ops->info_get(devlink, &req, extack);
4027 	if (err)
4028 		goto err_cancel_msg;
4029 
4030 	genlmsg_end(msg, hdr);
4031 	return 0;
4032 
4033 err_cancel_msg:
4034 	genlmsg_cancel(msg, hdr);
4035 	return err;
4036 }
4037 
devlink_nl_cmd_info_get_doit(struct sk_buff * skb,struct genl_info * info)4038 static int devlink_nl_cmd_info_get_doit(struct sk_buff *skb,
4039 					struct genl_info *info)
4040 {
4041 	struct devlink *devlink = info->user_ptr[0];
4042 	struct sk_buff *msg;
4043 	int err;
4044 
4045 	if (!devlink->ops->info_get)
4046 		return -EOPNOTSUPP;
4047 
4048 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4049 	if (!msg)
4050 		return -ENOMEM;
4051 
4052 	err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
4053 				   info->snd_portid, info->snd_seq, 0,
4054 				   info->extack);
4055 	if (err) {
4056 		nlmsg_free(msg);
4057 		return err;
4058 	}
4059 
4060 	return genlmsg_reply(msg, info);
4061 }
4062 
devlink_nl_cmd_info_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)4063 static int devlink_nl_cmd_info_get_dumpit(struct sk_buff *msg,
4064 					  struct netlink_callback *cb)
4065 {
4066 	struct devlink *devlink;
4067 	int start = cb->args[0];
4068 	int idx = 0;
4069 	int err;
4070 
4071 	mutex_lock(&devlink_mutex);
4072 	list_for_each_entry(devlink, &devlink_list, list) {
4073 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
4074 			continue;
4075 		if (idx < start) {
4076 			idx++;
4077 			continue;
4078 		}
4079 
4080 		if (!devlink->ops->info_get) {
4081 			idx++;
4082 			continue;
4083 		}
4084 
4085 		mutex_lock(&devlink->lock);
4086 		err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
4087 					   NETLINK_CB(cb->skb).portid,
4088 					   cb->nlh->nlmsg_seq, NLM_F_MULTI,
4089 					   cb->extack);
4090 		mutex_unlock(&devlink->lock);
4091 		if (err && err != -EOPNOTSUPP)
4092 			break;
4093 		idx++;
4094 	}
4095 	mutex_unlock(&devlink_mutex);
4096 
4097 	cb->args[0] = idx;
4098 	return msg->len;
4099 }
4100 
4101 struct devlink_fmsg_item {
4102 	struct list_head list;
4103 	int attrtype;
4104 	u8 nla_type;
4105 	u16 len;
4106 	int value[0];
4107 };
4108 
4109 struct devlink_fmsg {
4110 	struct list_head item_list;
4111 };
4112 
devlink_fmsg_alloc(void)4113 static struct devlink_fmsg *devlink_fmsg_alloc(void)
4114 {
4115 	struct devlink_fmsg *fmsg;
4116 
4117 	fmsg = kzalloc(sizeof(*fmsg), GFP_KERNEL);
4118 	if (!fmsg)
4119 		return NULL;
4120 
4121 	INIT_LIST_HEAD(&fmsg->item_list);
4122 
4123 	return fmsg;
4124 }
4125 
devlink_fmsg_free(struct devlink_fmsg * fmsg)4126 static void devlink_fmsg_free(struct devlink_fmsg *fmsg)
4127 {
4128 	struct devlink_fmsg_item *item, *tmp;
4129 
4130 	list_for_each_entry_safe(item, tmp, &fmsg->item_list, list) {
4131 		list_del(&item->list);
4132 		kfree(item);
4133 	}
4134 	kfree(fmsg);
4135 }
4136 
devlink_fmsg_nest_common(struct devlink_fmsg * fmsg,int attrtype)4137 static int devlink_fmsg_nest_common(struct devlink_fmsg *fmsg,
4138 				    int attrtype)
4139 {
4140 	struct devlink_fmsg_item *item;
4141 
4142 	item = kzalloc(sizeof(*item), GFP_KERNEL);
4143 	if (!item)
4144 		return -ENOMEM;
4145 
4146 	item->attrtype = attrtype;
4147 	list_add_tail(&item->list, &fmsg->item_list);
4148 
4149 	return 0;
4150 }
4151 
devlink_fmsg_obj_nest_start(struct devlink_fmsg * fmsg)4152 int devlink_fmsg_obj_nest_start(struct devlink_fmsg *fmsg)
4153 {
4154 	return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_OBJ_NEST_START);
4155 }
4156 EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_start);
4157 
devlink_fmsg_nest_end(struct devlink_fmsg * fmsg)4158 static int devlink_fmsg_nest_end(struct devlink_fmsg *fmsg)
4159 {
4160 	return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_NEST_END);
4161 }
4162 
devlink_fmsg_obj_nest_end(struct devlink_fmsg * fmsg)4163 int devlink_fmsg_obj_nest_end(struct devlink_fmsg *fmsg)
4164 {
4165 	return devlink_fmsg_nest_end(fmsg);
4166 }
4167 EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_end);
4168 
4169 #define DEVLINK_FMSG_MAX_SIZE (GENLMSG_DEFAULT_SIZE - GENL_HDRLEN - NLA_HDRLEN)
4170 
devlink_fmsg_put_name(struct devlink_fmsg * fmsg,const char * name)4171 static int devlink_fmsg_put_name(struct devlink_fmsg *fmsg, const char *name)
4172 {
4173 	struct devlink_fmsg_item *item;
4174 
4175 	if (strlen(name) + 1 > DEVLINK_FMSG_MAX_SIZE)
4176 		return -EMSGSIZE;
4177 
4178 	item = kzalloc(sizeof(*item) + strlen(name) + 1, GFP_KERNEL);
4179 	if (!item)
4180 		return -ENOMEM;
4181 
4182 	item->nla_type = NLA_NUL_STRING;
4183 	item->len = strlen(name) + 1;
4184 	item->attrtype = DEVLINK_ATTR_FMSG_OBJ_NAME;
4185 	memcpy(&item->value, name, item->len);
4186 	list_add_tail(&item->list, &fmsg->item_list);
4187 
4188 	return 0;
4189 }
4190 
devlink_fmsg_pair_nest_start(struct devlink_fmsg * fmsg,const char * name)4191 int devlink_fmsg_pair_nest_start(struct devlink_fmsg *fmsg, const char *name)
4192 {
4193 	int err;
4194 
4195 	err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_PAIR_NEST_START);
4196 	if (err)
4197 		return err;
4198 
4199 	err = devlink_fmsg_put_name(fmsg, name);
4200 	if (err)
4201 		return err;
4202 
4203 	return 0;
4204 }
4205 EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_start);
4206 
devlink_fmsg_pair_nest_end(struct devlink_fmsg * fmsg)4207 int devlink_fmsg_pair_nest_end(struct devlink_fmsg *fmsg)
4208 {
4209 	return devlink_fmsg_nest_end(fmsg);
4210 }
4211 EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_end);
4212 
devlink_fmsg_arr_pair_nest_start(struct devlink_fmsg * fmsg,const char * name)4213 int devlink_fmsg_arr_pair_nest_start(struct devlink_fmsg *fmsg,
4214 				     const char *name)
4215 {
4216 	int err;
4217 
4218 	err = devlink_fmsg_pair_nest_start(fmsg, name);
4219 	if (err)
4220 		return err;
4221 
4222 	err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_ARR_NEST_START);
4223 	if (err)
4224 		return err;
4225 
4226 	return 0;
4227 }
4228 EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_start);
4229 
devlink_fmsg_arr_pair_nest_end(struct devlink_fmsg * fmsg)4230 int devlink_fmsg_arr_pair_nest_end(struct devlink_fmsg *fmsg)
4231 {
4232 	int err;
4233 
4234 	err = devlink_fmsg_nest_end(fmsg);
4235 	if (err)
4236 		return err;
4237 
4238 	err = devlink_fmsg_nest_end(fmsg);
4239 	if (err)
4240 		return err;
4241 
4242 	return 0;
4243 }
4244 EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_end);
4245 
devlink_fmsg_put_value(struct devlink_fmsg * fmsg,const void * value,u16 value_len,u8 value_nla_type)4246 static int devlink_fmsg_put_value(struct devlink_fmsg *fmsg,
4247 				  const void *value, u16 value_len,
4248 				  u8 value_nla_type)
4249 {
4250 	struct devlink_fmsg_item *item;
4251 
4252 	if (value_len > DEVLINK_FMSG_MAX_SIZE)
4253 		return -EMSGSIZE;
4254 
4255 	item = kzalloc(sizeof(*item) + value_len, GFP_KERNEL);
4256 	if (!item)
4257 		return -ENOMEM;
4258 
4259 	item->nla_type = value_nla_type;
4260 	item->len = value_len;
4261 	item->attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
4262 	memcpy(&item->value, value, item->len);
4263 	list_add_tail(&item->list, &fmsg->item_list);
4264 
4265 	return 0;
4266 }
4267 
devlink_fmsg_bool_put(struct devlink_fmsg * fmsg,bool value)4268 int devlink_fmsg_bool_put(struct devlink_fmsg *fmsg, bool value)
4269 {
4270 	return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_FLAG);
4271 }
4272 EXPORT_SYMBOL_GPL(devlink_fmsg_bool_put);
4273 
devlink_fmsg_u8_put(struct devlink_fmsg * fmsg,u8 value)4274 int devlink_fmsg_u8_put(struct devlink_fmsg *fmsg, u8 value)
4275 {
4276 	return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U8);
4277 }
4278 EXPORT_SYMBOL_GPL(devlink_fmsg_u8_put);
4279 
devlink_fmsg_u32_put(struct devlink_fmsg * fmsg,u32 value)4280 int devlink_fmsg_u32_put(struct devlink_fmsg *fmsg, u32 value)
4281 {
4282 	return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U32);
4283 }
4284 EXPORT_SYMBOL_GPL(devlink_fmsg_u32_put);
4285 
devlink_fmsg_u64_put(struct devlink_fmsg * fmsg,u64 value)4286 int devlink_fmsg_u64_put(struct devlink_fmsg *fmsg, u64 value)
4287 {
4288 	return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U64);
4289 }
4290 EXPORT_SYMBOL_GPL(devlink_fmsg_u64_put);
4291 
devlink_fmsg_string_put(struct devlink_fmsg * fmsg,const char * value)4292 int devlink_fmsg_string_put(struct devlink_fmsg *fmsg, const char *value)
4293 {
4294 	return devlink_fmsg_put_value(fmsg, value, strlen(value) + 1,
4295 				      NLA_NUL_STRING);
4296 }
4297 EXPORT_SYMBOL_GPL(devlink_fmsg_string_put);
4298 
devlink_fmsg_binary_put(struct devlink_fmsg * fmsg,const void * value,u16 value_len)4299 int devlink_fmsg_binary_put(struct devlink_fmsg *fmsg, const void *value,
4300 			    u16 value_len)
4301 {
4302 	return devlink_fmsg_put_value(fmsg, value, value_len, NLA_BINARY);
4303 }
4304 EXPORT_SYMBOL_GPL(devlink_fmsg_binary_put);
4305 
devlink_fmsg_bool_pair_put(struct devlink_fmsg * fmsg,const char * name,bool value)4306 int devlink_fmsg_bool_pair_put(struct devlink_fmsg *fmsg, const char *name,
4307 			       bool value)
4308 {
4309 	int err;
4310 
4311 	err = devlink_fmsg_pair_nest_start(fmsg, name);
4312 	if (err)
4313 		return err;
4314 
4315 	err = devlink_fmsg_bool_put(fmsg, value);
4316 	if (err)
4317 		return err;
4318 
4319 	err = devlink_fmsg_pair_nest_end(fmsg);
4320 	if (err)
4321 		return err;
4322 
4323 	return 0;
4324 }
4325 EXPORT_SYMBOL_GPL(devlink_fmsg_bool_pair_put);
4326 
devlink_fmsg_u8_pair_put(struct devlink_fmsg * fmsg,const char * name,u8 value)4327 int devlink_fmsg_u8_pair_put(struct devlink_fmsg *fmsg, const char *name,
4328 			     u8 value)
4329 {
4330 	int err;
4331 
4332 	err = devlink_fmsg_pair_nest_start(fmsg, name);
4333 	if (err)
4334 		return err;
4335 
4336 	err = devlink_fmsg_u8_put(fmsg, value);
4337 	if (err)
4338 		return err;
4339 
4340 	err = devlink_fmsg_pair_nest_end(fmsg);
4341 	if (err)
4342 		return err;
4343 
4344 	return 0;
4345 }
4346 EXPORT_SYMBOL_GPL(devlink_fmsg_u8_pair_put);
4347 
devlink_fmsg_u32_pair_put(struct devlink_fmsg * fmsg,const char * name,u32 value)4348 int devlink_fmsg_u32_pair_put(struct devlink_fmsg *fmsg, const char *name,
4349 			      u32 value)
4350 {
4351 	int err;
4352 
4353 	err = devlink_fmsg_pair_nest_start(fmsg, name);
4354 	if (err)
4355 		return err;
4356 
4357 	err = devlink_fmsg_u32_put(fmsg, value);
4358 	if (err)
4359 		return err;
4360 
4361 	err = devlink_fmsg_pair_nest_end(fmsg);
4362 	if (err)
4363 		return err;
4364 
4365 	return 0;
4366 }
4367 EXPORT_SYMBOL_GPL(devlink_fmsg_u32_pair_put);
4368 
devlink_fmsg_u64_pair_put(struct devlink_fmsg * fmsg,const char * name,u64 value)4369 int devlink_fmsg_u64_pair_put(struct devlink_fmsg *fmsg, const char *name,
4370 			      u64 value)
4371 {
4372 	int err;
4373 
4374 	err = devlink_fmsg_pair_nest_start(fmsg, name);
4375 	if (err)
4376 		return err;
4377 
4378 	err = devlink_fmsg_u64_put(fmsg, value);
4379 	if (err)
4380 		return err;
4381 
4382 	err = devlink_fmsg_pair_nest_end(fmsg);
4383 	if (err)
4384 		return err;
4385 
4386 	return 0;
4387 }
4388 EXPORT_SYMBOL_GPL(devlink_fmsg_u64_pair_put);
4389 
devlink_fmsg_string_pair_put(struct devlink_fmsg * fmsg,const char * name,const char * value)4390 int devlink_fmsg_string_pair_put(struct devlink_fmsg *fmsg, const char *name,
4391 				 const char *value)
4392 {
4393 	int err;
4394 
4395 	err = devlink_fmsg_pair_nest_start(fmsg, name);
4396 	if (err)
4397 		return err;
4398 
4399 	err = devlink_fmsg_string_put(fmsg, value);
4400 	if (err)
4401 		return err;
4402 
4403 	err = devlink_fmsg_pair_nest_end(fmsg);
4404 	if (err)
4405 		return err;
4406 
4407 	return 0;
4408 }
4409 EXPORT_SYMBOL_GPL(devlink_fmsg_string_pair_put);
4410 
devlink_fmsg_binary_pair_put(struct devlink_fmsg * fmsg,const char * name,const void * value,u16 value_len)4411 int devlink_fmsg_binary_pair_put(struct devlink_fmsg *fmsg, const char *name,
4412 				 const void *value, u16 value_len)
4413 {
4414 	int err;
4415 
4416 	err = devlink_fmsg_pair_nest_start(fmsg, name);
4417 	if (err)
4418 		return err;
4419 
4420 	err = devlink_fmsg_binary_put(fmsg, value, value_len);
4421 	if (err)
4422 		return err;
4423 
4424 	err = devlink_fmsg_pair_nest_end(fmsg);
4425 	if (err)
4426 		return err;
4427 
4428 	return 0;
4429 }
4430 EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_put);
4431 
4432 static int
devlink_fmsg_item_fill_type(struct devlink_fmsg_item * msg,struct sk_buff * skb)4433 devlink_fmsg_item_fill_type(struct devlink_fmsg_item *msg, struct sk_buff *skb)
4434 {
4435 	switch (msg->nla_type) {
4436 	case NLA_FLAG:
4437 	case NLA_U8:
4438 	case NLA_U32:
4439 	case NLA_U64:
4440 	case NLA_NUL_STRING:
4441 	case NLA_BINARY:
4442 		return nla_put_u8(skb, DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE,
4443 				  msg->nla_type);
4444 	default:
4445 		return -EINVAL;
4446 	}
4447 }
4448 
4449 static int
devlink_fmsg_item_fill_data(struct devlink_fmsg_item * msg,struct sk_buff * skb)4450 devlink_fmsg_item_fill_data(struct devlink_fmsg_item *msg, struct sk_buff *skb)
4451 {
4452 	int attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
4453 	u8 tmp;
4454 
4455 	switch (msg->nla_type) {
4456 	case NLA_FLAG:
4457 		/* Always provide flag data, regardless of its value */
4458 		tmp = *(bool *) msg->value;
4459 
4460 		return nla_put_u8(skb, attrtype, tmp);
4461 	case NLA_U8:
4462 		return nla_put_u8(skb, attrtype, *(u8 *) msg->value);
4463 	case NLA_U32:
4464 		return nla_put_u32(skb, attrtype, *(u32 *) msg->value);
4465 	case NLA_U64:
4466 		return nla_put_u64_64bit(skb, attrtype, *(u64 *) msg->value,
4467 					 DEVLINK_ATTR_PAD);
4468 	case NLA_NUL_STRING:
4469 		return nla_put_string(skb, attrtype, (char *) &msg->value);
4470 	case NLA_BINARY:
4471 		return nla_put(skb, attrtype, msg->len, (void *) &msg->value);
4472 	default:
4473 		return -EINVAL;
4474 	}
4475 }
4476 
4477 static int
devlink_fmsg_prepare_skb(struct devlink_fmsg * fmsg,struct sk_buff * skb,int * start)4478 devlink_fmsg_prepare_skb(struct devlink_fmsg *fmsg, struct sk_buff *skb,
4479 			 int *start)
4480 {
4481 	struct devlink_fmsg_item *item;
4482 	struct nlattr *fmsg_nlattr;
4483 	int i = 0;
4484 	int err;
4485 
4486 	fmsg_nlattr = nla_nest_start_noflag(skb, DEVLINK_ATTR_FMSG);
4487 	if (!fmsg_nlattr)
4488 		return -EMSGSIZE;
4489 
4490 	list_for_each_entry(item, &fmsg->item_list, list) {
4491 		if (i < *start) {
4492 			i++;
4493 			continue;
4494 		}
4495 
4496 		switch (item->attrtype) {
4497 		case DEVLINK_ATTR_FMSG_OBJ_NEST_START:
4498 		case DEVLINK_ATTR_FMSG_PAIR_NEST_START:
4499 		case DEVLINK_ATTR_FMSG_ARR_NEST_START:
4500 		case DEVLINK_ATTR_FMSG_NEST_END:
4501 			err = nla_put_flag(skb, item->attrtype);
4502 			break;
4503 		case DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA:
4504 			err = devlink_fmsg_item_fill_type(item, skb);
4505 			if (err)
4506 				break;
4507 			err = devlink_fmsg_item_fill_data(item, skb);
4508 			break;
4509 		case DEVLINK_ATTR_FMSG_OBJ_NAME:
4510 			err = nla_put_string(skb, item->attrtype,
4511 					     (char *) &item->value);
4512 			break;
4513 		default:
4514 			err = -EINVAL;
4515 			break;
4516 		}
4517 		if (!err)
4518 			*start = ++i;
4519 		else
4520 			break;
4521 	}
4522 
4523 	nla_nest_end(skb, fmsg_nlattr);
4524 	return err;
4525 }
4526 
devlink_fmsg_snd(struct devlink_fmsg * fmsg,struct genl_info * info,enum devlink_command cmd,int flags)4527 static int devlink_fmsg_snd(struct devlink_fmsg *fmsg,
4528 			    struct genl_info *info,
4529 			    enum devlink_command cmd, int flags)
4530 {
4531 	struct nlmsghdr *nlh;
4532 	struct sk_buff *skb;
4533 	bool last = false;
4534 	int index = 0;
4535 	void *hdr;
4536 	int err;
4537 
4538 	while (!last) {
4539 		int tmp_index = index;
4540 
4541 		skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
4542 		if (!skb)
4543 			return -ENOMEM;
4544 
4545 		hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
4546 				  &devlink_nl_family, flags | NLM_F_MULTI, cmd);
4547 		if (!hdr) {
4548 			err = -EMSGSIZE;
4549 			goto nla_put_failure;
4550 		}
4551 
4552 		err = devlink_fmsg_prepare_skb(fmsg, skb, &index);
4553 		if (!err)
4554 			last = true;
4555 		else if (err != -EMSGSIZE || tmp_index == index)
4556 			goto nla_put_failure;
4557 
4558 		genlmsg_end(skb, hdr);
4559 		err = genlmsg_reply(skb, info);
4560 		if (err)
4561 			return err;
4562 	}
4563 
4564 	skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
4565 	if (!skb)
4566 		return -ENOMEM;
4567 	nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
4568 			NLMSG_DONE, 0, flags | NLM_F_MULTI);
4569 	if (!nlh) {
4570 		err = -EMSGSIZE;
4571 		goto nla_put_failure;
4572 	}
4573 
4574 	return genlmsg_reply(skb, info);
4575 
4576 nla_put_failure:
4577 	nlmsg_free(skb);
4578 	return err;
4579 }
4580 
devlink_fmsg_dumpit(struct devlink_fmsg * fmsg,struct sk_buff * skb,struct netlink_callback * cb,enum devlink_command cmd)4581 static int devlink_fmsg_dumpit(struct devlink_fmsg *fmsg, struct sk_buff *skb,
4582 			       struct netlink_callback *cb,
4583 			       enum devlink_command cmd)
4584 {
4585 	int index = cb->args[0];
4586 	int tmp_index = index;
4587 	void *hdr;
4588 	int err;
4589 
4590 	hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
4591 			  &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, cmd);
4592 	if (!hdr) {
4593 		err = -EMSGSIZE;
4594 		goto nla_put_failure;
4595 	}
4596 
4597 	err = devlink_fmsg_prepare_skb(fmsg, skb, &index);
4598 	if ((err && err != -EMSGSIZE) || tmp_index == index)
4599 		goto nla_put_failure;
4600 
4601 	cb->args[0] = index;
4602 	genlmsg_end(skb, hdr);
4603 	return skb->len;
4604 
4605 nla_put_failure:
4606 	genlmsg_cancel(skb, hdr);
4607 	return err;
4608 }
4609 
4610 struct devlink_health_reporter {
4611 	struct list_head list;
4612 	void *priv;
4613 	const struct devlink_health_reporter_ops *ops;
4614 	struct devlink *devlink;
4615 	struct devlink_fmsg *dump_fmsg;
4616 	struct mutex dump_lock; /* lock parallel read/write from dump buffers */
4617 	u64 graceful_period;
4618 	bool auto_recover;
4619 	u8 health_state;
4620 	u64 dump_ts;
4621 	u64 dump_real_ts;
4622 	u64 error_count;
4623 	u64 recovery_count;
4624 	u64 last_recovery_ts;
4625 	refcount_t refcount;
4626 };
4627 
4628 void *
devlink_health_reporter_priv(struct devlink_health_reporter * reporter)4629 devlink_health_reporter_priv(struct devlink_health_reporter *reporter)
4630 {
4631 	return reporter->priv;
4632 }
4633 EXPORT_SYMBOL_GPL(devlink_health_reporter_priv);
4634 
4635 static struct devlink_health_reporter *
devlink_health_reporter_find_by_name(struct devlink * devlink,const char * reporter_name)4636 devlink_health_reporter_find_by_name(struct devlink *devlink,
4637 				     const char *reporter_name)
4638 {
4639 	struct devlink_health_reporter *reporter;
4640 
4641 	lockdep_assert_held(&devlink->reporters_lock);
4642 	list_for_each_entry(reporter, &devlink->reporter_list, list)
4643 		if (!strcmp(reporter->ops->name, reporter_name))
4644 			return reporter;
4645 	return NULL;
4646 }
4647 
4648 /**
4649  *	devlink_health_reporter_create - create devlink health reporter
4650  *
4651  *	@devlink: devlink
4652  *	@ops: ops
4653  *	@graceful_period: to avoid recovery loops, in msecs
4654  *	@auto_recover: auto recover when error occurs
4655  *	@priv: priv
4656  */
4657 struct devlink_health_reporter *
devlink_health_reporter_create(struct devlink * devlink,const struct devlink_health_reporter_ops * ops,u64 graceful_period,bool auto_recover,void * priv)4658 devlink_health_reporter_create(struct devlink *devlink,
4659 			       const struct devlink_health_reporter_ops *ops,
4660 			       u64 graceful_period, bool auto_recover,
4661 			       void *priv)
4662 {
4663 	struct devlink_health_reporter *reporter;
4664 
4665 	mutex_lock(&devlink->reporters_lock);
4666 	if (devlink_health_reporter_find_by_name(devlink, ops->name)) {
4667 		reporter = ERR_PTR(-EEXIST);
4668 		goto unlock;
4669 	}
4670 
4671 	if (WARN_ON(auto_recover && !ops->recover) ||
4672 	    WARN_ON(graceful_period && !ops->recover)) {
4673 		reporter = ERR_PTR(-EINVAL);
4674 		goto unlock;
4675 	}
4676 
4677 	reporter = kzalloc(sizeof(*reporter), GFP_KERNEL);
4678 	if (!reporter) {
4679 		reporter = ERR_PTR(-ENOMEM);
4680 		goto unlock;
4681 	}
4682 
4683 	reporter->priv = priv;
4684 	reporter->ops = ops;
4685 	reporter->devlink = devlink;
4686 	reporter->graceful_period = graceful_period;
4687 	reporter->auto_recover = auto_recover;
4688 	mutex_init(&reporter->dump_lock);
4689 	refcount_set(&reporter->refcount, 1);
4690 	list_add_tail(&reporter->list, &devlink->reporter_list);
4691 unlock:
4692 	mutex_unlock(&devlink->reporters_lock);
4693 	return reporter;
4694 }
4695 EXPORT_SYMBOL_GPL(devlink_health_reporter_create);
4696 
4697 /**
4698  *	devlink_health_reporter_destroy - destroy devlink health reporter
4699  *
4700  *	@reporter: devlink health reporter to destroy
4701  */
4702 void
devlink_health_reporter_destroy(struct devlink_health_reporter * reporter)4703 devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
4704 {
4705 	mutex_lock(&reporter->devlink->reporters_lock);
4706 	list_del(&reporter->list);
4707 	mutex_unlock(&reporter->devlink->reporters_lock);
4708 	while (refcount_read(&reporter->refcount) > 1)
4709 		msleep(100);
4710 	mutex_destroy(&reporter->dump_lock);
4711 	if (reporter->dump_fmsg)
4712 		devlink_fmsg_free(reporter->dump_fmsg);
4713 	kfree(reporter);
4714 }
4715 EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
4716 
4717 void
devlink_health_reporter_state_update(struct devlink_health_reporter * reporter,enum devlink_health_reporter_state state)4718 devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
4719 				     enum devlink_health_reporter_state state)
4720 {
4721 	if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY &&
4722 		    state != DEVLINK_HEALTH_REPORTER_STATE_ERROR))
4723 		return;
4724 
4725 	if (reporter->health_state == state)
4726 		return;
4727 
4728 	reporter->health_state = state;
4729 	trace_devlink_health_reporter_state_update(reporter->devlink,
4730 						   reporter->ops->name, state);
4731 }
4732 EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update);
4733 
4734 static int
devlink_health_reporter_recover(struct devlink_health_reporter * reporter,void * priv_ctx)4735 devlink_health_reporter_recover(struct devlink_health_reporter *reporter,
4736 				void *priv_ctx)
4737 {
4738 	int err;
4739 
4740 	if (!reporter->ops->recover)
4741 		return -EOPNOTSUPP;
4742 
4743 	err = reporter->ops->recover(reporter, priv_ctx);
4744 	if (err)
4745 		return err;
4746 
4747 	reporter->recovery_count++;
4748 	reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY;
4749 	reporter->last_recovery_ts = jiffies;
4750 
4751 	return 0;
4752 }
4753 
4754 static void
devlink_health_dump_clear(struct devlink_health_reporter * reporter)4755 devlink_health_dump_clear(struct devlink_health_reporter *reporter)
4756 {
4757 	if (!reporter->dump_fmsg)
4758 		return;
4759 	devlink_fmsg_free(reporter->dump_fmsg);
4760 	reporter->dump_fmsg = NULL;
4761 }
4762 
devlink_health_do_dump(struct devlink_health_reporter * reporter,void * priv_ctx)4763 static int devlink_health_do_dump(struct devlink_health_reporter *reporter,
4764 				  void *priv_ctx)
4765 {
4766 	int err;
4767 
4768 	if (!reporter->ops->dump)
4769 		return 0;
4770 
4771 	if (reporter->dump_fmsg)
4772 		return 0;
4773 
4774 	reporter->dump_fmsg = devlink_fmsg_alloc();
4775 	if (!reporter->dump_fmsg) {
4776 		err = -ENOMEM;
4777 		return err;
4778 	}
4779 
4780 	err = devlink_fmsg_obj_nest_start(reporter->dump_fmsg);
4781 	if (err)
4782 		goto dump_err;
4783 
4784 	err = reporter->ops->dump(reporter, reporter->dump_fmsg,
4785 				  priv_ctx);
4786 	if (err)
4787 		goto dump_err;
4788 
4789 	err = devlink_fmsg_obj_nest_end(reporter->dump_fmsg);
4790 	if (err)
4791 		goto dump_err;
4792 
4793 	reporter->dump_ts = jiffies;
4794 	reporter->dump_real_ts = ktime_get_real_ns();
4795 
4796 	return 0;
4797 
4798 dump_err:
4799 	devlink_health_dump_clear(reporter);
4800 	return err;
4801 }
4802 
devlink_health_report(struct devlink_health_reporter * reporter,const char * msg,void * priv_ctx)4803 int devlink_health_report(struct devlink_health_reporter *reporter,
4804 			  const char *msg, void *priv_ctx)
4805 {
4806 	enum devlink_health_reporter_state prev_health_state;
4807 	struct devlink *devlink = reporter->devlink;
4808 
4809 	/* write a log message of the current error */
4810 	WARN_ON(!msg);
4811 	trace_devlink_health_report(devlink, reporter->ops->name, msg);
4812 	reporter->error_count++;
4813 	prev_health_state = reporter->health_state;
4814 	reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
4815 
4816 	/* abort if the previous error wasn't recovered */
4817 	if (reporter->auto_recover &&
4818 	    (prev_health_state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY ||
4819 	     jiffies - reporter->last_recovery_ts <
4820 	     msecs_to_jiffies(reporter->graceful_period))) {
4821 		trace_devlink_health_recover_aborted(devlink,
4822 						     reporter->ops->name,
4823 						     reporter->health_state,
4824 						     jiffies -
4825 						     reporter->last_recovery_ts);
4826 		return -ECANCELED;
4827 	}
4828 
4829 	reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
4830 
4831 	mutex_lock(&reporter->dump_lock);
4832 	/* store current dump of current error, for later analysis */
4833 	devlink_health_do_dump(reporter, priv_ctx);
4834 	mutex_unlock(&reporter->dump_lock);
4835 
4836 	if (reporter->auto_recover)
4837 		return devlink_health_reporter_recover(reporter, priv_ctx);
4838 
4839 	return 0;
4840 }
4841 EXPORT_SYMBOL_GPL(devlink_health_report);
4842 
4843 static struct devlink_health_reporter *
devlink_health_reporter_get_from_attrs(struct devlink * devlink,struct nlattr ** attrs)4844 devlink_health_reporter_get_from_attrs(struct devlink *devlink,
4845 				       struct nlattr **attrs)
4846 {
4847 	struct devlink_health_reporter *reporter;
4848 	char *reporter_name;
4849 
4850 	if (!attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME])
4851 		return NULL;
4852 
4853 	reporter_name = nla_data(attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]);
4854 	mutex_lock(&devlink->reporters_lock);
4855 	reporter = devlink_health_reporter_find_by_name(devlink, reporter_name);
4856 	if (reporter)
4857 		refcount_inc(&reporter->refcount);
4858 	mutex_unlock(&devlink->reporters_lock);
4859 	return reporter;
4860 }
4861 
4862 static struct devlink_health_reporter *
devlink_health_reporter_get_from_info(struct devlink * devlink,struct genl_info * info)4863 devlink_health_reporter_get_from_info(struct devlink *devlink,
4864 				      struct genl_info *info)
4865 {
4866 	return devlink_health_reporter_get_from_attrs(devlink, info->attrs);
4867 }
4868 
4869 static struct devlink_health_reporter *
devlink_health_reporter_get_from_cb(struct netlink_callback * cb)4870 devlink_health_reporter_get_from_cb(struct netlink_callback *cb)
4871 {
4872 	struct devlink_health_reporter *reporter;
4873 	struct devlink *devlink;
4874 	struct nlattr **attrs;
4875 	int err;
4876 
4877 	attrs = kmalloc_array(DEVLINK_ATTR_MAX + 1, sizeof(*attrs), GFP_KERNEL);
4878 	if (!attrs)
4879 		return NULL;
4880 
4881 	err = nlmsg_parse_deprecated(cb->nlh,
4882 				     GENL_HDRLEN + devlink_nl_family.hdrsize,
4883 				     attrs, DEVLINK_ATTR_MAX,
4884 				     devlink_nl_family.policy, cb->extack);
4885 	if (err)
4886 		goto free;
4887 
4888 	mutex_lock(&devlink_mutex);
4889 	devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
4890 	if (IS_ERR(devlink))
4891 		goto unlock;
4892 
4893 	reporter = devlink_health_reporter_get_from_attrs(devlink, attrs);
4894 	mutex_unlock(&devlink_mutex);
4895 	kfree(attrs);
4896 	return reporter;
4897 unlock:
4898 	mutex_unlock(&devlink_mutex);
4899 free:
4900 	kfree(attrs);
4901 	return NULL;
4902 }
4903 
4904 static void
devlink_health_reporter_put(struct devlink_health_reporter * reporter)4905 devlink_health_reporter_put(struct devlink_health_reporter *reporter)
4906 {
4907 	refcount_dec(&reporter->refcount);
4908 }
4909 
4910 static int
devlink_nl_health_reporter_fill(struct sk_buff * msg,struct devlink * devlink,struct devlink_health_reporter * reporter,enum devlink_command cmd,u32 portid,u32 seq,int flags)4911 devlink_nl_health_reporter_fill(struct sk_buff *msg,
4912 				struct devlink *devlink,
4913 				struct devlink_health_reporter *reporter,
4914 				enum devlink_command cmd, u32 portid,
4915 				u32 seq, int flags)
4916 {
4917 	struct nlattr *reporter_attr;
4918 	void *hdr;
4919 
4920 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
4921 	if (!hdr)
4922 		return -EMSGSIZE;
4923 
4924 	if (devlink_nl_put_handle(msg, devlink))
4925 		goto genlmsg_cancel;
4926 
4927 	reporter_attr = nla_nest_start_noflag(msg,
4928 					      DEVLINK_ATTR_HEALTH_REPORTER);
4929 	if (!reporter_attr)
4930 		goto genlmsg_cancel;
4931 	if (nla_put_string(msg, DEVLINK_ATTR_HEALTH_REPORTER_NAME,
4932 			   reporter->ops->name))
4933 		goto reporter_nest_cancel;
4934 	if (nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_STATE,
4935 		       reporter->health_state))
4936 		goto reporter_nest_cancel;
4937 	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_ERR_COUNT,
4938 			      reporter->error_count, DEVLINK_ATTR_PAD))
4939 		goto reporter_nest_cancel;
4940 	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_RECOVER_COUNT,
4941 			      reporter->recovery_count, DEVLINK_ATTR_PAD))
4942 		goto reporter_nest_cancel;
4943 	if (reporter->ops->recover &&
4944 	    nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD,
4945 			      reporter->graceful_period,
4946 			      DEVLINK_ATTR_PAD))
4947 		goto reporter_nest_cancel;
4948 	if (reporter->ops->recover &&
4949 	    nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER,
4950 		       reporter->auto_recover))
4951 		goto reporter_nest_cancel;
4952 	if (reporter->dump_fmsg &&
4953 	    nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS,
4954 			      jiffies_to_msecs(reporter->dump_ts),
4955 			      DEVLINK_ATTR_PAD))
4956 		goto reporter_nest_cancel;
4957 	if (reporter->dump_fmsg &&
4958 	    nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS_NS,
4959 			      reporter->dump_real_ts, DEVLINK_ATTR_PAD))
4960 		goto reporter_nest_cancel;
4961 
4962 	nla_nest_end(msg, reporter_attr);
4963 	genlmsg_end(msg, hdr);
4964 	return 0;
4965 
4966 reporter_nest_cancel:
4967 	nla_nest_end(msg, reporter_attr);
4968 genlmsg_cancel:
4969 	genlmsg_cancel(msg, hdr);
4970 	return -EMSGSIZE;
4971 }
4972 
devlink_nl_cmd_health_reporter_get_doit(struct sk_buff * skb,struct genl_info * info)4973 static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb,
4974 						   struct genl_info *info)
4975 {
4976 	struct devlink *devlink = info->user_ptr[0];
4977 	struct devlink_health_reporter *reporter;
4978 	struct sk_buff *msg;
4979 	int err;
4980 
4981 	reporter = devlink_health_reporter_get_from_info(devlink, info);
4982 	if (!reporter)
4983 		return -EINVAL;
4984 
4985 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4986 	if (!msg) {
4987 		err = -ENOMEM;
4988 		goto out;
4989 	}
4990 
4991 	err = devlink_nl_health_reporter_fill(msg, devlink, reporter,
4992 					      DEVLINK_CMD_HEALTH_REPORTER_GET,
4993 					      info->snd_portid, info->snd_seq,
4994 					      0);
4995 	if (err) {
4996 		nlmsg_free(msg);
4997 		goto out;
4998 	}
4999 
5000 	err = genlmsg_reply(msg, info);
5001 out:
5002 	devlink_health_reporter_put(reporter);
5003 	return err;
5004 }
5005 
5006 static int
devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)5007 devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg,
5008 					  struct netlink_callback *cb)
5009 {
5010 	struct devlink_health_reporter *reporter;
5011 	struct devlink *devlink;
5012 	int start = cb->args[0];
5013 	int idx = 0;
5014 	int err;
5015 
5016 	mutex_lock(&devlink_mutex);
5017 	list_for_each_entry(devlink, &devlink_list, list) {
5018 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
5019 			continue;
5020 		mutex_lock(&devlink->reporters_lock);
5021 		list_for_each_entry(reporter, &devlink->reporter_list,
5022 				    list) {
5023 			if (idx < start) {
5024 				idx++;
5025 				continue;
5026 			}
5027 			err = devlink_nl_health_reporter_fill(msg, devlink,
5028 							      reporter,
5029 							      DEVLINK_CMD_HEALTH_REPORTER_GET,
5030 							      NETLINK_CB(cb->skb).portid,
5031 							      cb->nlh->nlmsg_seq,
5032 							      NLM_F_MULTI);
5033 			if (err) {
5034 				mutex_unlock(&devlink->reporters_lock);
5035 				goto out;
5036 			}
5037 			idx++;
5038 		}
5039 		mutex_unlock(&devlink->reporters_lock);
5040 	}
5041 out:
5042 	mutex_unlock(&devlink_mutex);
5043 
5044 	cb->args[0] = idx;
5045 	return msg->len;
5046 }
5047 
5048 static int
devlink_nl_cmd_health_reporter_set_doit(struct sk_buff * skb,struct genl_info * info)5049 devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb,
5050 					struct genl_info *info)
5051 {
5052 	struct devlink *devlink = info->user_ptr[0];
5053 	struct devlink_health_reporter *reporter;
5054 	int err;
5055 
5056 	reporter = devlink_health_reporter_get_from_info(devlink, info);
5057 	if (!reporter)
5058 		return -EINVAL;
5059 
5060 	if (!reporter->ops->recover &&
5061 	    (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] ||
5062 	     info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])) {
5063 		err = -EOPNOTSUPP;
5064 		goto out;
5065 	}
5066 
5067 	if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD])
5068 		reporter->graceful_period =
5069 			nla_get_u64(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]);
5070 
5071 	if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])
5072 		reporter->auto_recover =
5073 			nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]);
5074 
5075 	devlink_health_reporter_put(reporter);
5076 	return 0;
5077 out:
5078 	devlink_health_reporter_put(reporter);
5079 	return err;
5080 }
5081 
devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff * skb,struct genl_info * info)5082 static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb,
5083 						       struct genl_info *info)
5084 {
5085 	struct devlink *devlink = info->user_ptr[0];
5086 	struct devlink_health_reporter *reporter;
5087 	int err;
5088 
5089 	reporter = devlink_health_reporter_get_from_info(devlink, info);
5090 	if (!reporter)
5091 		return -EINVAL;
5092 
5093 	err = devlink_health_reporter_recover(reporter, NULL);
5094 
5095 	devlink_health_reporter_put(reporter);
5096 	return err;
5097 }
5098 
devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff * skb,struct genl_info * info)5099 static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb,
5100 							struct genl_info *info)
5101 {
5102 	struct devlink *devlink = info->user_ptr[0];
5103 	struct devlink_health_reporter *reporter;
5104 	struct devlink_fmsg *fmsg;
5105 	int err;
5106 
5107 	reporter = devlink_health_reporter_get_from_info(devlink, info);
5108 	if (!reporter)
5109 		return -EINVAL;
5110 
5111 	if (!reporter->ops->diagnose) {
5112 		devlink_health_reporter_put(reporter);
5113 		return -EOPNOTSUPP;
5114 	}
5115 
5116 	fmsg = devlink_fmsg_alloc();
5117 	if (!fmsg) {
5118 		devlink_health_reporter_put(reporter);
5119 		return -ENOMEM;
5120 	}
5121 
5122 	err = devlink_fmsg_obj_nest_start(fmsg);
5123 	if (err)
5124 		goto out;
5125 
5126 	err = reporter->ops->diagnose(reporter, fmsg);
5127 	if (err)
5128 		goto out;
5129 
5130 	err = devlink_fmsg_obj_nest_end(fmsg);
5131 	if (err)
5132 		goto out;
5133 
5134 	err = devlink_fmsg_snd(fmsg, info,
5135 			       DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 0);
5136 
5137 out:
5138 	devlink_fmsg_free(fmsg);
5139 	devlink_health_reporter_put(reporter);
5140 	return err;
5141 }
5142 
5143 static int
devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff * skb,struct netlink_callback * cb)5144 devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb,
5145 					       struct netlink_callback *cb)
5146 {
5147 	struct devlink_health_reporter *reporter;
5148 	u64 start = cb->args[0];
5149 	int err;
5150 
5151 	reporter = devlink_health_reporter_get_from_cb(cb);
5152 	if (!reporter)
5153 		return -EINVAL;
5154 
5155 	if (!reporter->ops->dump) {
5156 		err = -EOPNOTSUPP;
5157 		goto out;
5158 	}
5159 	mutex_lock(&reporter->dump_lock);
5160 	if (!start) {
5161 		err = devlink_health_do_dump(reporter, NULL);
5162 		if (err)
5163 			goto unlock;
5164 		cb->args[1] = reporter->dump_ts;
5165 	}
5166 	if (!reporter->dump_fmsg || cb->args[1] != reporter->dump_ts) {
5167 		NL_SET_ERR_MSG_MOD(cb->extack, "Dump trampled, please retry");
5168 		err = -EAGAIN;
5169 		goto unlock;
5170 	}
5171 
5172 	err = devlink_fmsg_dumpit(reporter->dump_fmsg, skb, cb,
5173 				  DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET);
5174 unlock:
5175 	mutex_unlock(&reporter->dump_lock);
5176 out:
5177 	devlink_health_reporter_put(reporter);
5178 	return err;
5179 }
5180 
5181 static int
devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff * skb,struct genl_info * info)5182 devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb,
5183 					       struct genl_info *info)
5184 {
5185 	struct devlink *devlink = info->user_ptr[0];
5186 	struct devlink_health_reporter *reporter;
5187 
5188 	reporter = devlink_health_reporter_get_from_info(devlink, info);
5189 	if (!reporter)
5190 		return -EINVAL;
5191 
5192 	if (!reporter->ops->dump) {
5193 		devlink_health_reporter_put(reporter);
5194 		return -EOPNOTSUPP;
5195 	}
5196 
5197 	mutex_lock(&reporter->dump_lock);
5198 	devlink_health_dump_clear(reporter);
5199 	mutex_unlock(&reporter->dump_lock);
5200 	devlink_health_reporter_put(reporter);
5201 	return 0;
5202 }
5203 
5204 struct devlink_stats {
5205 	u64 rx_bytes;
5206 	u64 rx_packets;
5207 	struct u64_stats_sync syncp;
5208 };
5209 
5210 /**
5211  * struct devlink_trap_group_item - Packet trap group attributes.
5212  * @group: Immutable packet trap group attributes.
5213  * @refcount: Number of trap items using the group.
5214  * @list: trap_group_list member.
5215  * @stats: Trap group statistics.
5216  *
5217  * Describes packet trap group attributes. Created by devlink during trap
5218  * registration.
5219  */
5220 struct devlink_trap_group_item {
5221 	const struct devlink_trap_group *group;
5222 	refcount_t refcount;
5223 	struct list_head list;
5224 	struct devlink_stats __percpu *stats;
5225 };
5226 
5227 /**
5228  * struct devlink_trap_item - Packet trap attributes.
5229  * @trap: Immutable packet trap attributes.
5230  * @group_item: Associated group item.
5231  * @list: trap_list member.
5232  * @action: Trap action.
5233  * @stats: Trap statistics.
5234  * @priv: Driver private information.
5235  *
5236  * Describes both mutable and immutable packet trap attributes. Created by
5237  * devlink during trap registration and used for all trap related operations.
5238  */
5239 struct devlink_trap_item {
5240 	const struct devlink_trap *trap;
5241 	struct devlink_trap_group_item *group_item;
5242 	struct list_head list;
5243 	enum devlink_trap_action action;
5244 	struct devlink_stats __percpu *stats;
5245 	void *priv;
5246 };
5247 
5248 static struct devlink_trap_item *
devlink_trap_item_lookup(struct devlink * devlink,const char * name)5249 devlink_trap_item_lookup(struct devlink *devlink, const char *name)
5250 {
5251 	struct devlink_trap_item *trap_item;
5252 
5253 	list_for_each_entry(trap_item, &devlink->trap_list, list) {
5254 		if (!strcmp(trap_item->trap->name, name))
5255 			return trap_item;
5256 	}
5257 
5258 	return NULL;
5259 }
5260 
5261 static struct devlink_trap_item *
devlink_trap_item_get_from_info(struct devlink * devlink,struct genl_info * info)5262 devlink_trap_item_get_from_info(struct devlink *devlink,
5263 				struct genl_info *info)
5264 {
5265 	struct nlattr *attr;
5266 
5267 	if (!info->attrs[DEVLINK_ATTR_TRAP_NAME])
5268 		return NULL;
5269 	attr = info->attrs[DEVLINK_ATTR_TRAP_NAME];
5270 
5271 	return devlink_trap_item_lookup(devlink, nla_data(attr));
5272 }
5273 
5274 static int
devlink_trap_action_get_from_info(struct genl_info * info,enum devlink_trap_action * p_trap_action)5275 devlink_trap_action_get_from_info(struct genl_info *info,
5276 				  enum devlink_trap_action *p_trap_action)
5277 {
5278 	u8 val;
5279 
5280 	val = nla_get_u8(info->attrs[DEVLINK_ATTR_TRAP_ACTION]);
5281 	switch (val) {
5282 	case DEVLINK_TRAP_ACTION_DROP: /* fall-through */
5283 	case DEVLINK_TRAP_ACTION_TRAP:
5284 		*p_trap_action = val;
5285 		break;
5286 	default:
5287 		return -EINVAL;
5288 	}
5289 
5290 	return 0;
5291 }
5292 
devlink_trap_metadata_put(struct sk_buff * msg,const struct devlink_trap * trap)5293 static int devlink_trap_metadata_put(struct sk_buff *msg,
5294 				     const struct devlink_trap *trap)
5295 {
5296 	struct nlattr *attr;
5297 
5298 	attr = nla_nest_start(msg, DEVLINK_ATTR_TRAP_METADATA);
5299 	if (!attr)
5300 		return -EMSGSIZE;
5301 
5302 	if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT) &&
5303 	    nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_IN_PORT))
5304 		goto nla_put_failure;
5305 
5306 	nla_nest_end(msg, attr);
5307 
5308 	return 0;
5309 
5310 nla_put_failure:
5311 	nla_nest_cancel(msg, attr);
5312 	return -EMSGSIZE;
5313 }
5314 
devlink_trap_stats_read(struct devlink_stats __percpu * trap_stats,struct devlink_stats * stats)5315 static void devlink_trap_stats_read(struct devlink_stats __percpu *trap_stats,
5316 				    struct devlink_stats *stats)
5317 {
5318 	int i;
5319 
5320 	memset(stats, 0, sizeof(*stats));
5321 	for_each_possible_cpu(i) {
5322 		struct devlink_stats *cpu_stats;
5323 		u64 rx_packets, rx_bytes;
5324 		unsigned int start;
5325 
5326 		cpu_stats = per_cpu_ptr(trap_stats, i);
5327 		do {
5328 			start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
5329 			rx_packets = cpu_stats->rx_packets;
5330 			rx_bytes = cpu_stats->rx_bytes;
5331 		} while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
5332 
5333 		stats->rx_packets += rx_packets;
5334 		stats->rx_bytes += rx_bytes;
5335 	}
5336 }
5337 
devlink_trap_stats_put(struct sk_buff * msg,struct devlink_stats __percpu * trap_stats)5338 static int devlink_trap_stats_put(struct sk_buff *msg,
5339 				  struct devlink_stats __percpu *trap_stats)
5340 {
5341 	struct devlink_stats stats;
5342 	struct nlattr *attr;
5343 
5344 	devlink_trap_stats_read(trap_stats, &stats);
5345 
5346 	attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
5347 	if (!attr)
5348 		return -EMSGSIZE;
5349 
5350 	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS,
5351 			      stats.rx_packets, DEVLINK_ATTR_PAD))
5352 		goto nla_put_failure;
5353 
5354 	if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES,
5355 			      stats.rx_bytes, DEVLINK_ATTR_PAD))
5356 		goto nla_put_failure;
5357 
5358 	nla_nest_end(msg, attr);
5359 
5360 	return 0;
5361 
5362 nla_put_failure:
5363 	nla_nest_cancel(msg, attr);
5364 	return -EMSGSIZE;
5365 }
5366 
devlink_nl_trap_fill(struct sk_buff * msg,struct devlink * devlink,const struct devlink_trap_item * trap_item,enum devlink_command cmd,u32 portid,u32 seq,int flags)5367 static int devlink_nl_trap_fill(struct sk_buff *msg, struct devlink *devlink,
5368 				const struct devlink_trap_item *trap_item,
5369 				enum devlink_command cmd, u32 portid, u32 seq,
5370 				int flags)
5371 {
5372 	struct devlink_trap_group_item *group_item = trap_item->group_item;
5373 	void *hdr;
5374 	int err;
5375 
5376 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
5377 	if (!hdr)
5378 		return -EMSGSIZE;
5379 
5380 	if (devlink_nl_put_handle(msg, devlink))
5381 		goto nla_put_failure;
5382 
5383 	if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
5384 			   group_item->group->name))
5385 		goto nla_put_failure;
5386 
5387 	if (nla_put_string(msg, DEVLINK_ATTR_TRAP_NAME, trap_item->trap->name))
5388 		goto nla_put_failure;
5389 
5390 	if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_TYPE, trap_item->trap->type))
5391 		goto nla_put_failure;
5392 
5393 	if (trap_item->trap->generic &&
5394 	    nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
5395 		goto nla_put_failure;
5396 
5397 	if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_ACTION, trap_item->action))
5398 		goto nla_put_failure;
5399 
5400 	err = devlink_trap_metadata_put(msg, trap_item->trap);
5401 	if (err)
5402 		goto nla_put_failure;
5403 
5404 	err = devlink_trap_stats_put(msg, trap_item->stats);
5405 	if (err)
5406 		goto nla_put_failure;
5407 
5408 	genlmsg_end(msg, hdr);
5409 
5410 	return 0;
5411 
5412 nla_put_failure:
5413 	genlmsg_cancel(msg, hdr);
5414 	return -EMSGSIZE;
5415 }
5416 
devlink_nl_cmd_trap_get_doit(struct sk_buff * skb,struct genl_info * info)5417 static int devlink_nl_cmd_trap_get_doit(struct sk_buff *skb,
5418 					struct genl_info *info)
5419 {
5420 	struct netlink_ext_ack *extack = info->extack;
5421 	struct devlink *devlink = info->user_ptr[0];
5422 	struct devlink_trap_item *trap_item;
5423 	struct sk_buff *msg;
5424 	int err;
5425 
5426 	if (list_empty(&devlink->trap_list))
5427 		return -EOPNOTSUPP;
5428 
5429 	trap_item = devlink_trap_item_get_from_info(devlink, info);
5430 	if (!trap_item) {
5431 		NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap");
5432 		return -ENOENT;
5433 	}
5434 
5435 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5436 	if (!msg)
5437 		return -ENOMEM;
5438 
5439 	err = devlink_nl_trap_fill(msg, devlink, trap_item,
5440 				   DEVLINK_CMD_TRAP_NEW, info->snd_portid,
5441 				   info->snd_seq, 0);
5442 	if (err)
5443 		goto err_trap_fill;
5444 
5445 	return genlmsg_reply(msg, info);
5446 
5447 err_trap_fill:
5448 	nlmsg_free(msg);
5449 	return err;
5450 }
5451 
devlink_nl_cmd_trap_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)5452 static int devlink_nl_cmd_trap_get_dumpit(struct sk_buff *msg,
5453 					  struct netlink_callback *cb)
5454 {
5455 	struct devlink_trap_item *trap_item;
5456 	struct devlink *devlink;
5457 	int start = cb->args[0];
5458 	int idx = 0;
5459 	int err;
5460 
5461 	mutex_lock(&devlink_mutex);
5462 	list_for_each_entry(devlink, &devlink_list, list) {
5463 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
5464 			continue;
5465 		mutex_lock(&devlink->lock);
5466 		list_for_each_entry(trap_item, &devlink->trap_list, list) {
5467 			if (idx < start) {
5468 				idx++;
5469 				continue;
5470 			}
5471 			err = devlink_nl_trap_fill(msg, devlink, trap_item,
5472 						   DEVLINK_CMD_TRAP_NEW,
5473 						   NETLINK_CB(cb->skb).portid,
5474 						   cb->nlh->nlmsg_seq,
5475 						   NLM_F_MULTI);
5476 			if (err) {
5477 				mutex_unlock(&devlink->lock);
5478 				goto out;
5479 			}
5480 			idx++;
5481 		}
5482 		mutex_unlock(&devlink->lock);
5483 	}
5484 out:
5485 	mutex_unlock(&devlink_mutex);
5486 
5487 	cb->args[0] = idx;
5488 	return msg->len;
5489 }
5490 
__devlink_trap_action_set(struct devlink * devlink,struct devlink_trap_item * trap_item,enum devlink_trap_action trap_action,struct netlink_ext_ack * extack)5491 static int __devlink_trap_action_set(struct devlink *devlink,
5492 				     struct devlink_trap_item *trap_item,
5493 				     enum devlink_trap_action trap_action,
5494 				     struct netlink_ext_ack *extack)
5495 {
5496 	int err;
5497 
5498 	if (trap_item->action != trap_action &&
5499 	    trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP) {
5500 		NL_SET_ERR_MSG_MOD(extack, "Cannot change action of non-drop traps. Skipping");
5501 		return 0;
5502 	}
5503 
5504 	err = devlink->ops->trap_action_set(devlink, trap_item->trap,
5505 					    trap_action);
5506 	if (err)
5507 		return err;
5508 
5509 	trap_item->action = trap_action;
5510 
5511 	return 0;
5512 }
5513 
devlink_trap_action_set(struct devlink * devlink,struct devlink_trap_item * trap_item,struct genl_info * info)5514 static int devlink_trap_action_set(struct devlink *devlink,
5515 				   struct devlink_trap_item *trap_item,
5516 				   struct genl_info *info)
5517 {
5518 	enum devlink_trap_action trap_action;
5519 	int err;
5520 
5521 	if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
5522 		return 0;
5523 
5524 	err = devlink_trap_action_get_from_info(info, &trap_action);
5525 	if (err) {
5526 		NL_SET_ERR_MSG_MOD(info->extack, "Invalid trap action");
5527 		return -EINVAL;
5528 	}
5529 
5530 	return __devlink_trap_action_set(devlink, trap_item, trap_action,
5531 					 info->extack);
5532 }
5533 
devlink_nl_cmd_trap_set_doit(struct sk_buff * skb,struct genl_info * info)5534 static int devlink_nl_cmd_trap_set_doit(struct sk_buff *skb,
5535 					struct genl_info *info)
5536 {
5537 	struct netlink_ext_ack *extack = info->extack;
5538 	struct devlink *devlink = info->user_ptr[0];
5539 	struct devlink_trap_item *trap_item;
5540 	int err;
5541 
5542 	if (list_empty(&devlink->trap_list))
5543 		return -EOPNOTSUPP;
5544 
5545 	trap_item = devlink_trap_item_get_from_info(devlink, info);
5546 	if (!trap_item) {
5547 		NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap");
5548 		return -ENOENT;
5549 	}
5550 
5551 	err = devlink_trap_action_set(devlink, trap_item, info);
5552 	if (err)
5553 		return err;
5554 
5555 	return 0;
5556 }
5557 
5558 static struct devlink_trap_group_item *
devlink_trap_group_item_lookup(struct devlink * devlink,const char * name)5559 devlink_trap_group_item_lookup(struct devlink *devlink, const char *name)
5560 {
5561 	struct devlink_trap_group_item *group_item;
5562 
5563 	list_for_each_entry(group_item, &devlink->trap_group_list, list) {
5564 		if (!strcmp(group_item->group->name, name))
5565 			return group_item;
5566 	}
5567 
5568 	return NULL;
5569 }
5570 
5571 static struct devlink_trap_group_item *
devlink_trap_group_item_get_from_info(struct devlink * devlink,struct genl_info * info)5572 devlink_trap_group_item_get_from_info(struct devlink *devlink,
5573 				      struct genl_info *info)
5574 {
5575 	char *name;
5576 
5577 	if (!info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME])
5578 		return NULL;
5579 	name = nla_data(info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME]);
5580 
5581 	return devlink_trap_group_item_lookup(devlink, name);
5582 }
5583 
5584 static int
devlink_nl_trap_group_fill(struct sk_buff * msg,struct devlink * devlink,const struct devlink_trap_group_item * group_item,enum devlink_command cmd,u32 portid,u32 seq,int flags)5585 devlink_nl_trap_group_fill(struct sk_buff *msg, struct devlink *devlink,
5586 			   const struct devlink_trap_group_item *group_item,
5587 			   enum devlink_command cmd, u32 portid, u32 seq,
5588 			   int flags)
5589 {
5590 	void *hdr;
5591 	int err;
5592 
5593 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
5594 	if (!hdr)
5595 		return -EMSGSIZE;
5596 
5597 	if (devlink_nl_put_handle(msg, devlink))
5598 		goto nla_put_failure;
5599 
5600 	if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
5601 			   group_item->group->name))
5602 		goto nla_put_failure;
5603 
5604 	if (group_item->group->generic &&
5605 	    nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
5606 		goto nla_put_failure;
5607 
5608 	err = devlink_trap_stats_put(msg, group_item->stats);
5609 	if (err)
5610 		goto nla_put_failure;
5611 
5612 	genlmsg_end(msg, hdr);
5613 
5614 	return 0;
5615 
5616 nla_put_failure:
5617 	genlmsg_cancel(msg, hdr);
5618 	return -EMSGSIZE;
5619 }
5620 
devlink_nl_cmd_trap_group_get_doit(struct sk_buff * skb,struct genl_info * info)5621 static int devlink_nl_cmd_trap_group_get_doit(struct sk_buff *skb,
5622 					      struct genl_info *info)
5623 {
5624 	struct netlink_ext_ack *extack = info->extack;
5625 	struct devlink *devlink = info->user_ptr[0];
5626 	struct devlink_trap_group_item *group_item;
5627 	struct sk_buff *msg;
5628 	int err;
5629 
5630 	if (list_empty(&devlink->trap_group_list))
5631 		return -EOPNOTSUPP;
5632 
5633 	group_item = devlink_trap_group_item_get_from_info(devlink, info);
5634 	if (!group_item) {
5635 		NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap group");
5636 		return -ENOENT;
5637 	}
5638 
5639 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5640 	if (!msg)
5641 		return -ENOMEM;
5642 
5643 	err = devlink_nl_trap_group_fill(msg, devlink, group_item,
5644 					 DEVLINK_CMD_TRAP_GROUP_NEW,
5645 					 info->snd_portid, info->snd_seq, 0);
5646 	if (err)
5647 		goto err_trap_group_fill;
5648 
5649 	return genlmsg_reply(msg, info);
5650 
5651 err_trap_group_fill:
5652 	nlmsg_free(msg);
5653 	return err;
5654 }
5655 
devlink_nl_cmd_trap_group_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)5656 static int devlink_nl_cmd_trap_group_get_dumpit(struct sk_buff *msg,
5657 						struct netlink_callback *cb)
5658 {
5659 	enum devlink_command cmd = DEVLINK_CMD_TRAP_GROUP_NEW;
5660 	struct devlink_trap_group_item *group_item;
5661 	u32 portid = NETLINK_CB(cb->skb).portid;
5662 	struct devlink *devlink;
5663 	int start = cb->args[0];
5664 	int idx = 0;
5665 	int err;
5666 
5667 	mutex_lock(&devlink_mutex);
5668 	list_for_each_entry(devlink, &devlink_list, list) {
5669 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
5670 			continue;
5671 		mutex_lock(&devlink->lock);
5672 		list_for_each_entry(group_item, &devlink->trap_group_list,
5673 				    list) {
5674 			if (idx < start) {
5675 				idx++;
5676 				continue;
5677 			}
5678 			err = devlink_nl_trap_group_fill(msg, devlink,
5679 							 group_item, cmd,
5680 							 portid,
5681 							 cb->nlh->nlmsg_seq,
5682 							 NLM_F_MULTI);
5683 			if (err) {
5684 				mutex_unlock(&devlink->lock);
5685 				goto out;
5686 			}
5687 			idx++;
5688 		}
5689 		mutex_unlock(&devlink->lock);
5690 	}
5691 out:
5692 	mutex_unlock(&devlink_mutex);
5693 
5694 	cb->args[0] = idx;
5695 	return msg->len;
5696 }
5697 
5698 static int
__devlink_trap_group_action_set(struct devlink * devlink,struct devlink_trap_group_item * group_item,enum devlink_trap_action trap_action,struct netlink_ext_ack * extack)5699 __devlink_trap_group_action_set(struct devlink *devlink,
5700 				struct devlink_trap_group_item *group_item,
5701 				enum devlink_trap_action trap_action,
5702 				struct netlink_ext_ack *extack)
5703 {
5704 	const char *group_name = group_item->group->name;
5705 	struct devlink_trap_item *trap_item;
5706 	int err;
5707 
5708 	list_for_each_entry(trap_item, &devlink->trap_list, list) {
5709 		if (strcmp(trap_item->trap->group.name, group_name))
5710 			continue;
5711 		err = __devlink_trap_action_set(devlink, trap_item,
5712 						trap_action, extack);
5713 		if (err)
5714 			return err;
5715 	}
5716 
5717 	return 0;
5718 }
5719 
5720 static int
devlink_trap_group_action_set(struct devlink * devlink,struct devlink_trap_group_item * group_item,struct genl_info * info)5721 devlink_trap_group_action_set(struct devlink *devlink,
5722 			      struct devlink_trap_group_item *group_item,
5723 			      struct genl_info *info)
5724 {
5725 	enum devlink_trap_action trap_action;
5726 	int err;
5727 
5728 	if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
5729 		return 0;
5730 
5731 	err = devlink_trap_action_get_from_info(info, &trap_action);
5732 	if (err) {
5733 		NL_SET_ERR_MSG_MOD(info->extack, "Invalid trap action");
5734 		return -EINVAL;
5735 	}
5736 
5737 	err = __devlink_trap_group_action_set(devlink, group_item, trap_action,
5738 					      info->extack);
5739 	if (err)
5740 		return err;
5741 
5742 	return 0;
5743 }
5744 
devlink_nl_cmd_trap_group_set_doit(struct sk_buff * skb,struct genl_info * info)5745 static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb,
5746 					      struct genl_info *info)
5747 {
5748 	struct netlink_ext_ack *extack = info->extack;
5749 	struct devlink *devlink = info->user_ptr[0];
5750 	struct devlink_trap_group_item *group_item;
5751 	int err;
5752 
5753 	if (list_empty(&devlink->trap_group_list))
5754 		return -EOPNOTSUPP;
5755 
5756 	group_item = devlink_trap_group_item_get_from_info(devlink, info);
5757 	if (!group_item) {
5758 		NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap group");
5759 		return -ENOENT;
5760 	}
5761 
5762 	err = devlink_trap_group_action_set(devlink, group_item, info);
5763 	if (err)
5764 		return err;
5765 
5766 	return 0;
5767 }
5768 
5769 static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
5770 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
5771 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
5772 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 },
5773 	[DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 },
5774 	[DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 },
5775 	[DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 },
5776 	[DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 },
5777 	[DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 },
5778 	[DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 },
5779 	[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 },
5780 	[DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 },
5781 	[DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 },
5782 	[DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 },
5783 	[DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 },
5784 	[DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 },
5785 	[DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING },
5786 	[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 },
5787 	[DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64},
5788 	[DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64},
5789 	[DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING },
5790 	[DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 },
5791 	[DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 },
5792 	[DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING },
5793 	[DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 },
5794 	[DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING },
5795 	[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] = { .type = NLA_U64 },
5796 	[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER] = { .type = NLA_U8 },
5797 	[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME] = { .type = NLA_NUL_STRING },
5798 	[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT] = { .type = NLA_NUL_STRING },
5799 	[DEVLINK_ATTR_TRAP_NAME] = { .type = NLA_NUL_STRING },
5800 	[DEVLINK_ATTR_TRAP_ACTION] = { .type = NLA_U8 },
5801 	[DEVLINK_ATTR_TRAP_GROUP_NAME] = { .type = NLA_NUL_STRING },
5802 };
5803 
5804 static const struct genl_ops devlink_nl_ops[] = {
5805 	{
5806 		.cmd = DEVLINK_CMD_GET,
5807 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5808 		.doit = devlink_nl_cmd_get_doit,
5809 		.dumpit = devlink_nl_cmd_get_dumpit,
5810 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5811 		/* can be retrieved by unprivileged users */
5812 	},
5813 	{
5814 		.cmd = DEVLINK_CMD_PORT_GET,
5815 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5816 		.doit = devlink_nl_cmd_port_get_doit,
5817 		.dumpit = devlink_nl_cmd_port_get_dumpit,
5818 		.internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
5819 		/* can be retrieved by unprivileged users */
5820 	},
5821 	{
5822 		.cmd = DEVLINK_CMD_PORT_SET,
5823 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5824 		.doit = devlink_nl_cmd_port_set_doit,
5825 		.flags = GENL_ADMIN_PERM,
5826 		.internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
5827 	},
5828 	{
5829 		.cmd = DEVLINK_CMD_PORT_SPLIT,
5830 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5831 		.doit = devlink_nl_cmd_port_split_doit,
5832 		.flags = GENL_ADMIN_PERM,
5833 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5834 				  DEVLINK_NL_FLAG_NO_LOCK,
5835 	},
5836 	{
5837 		.cmd = DEVLINK_CMD_PORT_UNSPLIT,
5838 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5839 		.doit = devlink_nl_cmd_port_unsplit_doit,
5840 		.flags = GENL_ADMIN_PERM,
5841 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5842 				  DEVLINK_NL_FLAG_NO_LOCK,
5843 	},
5844 	{
5845 		.cmd = DEVLINK_CMD_SB_GET,
5846 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5847 		.doit = devlink_nl_cmd_sb_get_doit,
5848 		.dumpit = devlink_nl_cmd_sb_get_dumpit,
5849 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5850 				  DEVLINK_NL_FLAG_NEED_SB,
5851 		/* can be retrieved by unprivileged users */
5852 	},
5853 	{
5854 		.cmd = DEVLINK_CMD_SB_POOL_GET,
5855 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5856 		.doit = devlink_nl_cmd_sb_pool_get_doit,
5857 		.dumpit = devlink_nl_cmd_sb_pool_get_dumpit,
5858 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5859 				  DEVLINK_NL_FLAG_NEED_SB,
5860 		/* can be retrieved by unprivileged users */
5861 	},
5862 	{
5863 		.cmd = DEVLINK_CMD_SB_POOL_SET,
5864 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5865 		.doit = devlink_nl_cmd_sb_pool_set_doit,
5866 		.flags = GENL_ADMIN_PERM,
5867 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5868 				  DEVLINK_NL_FLAG_NEED_SB,
5869 	},
5870 	{
5871 		.cmd = DEVLINK_CMD_SB_PORT_POOL_GET,
5872 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5873 		.doit = devlink_nl_cmd_sb_port_pool_get_doit,
5874 		.dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit,
5875 		.internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5876 				  DEVLINK_NL_FLAG_NEED_SB,
5877 		/* can be retrieved by unprivileged users */
5878 	},
5879 	{
5880 		.cmd = DEVLINK_CMD_SB_PORT_POOL_SET,
5881 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5882 		.doit = devlink_nl_cmd_sb_port_pool_set_doit,
5883 		.flags = GENL_ADMIN_PERM,
5884 		.internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5885 				  DEVLINK_NL_FLAG_NEED_SB,
5886 	},
5887 	{
5888 		.cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET,
5889 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5890 		.doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit,
5891 		.dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit,
5892 		.internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5893 				  DEVLINK_NL_FLAG_NEED_SB,
5894 		/* can be retrieved by unprivileged users */
5895 	},
5896 	{
5897 		.cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET,
5898 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5899 		.doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit,
5900 		.flags = GENL_ADMIN_PERM,
5901 		.internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5902 				  DEVLINK_NL_FLAG_NEED_SB,
5903 	},
5904 	{
5905 		.cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT,
5906 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5907 		.doit = devlink_nl_cmd_sb_occ_snapshot_doit,
5908 		.flags = GENL_ADMIN_PERM,
5909 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5910 				  DEVLINK_NL_FLAG_NEED_SB,
5911 	},
5912 	{
5913 		.cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR,
5914 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5915 		.doit = devlink_nl_cmd_sb_occ_max_clear_doit,
5916 		.flags = GENL_ADMIN_PERM,
5917 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5918 				  DEVLINK_NL_FLAG_NEED_SB,
5919 	},
5920 	{
5921 		.cmd = DEVLINK_CMD_ESWITCH_GET,
5922 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5923 		.doit = devlink_nl_cmd_eswitch_get_doit,
5924 		.flags = GENL_ADMIN_PERM,
5925 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5926 	},
5927 	{
5928 		.cmd = DEVLINK_CMD_ESWITCH_SET,
5929 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5930 		.doit = devlink_nl_cmd_eswitch_set_doit,
5931 		.flags = GENL_ADMIN_PERM,
5932 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5933 				  DEVLINK_NL_FLAG_NO_LOCK,
5934 	},
5935 	{
5936 		.cmd = DEVLINK_CMD_DPIPE_TABLE_GET,
5937 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5938 		.doit = devlink_nl_cmd_dpipe_table_get,
5939 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5940 		/* can be retrieved by unprivileged users */
5941 	},
5942 	{
5943 		.cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET,
5944 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5945 		.doit = devlink_nl_cmd_dpipe_entries_get,
5946 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5947 		/* can be retrieved by unprivileged users */
5948 	},
5949 	{
5950 		.cmd = DEVLINK_CMD_DPIPE_HEADERS_GET,
5951 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5952 		.doit = devlink_nl_cmd_dpipe_headers_get,
5953 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5954 		/* can be retrieved by unprivileged users */
5955 	},
5956 	{
5957 		.cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET,
5958 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5959 		.doit = devlink_nl_cmd_dpipe_table_counters_set,
5960 		.flags = GENL_ADMIN_PERM,
5961 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5962 	},
5963 	{
5964 		.cmd = DEVLINK_CMD_RESOURCE_SET,
5965 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5966 		.doit = devlink_nl_cmd_resource_set,
5967 		.flags = GENL_ADMIN_PERM,
5968 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5969 	},
5970 	{
5971 		.cmd = DEVLINK_CMD_RESOURCE_DUMP,
5972 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5973 		.doit = devlink_nl_cmd_resource_dump,
5974 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5975 		/* can be retrieved by unprivileged users */
5976 	},
5977 	{
5978 		.cmd = DEVLINK_CMD_RELOAD,
5979 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5980 		.doit = devlink_nl_cmd_reload,
5981 		.flags = GENL_ADMIN_PERM,
5982 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5983 				  DEVLINK_NL_FLAG_NO_LOCK,
5984 	},
5985 	{
5986 		.cmd = DEVLINK_CMD_PARAM_GET,
5987 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5988 		.doit = devlink_nl_cmd_param_get_doit,
5989 		.dumpit = devlink_nl_cmd_param_get_dumpit,
5990 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5991 		/* can be retrieved by unprivileged users */
5992 	},
5993 	{
5994 		.cmd = DEVLINK_CMD_PARAM_SET,
5995 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5996 		.doit = devlink_nl_cmd_param_set_doit,
5997 		.flags = GENL_ADMIN_PERM,
5998 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5999 	},
6000 	{
6001 		.cmd = DEVLINK_CMD_PORT_PARAM_GET,
6002 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6003 		.doit = devlink_nl_cmd_port_param_get_doit,
6004 		.dumpit = devlink_nl_cmd_port_param_get_dumpit,
6005 		.internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
6006 		/* can be retrieved by unprivileged users */
6007 	},
6008 	{
6009 		.cmd = DEVLINK_CMD_PORT_PARAM_SET,
6010 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6011 		.doit = devlink_nl_cmd_port_param_set_doit,
6012 		.flags = GENL_ADMIN_PERM,
6013 		.internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
6014 	},
6015 	{
6016 		.cmd = DEVLINK_CMD_REGION_GET,
6017 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6018 		.doit = devlink_nl_cmd_region_get_doit,
6019 		.dumpit = devlink_nl_cmd_region_get_dumpit,
6020 		.flags = GENL_ADMIN_PERM,
6021 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6022 	},
6023 	{
6024 		.cmd = DEVLINK_CMD_REGION_DEL,
6025 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6026 		.doit = devlink_nl_cmd_region_del,
6027 		.flags = GENL_ADMIN_PERM,
6028 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6029 	},
6030 	{
6031 		.cmd = DEVLINK_CMD_REGION_READ,
6032 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6033 		.dumpit = devlink_nl_cmd_region_read_dumpit,
6034 		.flags = GENL_ADMIN_PERM,
6035 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6036 	},
6037 	{
6038 		.cmd = DEVLINK_CMD_INFO_GET,
6039 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6040 		.doit = devlink_nl_cmd_info_get_doit,
6041 		.dumpit = devlink_nl_cmd_info_get_dumpit,
6042 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6043 		/* can be retrieved by unprivileged users */
6044 	},
6045 	{
6046 		.cmd = DEVLINK_CMD_HEALTH_REPORTER_GET,
6047 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6048 		.doit = devlink_nl_cmd_health_reporter_get_doit,
6049 		.dumpit = devlink_nl_cmd_health_reporter_get_dumpit,
6050 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6051 				  DEVLINK_NL_FLAG_NO_LOCK,
6052 		/* can be retrieved by unprivileged users */
6053 	},
6054 	{
6055 		.cmd = DEVLINK_CMD_HEALTH_REPORTER_SET,
6056 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6057 		.doit = devlink_nl_cmd_health_reporter_set_doit,
6058 		.flags = GENL_ADMIN_PERM,
6059 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6060 				  DEVLINK_NL_FLAG_NO_LOCK,
6061 	},
6062 	{
6063 		.cmd = DEVLINK_CMD_HEALTH_REPORTER_RECOVER,
6064 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6065 		.doit = devlink_nl_cmd_health_reporter_recover_doit,
6066 		.flags = GENL_ADMIN_PERM,
6067 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6068 				  DEVLINK_NL_FLAG_NO_LOCK,
6069 	},
6070 	{
6071 		.cmd = DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE,
6072 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6073 		.doit = devlink_nl_cmd_health_reporter_diagnose_doit,
6074 		.flags = GENL_ADMIN_PERM,
6075 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6076 				  DEVLINK_NL_FLAG_NO_LOCK,
6077 	},
6078 	{
6079 		.cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET,
6080 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6081 		.dumpit = devlink_nl_cmd_health_reporter_dump_get_dumpit,
6082 		.flags = GENL_ADMIN_PERM,
6083 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6084 				  DEVLINK_NL_FLAG_NO_LOCK,
6085 	},
6086 	{
6087 		.cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR,
6088 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6089 		.doit = devlink_nl_cmd_health_reporter_dump_clear_doit,
6090 		.flags = GENL_ADMIN_PERM,
6091 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
6092 				  DEVLINK_NL_FLAG_NO_LOCK,
6093 	},
6094 	{
6095 		.cmd = DEVLINK_CMD_FLASH_UPDATE,
6096 		.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
6097 		.doit = devlink_nl_cmd_flash_update,
6098 		.flags = GENL_ADMIN_PERM,
6099 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6100 	},
6101 	{
6102 		.cmd = DEVLINK_CMD_TRAP_GET,
6103 		.doit = devlink_nl_cmd_trap_get_doit,
6104 		.dumpit = devlink_nl_cmd_trap_get_dumpit,
6105 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6106 		/* can be retrieved by unprivileged users */
6107 	},
6108 	{
6109 		.cmd = DEVLINK_CMD_TRAP_SET,
6110 		.doit = devlink_nl_cmd_trap_set_doit,
6111 		.flags = GENL_ADMIN_PERM,
6112 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6113 	},
6114 	{
6115 		.cmd = DEVLINK_CMD_TRAP_GROUP_GET,
6116 		.doit = devlink_nl_cmd_trap_group_get_doit,
6117 		.dumpit = devlink_nl_cmd_trap_group_get_dumpit,
6118 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6119 		/* can be retrieved by unprivileged users */
6120 	},
6121 	{
6122 		.cmd = DEVLINK_CMD_TRAP_GROUP_SET,
6123 		.doit = devlink_nl_cmd_trap_group_set_doit,
6124 		.flags = GENL_ADMIN_PERM,
6125 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
6126 	},
6127 };
6128 
6129 static struct genl_family devlink_nl_family __ro_after_init = {
6130 	.name		= DEVLINK_GENL_NAME,
6131 	.version	= DEVLINK_GENL_VERSION,
6132 	.maxattr	= DEVLINK_ATTR_MAX,
6133 	.policy = devlink_nl_policy,
6134 	.netnsok	= true,
6135 	.pre_doit	= devlink_nl_pre_doit,
6136 	.post_doit	= devlink_nl_post_doit,
6137 	.module		= THIS_MODULE,
6138 	.ops		= devlink_nl_ops,
6139 	.n_ops		= ARRAY_SIZE(devlink_nl_ops),
6140 	.mcgrps		= devlink_nl_mcgrps,
6141 	.n_mcgrps	= ARRAY_SIZE(devlink_nl_mcgrps),
6142 };
6143 
6144 /**
6145  *	devlink_alloc - Allocate new devlink instance resources
6146  *
6147  *	@ops: ops
6148  *	@priv_size: size of user private data
6149  *
6150  *	Allocate new devlink instance resources, including devlink index
6151  *	and name.
6152  */
devlink_alloc(const struct devlink_ops * ops,size_t priv_size)6153 struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
6154 {
6155 	struct devlink *devlink;
6156 
6157 	if (WARN_ON(!ops))
6158 		return NULL;
6159 
6160 	devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL);
6161 	if (!devlink)
6162 		return NULL;
6163 	devlink->ops = ops;
6164 	devlink_net_set(devlink, &init_net);
6165 	INIT_LIST_HEAD(&devlink->port_list);
6166 	INIT_LIST_HEAD(&devlink->sb_list);
6167 	INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list);
6168 	INIT_LIST_HEAD(&devlink->resource_list);
6169 	INIT_LIST_HEAD(&devlink->param_list);
6170 	INIT_LIST_HEAD(&devlink->region_list);
6171 	INIT_LIST_HEAD(&devlink->reporter_list);
6172 	INIT_LIST_HEAD(&devlink->trap_list);
6173 	INIT_LIST_HEAD(&devlink->trap_group_list);
6174 	mutex_init(&devlink->lock);
6175 	mutex_init(&devlink->reporters_lock);
6176 	return devlink;
6177 }
6178 EXPORT_SYMBOL_GPL(devlink_alloc);
6179 
6180 /**
6181  *	devlink_register - Register devlink instance
6182  *
6183  *	@devlink: devlink
6184  *	@dev: parent device
6185  */
devlink_register(struct devlink * devlink,struct device * dev)6186 int devlink_register(struct devlink *devlink, struct device *dev)
6187 {
6188 	mutex_lock(&devlink_mutex);
6189 	devlink->dev = dev;
6190 	list_add_tail(&devlink->list, &devlink_list);
6191 	devlink_notify(devlink, DEVLINK_CMD_NEW);
6192 	mutex_unlock(&devlink_mutex);
6193 	return 0;
6194 }
6195 EXPORT_SYMBOL_GPL(devlink_register);
6196 
6197 /**
6198  *	devlink_unregister - Unregister devlink instance
6199  *
6200  *	@devlink: devlink
6201  */
devlink_unregister(struct devlink * devlink)6202 void devlink_unregister(struct devlink *devlink)
6203 {
6204 	mutex_lock(&devlink_mutex);
6205 	WARN_ON(devlink_reload_supported(devlink) &&
6206 		devlink->reload_enabled);
6207 	devlink_notify(devlink, DEVLINK_CMD_DEL);
6208 	list_del(&devlink->list);
6209 	mutex_unlock(&devlink_mutex);
6210 }
6211 EXPORT_SYMBOL_GPL(devlink_unregister);
6212 
6213 /**
6214  *	devlink_reload_enable - Enable reload of devlink instance
6215  *
6216  *	@devlink: devlink
6217  *
6218  *	Should be called at end of device initialization
6219  *	process when reload operation is supported.
6220  */
devlink_reload_enable(struct devlink * devlink)6221 void devlink_reload_enable(struct devlink *devlink)
6222 {
6223 	mutex_lock(&devlink_mutex);
6224 	devlink->reload_enabled = true;
6225 	mutex_unlock(&devlink_mutex);
6226 }
6227 EXPORT_SYMBOL_GPL(devlink_reload_enable);
6228 
6229 /**
6230  *	devlink_reload_disable - Disable reload of devlink instance
6231  *
6232  *	@devlink: devlink
6233  *
6234  *	Should be called at the beginning of device cleanup
6235  *	process when reload operation is supported.
6236  */
devlink_reload_disable(struct devlink * devlink)6237 void devlink_reload_disable(struct devlink *devlink)
6238 {
6239 	mutex_lock(&devlink_mutex);
6240 	/* Mutex is taken which ensures that no reload operation is in
6241 	 * progress while setting up forbidded flag.
6242 	 */
6243 	devlink->reload_enabled = false;
6244 	mutex_unlock(&devlink_mutex);
6245 }
6246 EXPORT_SYMBOL_GPL(devlink_reload_disable);
6247 
6248 /**
6249  *	devlink_free - Free devlink instance resources
6250  *
6251  *	@devlink: devlink
6252  */
devlink_free(struct devlink * devlink)6253 void devlink_free(struct devlink *devlink)
6254 {
6255 	mutex_destroy(&devlink->reporters_lock);
6256 	mutex_destroy(&devlink->lock);
6257 	WARN_ON(!list_empty(&devlink->trap_group_list));
6258 	WARN_ON(!list_empty(&devlink->trap_list));
6259 	WARN_ON(!list_empty(&devlink->reporter_list));
6260 	WARN_ON(!list_empty(&devlink->region_list));
6261 	WARN_ON(!list_empty(&devlink->param_list));
6262 	WARN_ON(!list_empty(&devlink->resource_list));
6263 	WARN_ON(!list_empty(&devlink->dpipe_table_list));
6264 	WARN_ON(!list_empty(&devlink->sb_list));
6265 	WARN_ON(!list_empty(&devlink->port_list));
6266 
6267 	kfree(devlink);
6268 }
6269 EXPORT_SYMBOL_GPL(devlink_free);
6270 
devlink_port_type_warn(struct work_struct * work)6271 static void devlink_port_type_warn(struct work_struct *work)
6272 {
6273 	WARN(true, "Type was not set for devlink port.");
6274 }
6275 
devlink_port_type_should_warn(struct devlink_port * devlink_port)6276 static bool devlink_port_type_should_warn(struct devlink_port *devlink_port)
6277 {
6278 	/* Ignore CPU and DSA flavours. */
6279 	return devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_CPU &&
6280 	       devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_DSA;
6281 }
6282 
6283 #define DEVLINK_PORT_TYPE_WARN_TIMEOUT (HZ * 30)
6284 
devlink_port_type_warn_schedule(struct devlink_port * devlink_port)6285 static void devlink_port_type_warn_schedule(struct devlink_port *devlink_port)
6286 {
6287 	if (!devlink_port_type_should_warn(devlink_port))
6288 		return;
6289 	/* Schedule a work to WARN in case driver does not set port
6290 	 * type within timeout.
6291 	 */
6292 	schedule_delayed_work(&devlink_port->type_warn_dw,
6293 			      DEVLINK_PORT_TYPE_WARN_TIMEOUT);
6294 }
6295 
devlink_port_type_warn_cancel(struct devlink_port * devlink_port)6296 static void devlink_port_type_warn_cancel(struct devlink_port *devlink_port)
6297 {
6298 	if (!devlink_port_type_should_warn(devlink_port))
6299 		return;
6300 	cancel_delayed_work_sync(&devlink_port->type_warn_dw);
6301 }
6302 
6303 /**
6304  *	devlink_port_register - Register devlink port
6305  *
6306  *	@devlink: devlink
6307  *	@devlink_port: devlink port
6308  *	@port_index: driver-specific numerical identifier of the port
6309  *
6310  *	Register devlink port with provided port index. User can use
6311  *	any indexing, even hw-related one. devlink_port structure
6312  *	is convenient to be embedded inside user driver private structure.
6313  *	Note that the caller should take care of zeroing the devlink_port
6314  *	structure.
6315  */
devlink_port_register(struct devlink * devlink,struct devlink_port * devlink_port,unsigned int port_index)6316 int devlink_port_register(struct devlink *devlink,
6317 			  struct devlink_port *devlink_port,
6318 			  unsigned int port_index)
6319 {
6320 	mutex_lock(&devlink->lock);
6321 	if (devlink_port_index_exists(devlink, port_index)) {
6322 		mutex_unlock(&devlink->lock);
6323 		return -EEXIST;
6324 	}
6325 	devlink_port->devlink = devlink;
6326 	devlink_port->index = port_index;
6327 	devlink_port->registered = true;
6328 	spin_lock_init(&devlink_port->type_lock);
6329 	list_add_tail(&devlink_port->list, &devlink->port_list);
6330 	INIT_LIST_HEAD(&devlink_port->param_list);
6331 	mutex_unlock(&devlink->lock);
6332 	INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn);
6333 	devlink_port_type_warn_schedule(devlink_port);
6334 	devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
6335 	return 0;
6336 }
6337 EXPORT_SYMBOL_GPL(devlink_port_register);
6338 
6339 /**
6340  *	devlink_port_unregister - Unregister devlink port
6341  *
6342  *	@devlink_port: devlink port
6343  */
devlink_port_unregister(struct devlink_port * devlink_port)6344 void devlink_port_unregister(struct devlink_port *devlink_port)
6345 {
6346 	struct devlink *devlink = devlink_port->devlink;
6347 
6348 	devlink_port_type_warn_cancel(devlink_port);
6349 	devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
6350 	mutex_lock(&devlink->lock);
6351 	list_del(&devlink_port->list);
6352 	mutex_unlock(&devlink->lock);
6353 }
6354 EXPORT_SYMBOL_GPL(devlink_port_unregister);
6355 
__devlink_port_type_set(struct devlink_port * devlink_port,enum devlink_port_type type,void * type_dev)6356 static void __devlink_port_type_set(struct devlink_port *devlink_port,
6357 				    enum devlink_port_type type,
6358 				    void *type_dev)
6359 {
6360 	if (WARN_ON(!devlink_port->registered))
6361 		return;
6362 	devlink_port_type_warn_cancel(devlink_port);
6363 	spin_lock_bh(&devlink_port->type_lock);
6364 	devlink_port->type = type;
6365 	devlink_port->type_dev = type_dev;
6366 	spin_unlock_bh(&devlink_port->type_lock);
6367 	devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
6368 }
6369 
6370 /**
6371  *	devlink_port_type_eth_set - Set port type to Ethernet
6372  *
6373  *	@devlink_port: devlink port
6374  *	@netdev: related netdevice
6375  */
devlink_port_type_eth_set(struct devlink_port * devlink_port,struct net_device * netdev)6376 void devlink_port_type_eth_set(struct devlink_port *devlink_port,
6377 			       struct net_device *netdev)
6378 {
6379 	const struct net_device_ops *ops = netdev->netdev_ops;
6380 
6381 	/* If driver registers devlink port, it should set devlink port
6382 	 * attributes accordingly so the compat functions are called
6383 	 * and the original ops are not used.
6384 	 */
6385 	if (ops->ndo_get_phys_port_name) {
6386 		/* Some drivers use the same set of ndos for netdevs
6387 		 * that have devlink_port registered and also for
6388 		 * those who don't. Make sure that ndo_get_phys_port_name
6389 		 * returns -EOPNOTSUPP here in case it is defined.
6390 		 * Warn if not.
6391 		 */
6392 		char name[IFNAMSIZ];
6393 		int err;
6394 
6395 		err = ops->ndo_get_phys_port_name(netdev, name, sizeof(name));
6396 		WARN_ON(err != -EOPNOTSUPP);
6397 	}
6398 	if (ops->ndo_get_port_parent_id) {
6399 		/* Some drivers use the same set of ndos for netdevs
6400 		 * that have devlink_port registered and also for
6401 		 * those who don't. Make sure that ndo_get_port_parent_id
6402 		 * returns -EOPNOTSUPP here in case it is defined.
6403 		 * Warn if not.
6404 		 */
6405 		struct netdev_phys_item_id ppid;
6406 		int err;
6407 
6408 		err = ops->ndo_get_port_parent_id(netdev, &ppid);
6409 		WARN_ON(err != -EOPNOTSUPP);
6410 	}
6411 	__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, netdev);
6412 }
6413 EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
6414 
6415 /**
6416  *	devlink_port_type_ib_set - Set port type to InfiniBand
6417  *
6418  *	@devlink_port: devlink port
6419  *	@ibdev: related IB device
6420  */
devlink_port_type_ib_set(struct devlink_port * devlink_port,struct ib_device * ibdev)6421 void devlink_port_type_ib_set(struct devlink_port *devlink_port,
6422 			      struct ib_device *ibdev)
6423 {
6424 	__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_IB, ibdev);
6425 }
6426 EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
6427 
6428 /**
6429  *	devlink_port_type_clear - Clear port type
6430  *
6431  *	@devlink_port: devlink port
6432  */
devlink_port_type_clear(struct devlink_port * devlink_port)6433 void devlink_port_type_clear(struct devlink_port *devlink_port)
6434 {
6435 	__devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL);
6436 	devlink_port_type_warn_schedule(devlink_port);
6437 }
6438 EXPORT_SYMBOL_GPL(devlink_port_type_clear);
6439 
__devlink_port_attrs_set(struct devlink_port * devlink_port,enum devlink_port_flavour flavour,const unsigned char * switch_id,unsigned char switch_id_len)6440 static int __devlink_port_attrs_set(struct devlink_port *devlink_port,
6441 				    enum devlink_port_flavour flavour,
6442 				    const unsigned char *switch_id,
6443 				    unsigned char switch_id_len)
6444 {
6445 	struct devlink_port_attrs *attrs = &devlink_port->attrs;
6446 
6447 	if (WARN_ON(devlink_port->registered))
6448 		return -EEXIST;
6449 	attrs->set = true;
6450 	attrs->flavour = flavour;
6451 	if (switch_id) {
6452 		attrs->switch_port = true;
6453 		if (WARN_ON(switch_id_len > MAX_PHYS_ITEM_ID_LEN))
6454 			switch_id_len = MAX_PHYS_ITEM_ID_LEN;
6455 		memcpy(attrs->switch_id.id, switch_id, switch_id_len);
6456 		attrs->switch_id.id_len = switch_id_len;
6457 	} else {
6458 		attrs->switch_port = false;
6459 	}
6460 	return 0;
6461 }
6462 
6463 /**
6464  *	devlink_port_attrs_set - Set port attributes
6465  *
6466  *	@devlink_port: devlink port
6467  *	@flavour: flavour of the port
6468  *	@port_number: number of the port that is facing user, for example
6469  *	              the front panel port number
6470  *	@split: indicates if this is split port
6471  *	@split_subport_number: if the port is split, this is the number
6472  *	                       of subport.
6473  *	@switch_id: if the port is part of switch, this is buffer with ID,
6474  *	            otwerwise this is NULL
6475  *	@switch_id_len: length of the switch_id buffer
6476  */
devlink_port_attrs_set(struct devlink_port * devlink_port,enum devlink_port_flavour flavour,u32 port_number,bool split,u32 split_subport_number,const unsigned char * switch_id,unsigned char switch_id_len)6477 void devlink_port_attrs_set(struct devlink_port *devlink_port,
6478 			    enum devlink_port_flavour flavour,
6479 			    u32 port_number, bool split,
6480 			    u32 split_subport_number,
6481 			    const unsigned char *switch_id,
6482 			    unsigned char switch_id_len)
6483 {
6484 	struct devlink_port_attrs *attrs = &devlink_port->attrs;
6485 	int ret;
6486 
6487 	ret = __devlink_port_attrs_set(devlink_port, flavour,
6488 				       switch_id, switch_id_len);
6489 	if (ret)
6490 		return;
6491 	attrs->split = split;
6492 	attrs->phys.port_number = port_number;
6493 	attrs->phys.split_subport_number = split_subport_number;
6494 }
6495 EXPORT_SYMBOL_GPL(devlink_port_attrs_set);
6496 
6497 /**
6498  *	devlink_port_attrs_pci_pf_set - Set PCI PF port attributes
6499  *
6500  *	@devlink_port: devlink port
6501  *	@pf: associated PF for the devlink port instance
6502  *	@switch_id: if the port is part of switch, this is buffer with ID,
6503  *	            otherwise this is NULL
6504  *	@switch_id_len: length of the switch_id buffer
6505  */
devlink_port_attrs_pci_pf_set(struct devlink_port * devlink_port,const unsigned char * switch_id,unsigned char switch_id_len,u16 pf)6506 void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port,
6507 				   const unsigned char *switch_id,
6508 				   unsigned char switch_id_len, u16 pf)
6509 {
6510 	struct devlink_port_attrs *attrs = &devlink_port->attrs;
6511 	int ret;
6512 
6513 	ret = __devlink_port_attrs_set(devlink_port,
6514 				       DEVLINK_PORT_FLAVOUR_PCI_PF,
6515 				       switch_id, switch_id_len);
6516 	if (ret)
6517 		return;
6518 
6519 	attrs->pci_pf.pf = pf;
6520 }
6521 EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_pf_set);
6522 
6523 /**
6524  *	devlink_port_attrs_pci_vf_set - Set PCI VF port attributes
6525  *
6526  *	@devlink_port: devlink port
6527  *	@pf: associated PF for the devlink port instance
6528  *	@vf: associated VF of a PF for the devlink port instance
6529  *	@switch_id: if the port is part of switch, this is buffer with ID,
6530  *	            otherwise this is NULL
6531  *	@switch_id_len: length of the switch_id buffer
6532  */
devlink_port_attrs_pci_vf_set(struct devlink_port * devlink_port,const unsigned char * switch_id,unsigned char switch_id_len,u16 pf,u16 vf)6533 void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port,
6534 				   const unsigned char *switch_id,
6535 				   unsigned char switch_id_len,
6536 				   u16 pf, u16 vf)
6537 {
6538 	struct devlink_port_attrs *attrs = &devlink_port->attrs;
6539 	int ret;
6540 
6541 	ret = __devlink_port_attrs_set(devlink_port,
6542 				       DEVLINK_PORT_FLAVOUR_PCI_VF,
6543 				       switch_id, switch_id_len);
6544 	if (ret)
6545 		return;
6546 	attrs->pci_vf.pf = pf;
6547 	attrs->pci_vf.vf = vf;
6548 }
6549 EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_vf_set);
6550 
__devlink_port_phys_port_name_get(struct devlink_port * devlink_port,char * name,size_t len)6551 static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port,
6552 					     char *name, size_t len)
6553 {
6554 	struct devlink_port_attrs *attrs = &devlink_port->attrs;
6555 	int n = 0;
6556 
6557 	if (!attrs->set)
6558 		return -EOPNOTSUPP;
6559 
6560 	switch (attrs->flavour) {
6561 	case DEVLINK_PORT_FLAVOUR_PHYSICAL:
6562 		if (!attrs->split)
6563 			n = snprintf(name, len, "p%u", attrs->phys.port_number);
6564 		else
6565 			n = snprintf(name, len, "p%us%u",
6566 				     attrs->phys.port_number,
6567 				     attrs->phys.split_subport_number);
6568 		break;
6569 	case DEVLINK_PORT_FLAVOUR_CPU:
6570 	case DEVLINK_PORT_FLAVOUR_DSA:
6571 		/* As CPU and DSA ports do not have a netdevice associated
6572 		 * case should not ever happen.
6573 		 */
6574 		WARN_ON(1);
6575 		return -EINVAL;
6576 	case DEVLINK_PORT_FLAVOUR_PCI_PF:
6577 		n = snprintf(name, len, "pf%u", attrs->pci_pf.pf);
6578 		break;
6579 	case DEVLINK_PORT_FLAVOUR_PCI_VF:
6580 		n = snprintf(name, len, "pf%uvf%u",
6581 			     attrs->pci_vf.pf, attrs->pci_vf.vf);
6582 		break;
6583 	}
6584 
6585 	if (n >= len)
6586 		return -EINVAL;
6587 
6588 	return 0;
6589 }
6590 
devlink_sb_register(struct devlink * devlink,unsigned int sb_index,u32 size,u16 ingress_pools_count,u16 egress_pools_count,u16 ingress_tc_count,u16 egress_tc_count)6591 int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
6592 			u32 size, u16 ingress_pools_count,
6593 			u16 egress_pools_count, u16 ingress_tc_count,
6594 			u16 egress_tc_count)
6595 {
6596 	struct devlink_sb *devlink_sb;
6597 	int err = 0;
6598 
6599 	mutex_lock(&devlink->lock);
6600 	if (devlink_sb_index_exists(devlink, sb_index)) {
6601 		err = -EEXIST;
6602 		goto unlock;
6603 	}
6604 
6605 	devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL);
6606 	if (!devlink_sb) {
6607 		err = -ENOMEM;
6608 		goto unlock;
6609 	}
6610 	devlink_sb->index = sb_index;
6611 	devlink_sb->size = size;
6612 	devlink_sb->ingress_pools_count = ingress_pools_count;
6613 	devlink_sb->egress_pools_count = egress_pools_count;
6614 	devlink_sb->ingress_tc_count = ingress_tc_count;
6615 	devlink_sb->egress_tc_count = egress_tc_count;
6616 	list_add_tail(&devlink_sb->list, &devlink->sb_list);
6617 unlock:
6618 	mutex_unlock(&devlink->lock);
6619 	return err;
6620 }
6621 EXPORT_SYMBOL_GPL(devlink_sb_register);
6622 
devlink_sb_unregister(struct devlink * devlink,unsigned int sb_index)6623 void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index)
6624 {
6625 	struct devlink_sb *devlink_sb;
6626 
6627 	mutex_lock(&devlink->lock);
6628 	devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
6629 	WARN_ON(!devlink_sb);
6630 	list_del(&devlink_sb->list);
6631 	mutex_unlock(&devlink->lock);
6632 	kfree(devlink_sb);
6633 }
6634 EXPORT_SYMBOL_GPL(devlink_sb_unregister);
6635 
6636 /**
6637  *	devlink_dpipe_headers_register - register dpipe headers
6638  *
6639  *	@devlink: devlink
6640  *	@dpipe_headers: dpipe header array
6641  *
6642  *	Register the headers supported by hardware.
6643  */
devlink_dpipe_headers_register(struct devlink * devlink,struct devlink_dpipe_headers * dpipe_headers)6644 int devlink_dpipe_headers_register(struct devlink *devlink,
6645 				   struct devlink_dpipe_headers *dpipe_headers)
6646 {
6647 	mutex_lock(&devlink->lock);
6648 	devlink->dpipe_headers = dpipe_headers;
6649 	mutex_unlock(&devlink->lock);
6650 	return 0;
6651 }
6652 EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register);
6653 
6654 /**
6655  *	devlink_dpipe_headers_unregister - unregister dpipe headers
6656  *
6657  *	@devlink: devlink
6658  *
6659  *	Unregister the headers supported by hardware.
6660  */
devlink_dpipe_headers_unregister(struct devlink * devlink)6661 void devlink_dpipe_headers_unregister(struct devlink *devlink)
6662 {
6663 	mutex_lock(&devlink->lock);
6664 	devlink->dpipe_headers = NULL;
6665 	mutex_unlock(&devlink->lock);
6666 }
6667 EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister);
6668 
6669 /**
6670  *	devlink_dpipe_table_counter_enabled - check if counter allocation
6671  *					      required
6672  *	@devlink: devlink
6673  *	@table_name: tables name
6674  *
6675  *	Used by driver to check if counter allocation is required.
6676  *	After counter allocation is turned on the table entries
6677  *	are updated to include counter statistics.
6678  *
6679  *	After that point on the driver must respect the counter
6680  *	state so that each entry added to the table is added
6681  *	with a counter.
6682  */
devlink_dpipe_table_counter_enabled(struct devlink * devlink,const char * table_name)6683 bool devlink_dpipe_table_counter_enabled(struct devlink *devlink,
6684 					 const char *table_name)
6685 {
6686 	struct devlink_dpipe_table *table;
6687 	bool enabled;
6688 
6689 	rcu_read_lock();
6690 	table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
6691 					 table_name);
6692 	enabled = false;
6693 	if (table)
6694 		enabled = table->counters_enabled;
6695 	rcu_read_unlock();
6696 	return enabled;
6697 }
6698 EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled);
6699 
6700 /**
6701  *	devlink_dpipe_table_register - register dpipe table
6702  *
6703  *	@devlink: devlink
6704  *	@table_name: table name
6705  *	@table_ops: table ops
6706  *	@priv: priv
6707  *	@counter_control_extern: external control for counters
6708  */
devlink_dpipe_table_register(struct devlink * devlink,const char * table_name,struct devlink_dpipe_table_ops * table_ops,void * priv,bool counter_control_extern)6709 int devlink_dpipe_table_register(struct devlink *devlink,
6710 				 const char *table_name,
6711 				 struct devlink_dpipe_table_ops *table_ops,
6712 				 void *priv, bool counter_control_extern)
6713 {
6714 	struct devlink_dpipe_table *table;
6715 
6716 	if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name))
6717 		return -EEXIST;
6718 
6719 	if (WARN_ON(!table_ops->size_get))
6720 		return -EINVAL;
6721 
6722 	table = kzalloc(sizeof(*table), GFP_KERNEL);
6723 	if (!table)
6724 		return -ENOMEM;
6725 
6726 	table->name = table_name;
6727 	table->table_ops = table_ops;
6728 	table->priv = priv;
6729 	table->counter_control_extern = counter_control_extern;
6730 
6731 	mutex_lock(&devlink->lock);
6732 	list_add_tail_rcu(&table->list, &devlink->dpipe_table_list);
6733 	mutex_unlock(&devlink->lock);
6734 	return 0;
6735 }
6736 EXPORT_SYMBOL_GPL(devlink_dpipe_table_register);
6737 
6738 /**
6739  *	devlink_dpipe_table_unregister - unregister dpipe table
6740  *
6741  *	@devlink: devlink
6742  *	@table_name: table name
6743  */
devlink_dpipe_table_unregister(struct devlink * devlink,const char * table_name)6744 void devlink_dpipe_table_unregister(struct devlink *devlink,
6745 				    const char *table_name)
6746 {
6747 	struct devlink_dpipe_table *table;
6748 
6749 	mutex_lock(&devlink->lock);
6750 	table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
6751 					 table_name);
6752 	if (!table)
6753 		goto unlock;
6754 	list_del_rcu(&table->list);
6755 	mutex_unlock(&devlink->lock);
6756 	kfree_rcu(table, rcu);
6757 	return;
6758 unlock:
6759 	mutex_unlock(&devlink->lock);
6760 }
6761 EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister);
6762 
6763 /**
6764  *	devlink_resource_register - devlink resource register
6765  *
6766  *	@devlink: devlink
6767  *	@resource_name: resource's name
6768  *	@resource_size: resource's size
6769  *	@resource_id: resource's id
6770  *	@parent_resource_id: resource's parent id
6771  *	@size_params: size parameters
6772  */
devlink_resource_register(struct devlink * devlink,const char * resource_name,u64 resource_size,u64 resource_id,u64 parent_resource_id,const struct devlink_resource_size_params * size_params)6773 int devlink_resource_register(struct devlink *devlink,
6774 			      const char *resource_name,
6775 			      u64 resource_size,
6776 			      u64 resource_id,
6777 			      u64 parent_resource_id,
6778 			      const struct devlink_resource_size_params *size_params)
6779 {
6780 	struct devlink_resource *resource;
6781 	struct list_head *resource_list;
6782 	bool top_hierarchy;
6783 	int err = 0;
6784 
6785 	top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP;
6786 
6787 	mutex_lock(&devlink->lock);
6788 	resource = devlink_resource_find(devlink, NULL, resource_id);
6789 	if (resource) {
6790 		err = -EINVAL;
6791 		goto out;
6792 	}
6793 
6794 	resource = kzalloc(sizeof(*resource), GFP_KERNEL);
6795 	if (!resource) {
6796 		err = -ENOMEM;
6797 		goto out;
6798 	}
6799 
6800 	if (top_hierarchy) {
6801 		resource_list = &devlink->resource_list;
6802 	} else {
6803 		struct devlink_resource *parent_resource;
6804 
6805 		parent_resource = devlink_resource_find(devlink, NULL,
6806 							parent_resource_id);
6807 		if (parent_resource) {
6808 			resource_list = &parent_resource->resource_list;
6809 			resource->parent = parent_resource;
6810 		} else {
6811 			kfree(resource);
6812 			err = -EINVAL;
6813 			goto out;
6814 		}
6815 	}
6816 
6817 	resource->name = resource_name;
6818 	resource->size = resource_size;
6819 	resource->size_new = resource_size;
6820 	resource->id = resource_id;
6821 	resource->size_valid = true;
6822 	memcpy(&resource->size_params, size_params,
6823 	       sizeof(resource->size_params));
6824 	INIT_LIST_HEAD(&resource->resource_list);
6825 	list_add_tail(&resource->list, resource_list);
6826 out:
6827 	mutex_unlock(&devlink->lock);
6828 	return err;
6829 }
6830 EXPORT_SYMBOL_GPL(devlink_resource_register);
6831 
6832 /**
6833  *	devlink_resources_unregister - free all resources
6834  *
6835  *	@devlink: devlink
6836  *	@resource: resource
6837  */
devlink_resources_unregister(struct devlink * devlink,struct devlink_resource * resource)6838 void devlink_resources_unregister(struct devlink *devlink,
6839 				  struct devlink_resource *resource)
6840 {
6841 	struct devlink_resource *tmp, *child_resource;
6842 	struct list_head *resource_list;
6843 
6844 	if (resource)
6845 		resource_list = &resource->resource_list;
6846 	else
6847 		resource_list = &devlink->resource_list;
6848 
6849 	if (!resource)
6850 		mutex_lock(&devlink->lock);
6851 
6852 	list_for_each_entry_safe(child_resource, tmp, resource_list, list) {
6853 		devlink_resources_unregister(devlink, child_resource);
6854 		list_del(&child_resource->list);
6855 		kfree(child_resource);
6856 	}
6857 
6858 	if (!resource)
6859 		mutex_unlock(&devlink->lock);
6860 }
6861 EXPORT_SYMBOL_GPL(devlink_resources_unregister);
6862 
6863 /**
6864  *	devlink_resource_size_get - get and update size
6865  *
6866  *	@devlink: devlink
6867  *	@resource_id: the requested resource id
6868  *	@p_resource_size: ptr to update
6869  */
devlink_resource_size_get(struct devlink * devlink,u64 resource_id,u64 * p_resource_size)6870 int devlink_resource_size_get(struct devlink *devlink,
6871 			      u64 resource_id,
6872 			      u64 *p_resource_size)
6873 {
6874 	struct devlink_resource *resource;
6875 	int err = 0;
6876 
6877 	mutex_lock(&devlink->lock);
6878 	resource = devlink_resource_find(devlink, NULL, resource_id);
6879 	if (!resource) {
6880 		err = -EINVAL;
6881 		goto out;
6882 	}
6883 	*p_resource_size = resource->size_new;
6884 	resource->size = resource->size_new;
6885 out:
6886 	mutex_unlock(&devlink->lock);
6887 	return err;
6888 }
6889 EXPORT_SYMBOL_GPL(devlink_resource_size_get);
6890 
6891 /**
6892  *	devlink_dpipe_table_resource_set - set the resource id
6893  *
6894  *	@devlink: devlink
6895  *	@table_name: table name
6896  *	@resource_id: resource id
6897  *	@resource_units: number of resource's units consumed per table's entry
6898  */
devlink_dpipe_table_resource_set(struct devlink * devlink,const char * table_name,u64 resource_id,u64 resource_units)6899 int devlink_dpipe_table_resource_set(struct devlink *devlink,
6900 				     const char *table_name, u64 resource_id,
6901 				     u64 resource_units)
6902 {
6903 	struct devlink_dpipe_table *table;
6904 	int err = 0;
6905 
6906 	mutex_lock(&devlink->lock);
6907 	table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
6908 					 table_name);
6909 	if (!table) {
6910 		err = -EINVAL;
6911 		goto out;
6912 	}
6913 	table->resource_id = resource_id;
6914 	table->resource_units = resource_units;
6915 	table->resource_valid = true;
6916 out:
6917 	mutex_unlock(&devlink->lock);
6918 	return err;
6919 }
6920 EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set);
6921 
6922 /**
6923  *	devlink_resource_occ_get_register - register occupancy getter
6924  *
6925  *	@devlink: devlink
6926  *	@resource_id: resource id
6927  *	@occ_get: occupancy getter callback
6928  *	@occ_get_priv: occupancy getter callback priv
6929  */
devlink_resource_occ_get_register(struct devlink * devlink,u64 resource_id,devlink_resource_occ_get_t * occ_get,void * occ_get_priv)6930 void devlink_resource_occ_get_register(struct devlink *devlink,
6931 				       u64 resource_id,
6932 				       devlink_resource_occ_get_t *occ_get,
6933 				       void *occ_get_priv)
6934 {
6935 	struct devlink_resource *resource;
6936 
6937 	mutex_lock(&devlink->lock);
6938 	resource = devlink_resource_find(devlink, NULL, resource_id);
6939 	if (WARN_ON(!resource))
6940 		goto out;
6941 	WARN_ON(resource->occ_get);
6942 
6943 	resource->occ_get = occ_get;
6944 	resource->occ_get_priv = occ_get_priv;
6945 out:
6946 	mutex_unlock(&devlink->lock);
6947 }
6948 EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register);
6949 
6950 /**
6951  *	devlink_resource_occ_get_unregister - unregister occupancy getter
6952  *
6953  *	@devlink: devlink
6954  *	@resource_id: resource id
6955  */
devlink_resource_occ_get_unregister(struct devlink * devlink,u64 resource_id)6956 void devlink_resource_occ_get_unregister(struct devlink *devlink,
6957 					 u64 resource_id)
6958 {
6959 	struct devlink_resource *resource;
6960 
6961 	mutex_lock(&devlink->lock);
6962 	resource = devlink_resource_find(devlink, NULL, resource_id);
6963 	if (WARN_ON(!resource))
6964 		goto out;
6965 	WARN_ON(!resource->occ_get);
6966 
6967 	resource->occ_get = NULL;
6968 	resource->occ_get_priv = NULL;
6969 out:
6970 	mutex_unlock(&devlink->lock);
6971 }
6972 EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister);
6973 
devlink_param_verify(const struct devlink_param * param)6974 static int devlink_param_verify(const struct devlink_param *param)
6975 {
6976 	if (!param || !param->name || !param->supported_cmodes)
6977 		return -EINVAL;
6978 	if (param->generic)
6979 		return devlink_param_generic_verify(param);
6980 	else
6981 		return devlink_param_driver_verify(param);
6982 }
6983 
__devlink_params_register(struct devlink * devlink,unsigned int port_index,struct list_head * param_list,const struct devlink_param * params,size_t params_count,enum devlink_command reg_cmd,enum devlink_command unreg_cmd)6984 static int __devlink_params_register(struct devlink *devlink,
6985 				     unsigned int port_index,
6986 				     struct list_head *param_list,
6987 				     const struct devlink_param *params,
6988 				     size_t params_count,
6989 				     enum devlink_command reg_cmd,
6990 				     enum devlink_command unreg_cmd)
6991 {
6992 	const struct devlink_param *param = params;
6993 	int i;
6994 	int err;
6995 
6996 	mutex_lock(&devlink->lock);
6997 	for (i = 0; i < params_count; i++, param++) {
6998 		err = devlink_param_verify(param);
6999 		if (err)
7000 			goto rollback;
7001 
7002 		err = devlink_param_register_one(devlink, port_index,
7003 						 param_list, param, reg_cmd);
7004 		if (err)
7005 			goto rollback;
7006 	}
7007 
7008 	mutex_unlock(&devlink->lock);
7009 	return 0;
7010 
7011 rollback:
7012 	if (!i)
7013 		goto unlock;
7014 	for (param--; i > 0; i--, param--)
7015 		devlink_param_unregister_one(devlink, port_index, param_list,
7016 					     param, unreg_cmd);
7017 unlock:
7018 	mutex_unlock(&devlink->lock);
7019 	return err;
7020 }
7021 
__devlink_params_unregister(struct devlink * devlink,unsigned int port_index,struct list_head * param_list,const struct devlink_param * params,size_t params_count,enum devlink_command cmd)7022 static void __devlink_params_unregister(struct devlink *devlink,
7023 					unsigned int port_index,
7024 					struct list_head *param_list,
7025 					const struct devlink_param *params,
7026 					size_t params_count,
7027 					enum devlink_command cmd)
7028 {
7029 	const struct devlink_param *param = params;
7030 	int i;
7031 
7032 	mutex_lock(&devlink->lock);
7033 	for (i = 0; i < params_count; i++, param++)
7034 		devlink_param_unregister_one(devlink, 0, param_list, param,
7035 					     cmd);
7036 	mutex_unlock(&devlink->lock);
7037 }
7038 
7039 /**
7040  *	devlink_params_register - register configuration parameters
7041  *
7042  *	@devlink: devlink
7043  *	@params: configuration parameters array
7044  *	@params_count: number of parameters provided
7045  *
7046  *	Register the configuration parameters supported by the driver.
7047  */
devlink_params_register(struct devlink * devlink,const struct devlink_param * params,size_t params_count)7048 int devlink_params_register(struct devlink *devlink,
7049 			    const struct devlink_param *params,
7050 			    size_t params_count)
7051 {
7052 	return __devlink_params_register(devlink, 0, &devlink->param_list,
7053 					 params, params_count,
7054 					 DEVLINK_CMD_PARAM_NEW,
7055 					 DEVLINK_CMD_PARAM_DEL);
7056 }
7057 EXPORT_SYMBOL_GPL(devlink_params_register);
7058 
7059 /**
7060  *	devlink_params_unregister - unregister configuration parameters
7061  *	@devlink: devlink
7062  *	@params: configuration parameters to unregister
7063  *	@params_count: number of parameters provided
7064  */
devlink_params_unregister(struct devlink * devlink,const struct devlink_param * params,size_t params_count)7065 void devlink_params_unregister(struct devlink *devlink,
7066 			       const struct devlink_param *params,
7067 			       size_t params_count)
7068 {
7069 	return __devlink_params_unregister(devlink, 0, &devlink->param_list,
7070 					   params, params_count,
7071 					   DEVLINK_CMD_PARAM_DEL);
7072 }
7073 EXPORT_SYMBOL_GPL(devlink_params_unregister);
7074 
7075 /**
7076  *	devlink_params_publish - publish configuration parameters
7077  *
7078  *	@devlink: devlink
7079  *
7080  *	Publish previously registered configuration parameters.
7081  */
devlink_params_publish(struct devlink * devlink)7082 void devlink_params_publish(struct devlink *devlink)
7083 {
7084 	struct devlink_param_item *param_item;
7085 
7086 	list_for_each_entry(param_item, &devlink->param_list, list) {
7087 		if (param_item->published)
7088 			continue;
7089 		param_item->published = true;
7090 		devlink_param_notify(devlink, 0, param_item,
7091 				     DEVLINK_CMD_PARAM_NEW);
7092 	}
7093 }
7094 EXPORT_SYMBOL_GPL(devlink_params_publish);
7095 
7096 /**
7097  *	devlink_params_unpublish - unpublish configuration parameters
7098  *
7099  *	@devlink: devlink
7100  *
7101  *	Unpublish previously registered configuration parameters.
7102  */
devlink_params_unpublish(struct devlink * devlink)7103 void devlink_params_unpublish(struct devlink *devlink)
7104 {
7105 	struct devlink_param_item *param_item;
7106 
7107 	list_for_each_entry(param_item, &devlink->param_list, list) {
7108 		if (!param_item->published)
7109 			continue;
7110 		param_item->published = false;
7111 		devlink_param_notify(devlink, 0, param_item,
7112 				     DEVLINK_CMD_PARAM_DEL);
7113 	}
7114 }
7115 EXPORT_SYMBOL_GPL(devlink_params_unpublish);
7116 
7117 /**
7118  *	devlink_port_params_register - register port configuration parameters
7119  *
7120  *	@devlink_port: devlink port
7121  *	@params: configuration parameters array
7122  *	@params_count: number of parameters provided
7123  *
7124  *	Register the configuration parameters supported by the port.
7125  */
devlink_port_params_register(struct devlink_port * devlink_port,const struct devlink_param * params,size_t params_count)7126 int devlink_port_params_register(struct devlink_port *devlink_port,
7127 				 const struct devlink_param *params,
7128 				 size_t params_count)
7129 {
7130 	return __devlink_params_register(devlink_port->devlink,
7131 					 devlink_port->index,
7132 					 &devlink_port->param_list, params,
7133 					 params_count,
7134 					 DEVLINK_CMD_PORT_PARAM_NEW,
7135 					 DEVLINK_CMD_PORT_PARAM_DEL);
7136 }
7137 EXPORT_SYMBOL_GPL(devlink_port_params_register);
7138 
7139 /**
7140  *	devlink_port_params_unregister - unregister port configuration
7141  *	parameters
7142  *
7143  *	@devlink_port: devlink port
7144  *	@params: configuration parameters array
7145  *	@params_count: number of parameters provided
7146  */
devlink_port_params_unregister(struct devlink_port * devlink_port,const struct devlink_param * params,size_t params_count)7147 void devlink_port_params_unregister(struct devlink_port *devlink_port,
7148 				    const struct devlink_param *params,
7149 				    size_t params_count)
7150 {
7151 	return __devlink_params_unregister(devlink_port->devlink,
7152 					   devlink_port->index,
7153 					   &devlink_port->param_list,
7154 					   params, params_count,
7155 					   DEVLINK_CMD_PORT_PARAM_DEL);
7156 }
7157 EXPORT_SYMBOL_GPL(devlink_port_params_unregister);
7158 
7159 static int
__devlink_param_driverinit_value_get(struct list_head * param_list,u32 param_id,union devlink_param_value * init_val)7160 __devlink_param_driverinit_value_get(struct list_head *param_list, u32 param_id,
7161 				     union devlink_param_value *init_val)
7162 {
7163 	struct devlink_param_item *param_item;
7164 
7165 	param_item = devlink_param_find_by_id(param_list, param_id);
7166 	if (!param_item)
7167 		return -EINVAL;
7168 
7169 	if (!param_item->driverinit_value_valid ||
7170 	    !devlink_param_cmode_is_supported(param_item->param,
7171 					      DEVLINK_PARAM_CMODE_DRIVERINIT))
7172 		return -EOPNOTSUPP;
7173 
7174 	if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
7175 		strcpy(init_val->vstr, param_item->driverinit_value.vstr);
7176 	else
7177 		*init_val = param_item->driverinit_value;
7178 
7179 	return 0;
7180 }
7181 
7182 static int
__devlink_param_driverinit_value_set(struct devlink * devlink,unsigned int port_index,struct list_head * param_list,u32 param_id,union devlink_param_value init_val,enum devlink_command cmd)7183 __devlink_param_driverinit_value_set(struct devlink *devlink,
7184 				     unsigned int port_index,
7185 				     struct list_head *param_list, u32 param_id,
7186 				     union devlink_param_value init_val,
7187 				     enum devlink_command cmd)
7188 {
7189 	struct devlink_param_item *param_item;
7190 
7191 	param_item = devlink_param_find_by_id(param_list, param_id);
7192 	if (!param_item)
7193 		return -EINVAL;
7194 
7195 	if (!devlink_param_cmode_is_supported(param_item->param,
7196 					      DEVLINK_PARAM_CMODE_DRIVERINIT))
7197 		return -EOPNOTSUPP;
7198 
7199 	if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
7200 		strcpy(param_item->driverinit_value.vstr, init_val.vstr);
7201 	else
7202 		param_item->driverinit_value = init_val;
7203 	param_item->driverinit_value_valid = true;
7204 
7205 	devlink_param_notify(devlink, port_index, param_item, cmd);
7206 	return 0;
7207 }
7208 
7209 /**
7210  *	devlink_param_driverinit_value_get - get configuration parameter
7211  *					     value for driver initializing
7212  *
7213  *	@devlink: devlink
7214  *	@param_id: parameter ID
7215  *	@init_val: value of parameter in driverinit configuration mode
7216  *
7217  *	This function should be used by the driver to get driverinit
7218  *	configuration for initialization after reload command.
7219  */
devlink_param_driverinit_value_get(struct devlink * devlink,u32 param_id,union devlink_param_value * init_val)7220 int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
7221 				       union devlink_param_value *init_val)
7222 {
7223 	if (!devlink_reload_supported(devlink))
7224 		return -EOPNOTSUPP;
7225 
7226 	return __devlink_param_driverinit_value_get(&devlink->param_list,
7227 						    param_id, init_val);
7228 }
7229 EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_get);
7230 
7231 /**
7232  *	devlink_param_driverinit_value_set - set value of configuration
7233  *					     parameter for driverinit
7234  *					     configuration mode
7235  *
7236  *	@devlink: devlink
7237  *	@param_id: parameter ID
7238  *	@init_val: value of parameter to set for driverinit configuration mode
7239  *
7240  *	This function should be used by the driver to set driverinit
7241  *	configuration mode default value.
7242  */
devlink_param_driverinit_value_set(struct devlink * devlink,u32 param_id,union devlink_param_value init_val)7243 int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
7244 				       union devlink_param_value init_val)
7245 {
7246 	return __devlink_param_driverinit_value_set(devlink, 0,
7247 						    &devlink->param_list,
7248 						    param_id, init_val,
7249 						    DEVLINK_CMD_PARAM_NEW);
7250 }
7251 EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_set);
7252 
7253 /**
7254  *	devlink_port_param_driverinit_value_get - get configuration parameter
7255  *						value for driver initializing
7256  *
7257  *	@devlink_port: devlink_port
7258  *	@param_id: parameter ID
7259  *	@init_val: value of parameter in driverinit configuration mode
7260  *
7261  *	This function should be used by the driver to get driverinit
7262  *	configuration for initialization after reload command.
7263  */
devlink_port_param_driverinit_value_get(struct devlink_port * devlink_port,u32 param_id,union devlink_param_value * init_val)7264 int devlink_port_param_driverinit_value_get(struct devlink_port *devlink_port,
7265 					    u32 param_id,
7266 					    union devlink_param_value *init_val)
7267 {
7268 	struct devlink *devlink = devlink_port->devlink;
7269 
7270 	if (!devlink_reload_supported(devlink))
7271 		return -EOPNOTSUPP;
7272 
7273 	return __devlink_param_driverinit_value_get(&devlink_port->param_list,
7274 						    param_id, init_val);
7275 }
7276 EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_get);
7277 
7278 /**
7279  *     devlink_port_param_driverinit_value_set - set value of configuration
7280  *                                               parameter for driverinit
7281  *                                               configuration mode
7282  *
7283  *     @devlink_port: devlink_port
7284  *     @param_id: parameter ID
7285  *     @init_val: value of parameter to set for driverinit configuration mode
7286  *
7287  *     This function should be used by the driver to set driverinit
7288  *     configuration mode default value.
7289  */
devlink_port_param_driverinit_value_set(struct devlink_port * devlink_port,u32 param_id,union devlink_param_value init_val)7290 int devlink_port_param_driverinit_value_set(struct devlink_port *devlink_port,
7291 					    u32 param_id,
7292 					    union devlink_param_value init_val)
7293 {
7294 	return __devlink_param_driverinit_value_set(devlink_port->devlink,
7295 						    devlink_port->index,
7296 						    &devlink_port->param_list,
7297 						    param_id, init_val,
7298 						    DEVLINK_CMD_PORT_PARAM_NEW);
7299 }
7300 EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_set);
7301 
7302 /**
7303  *	devlink_param_value_changed - notify devlink on a parameter's value
7304  *				      change. Should be called by the driver
7305  *				      right after the change.
7306  *
7307  *	@devlink: devlink
7308  *	@param_id: parameter ID
7309  *
7310  *	This function should be used by the driver to notify devlink on value
7311  *	change, excluding driverinit configuration mode.
7312  *	For driverinit configuration mode driver should use the function
7313  */
devlink_param_value_changed(struct devlink * devlink,u32 param_id)7314 void devlink_param_value_changed(struct devlink *devlink, u32 param_id)
7315 {
7316 	struct devlink_param_item *param_item;
7317 
7318 	param_item = devlink_param_find_by_id(&devlink->param_list, param_id);
7319 	WARN_ON(!param_item);
7320 
7321 	devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
7322 }
7323 EXPORT_SYMBOL_GPL(devlink_param_value_changed);
7324 
7325 /**
7326  *     devlink_port_param_value_changed - notify devlink on a parameter's value
7327  *                                      change. Should be called by the driver
7328  *                                      right after the change.
7329  *
7330  *     @devlink_port: devlink_port
7331  *     @param_id: parameter ID
7332  *
7333  *     This function should be used by the driver to notify devlink on value
7334  *     change, excluding driverinit configuration mode.
7335  *     For driverinit configuration mode driver should use the function
7336  *     devlink_port_param_driverinit_value_set() instead.
7337  */
devlink_port_param_value_changed(struct devlink_port * devlink_port,u32 param_id)7338 void devlink_port_param_value_changed(struct devlink_port *devlink_port,
7339 				      u32 param_id)
7340 {
7341 	struct devlink_param_item *param_item;
7342 
7343 	param_item = devlink_param_find_by_id(&devlink_port->param_list,
7344 					      param_id);
7345 	WARN_ON(!param_item);
7346 
7347 	devlink_param_notify(devlink_port->devlink, devlink_port->index,
7348 			     param_item, DEVLINK_CMD_PORT_PARAM_NEW);
7349 }
7350 EXPORT_SYMBOL_GPL(devlink_port_param_value_changed);
7351 
7352 /**
7353  *	devlink_param_value_str_fill - Safely fill-up the string preventing
7354  *				       from overflow of the preallocated buffer
7355  *
7356  *	@dst_val: destination devlink_param_value
7357  *	@src: source buffer
7358  */
devlink_param_value_str_fill(union devlink_param_value * dst_val,const char * src)7359 void devlink_param_value_str_fill(union devlink_param_value *dst_val,
7360 				  const char *src)
7361 {
7362 	size_t len;
7363 
7364 	len = strlcpy(dst_val->vstr, src, __DEVLINK_PARAM_MAX_STRING_VALUE);
7365 	WARN_ON(len >= __DEVLINK_PARAM_MAX_STRING_VALUE);
7366 }
7367 EXPORT_SYMBOL_GPL(devlink_param_value_str_fill);
7368 
7369 /**
7370  *	devlink_region_create - create a new address region
7371  *
7372  *	@devlink: devlink
7373  *	@region_name: region name
7374  *	@region_max_snapshots: Maximum supported number of snapshots for region
7375  *	@region_size: size of region
7376  */
devlink_region_create(struct devlink * devlink,const char * region_name,u32 region_max_snapshots,u64 region_size)7377 struct devlink_region *devlink_region_create(struct devlink *devlink,
7378 					     const char *region_name,
7379 					     u32 region_max_snapshots,
7380 					     u64 region_size)
7381 {
7382 	struct devlink_region *region;
7383 	int err = 0;
7384 
7385 	mutex_lock(&devlink->lock);
7386 
7387 	if (devlink_region_get_by_name(devlink, region_name)) {
7388 		err = -EEXIST;
7389 		goto unlock;
7390 	}
7391 
7392 	region = kzalloc(sizeof(*region), GFP_KERNEL);
7393 	if (!region) {
7394 		err = -ENOMEM;
7395 		goto unlock;
7396 	}
7397 
7398 	region->devlink = devlink;
7399 	region->max_snapshots = region_max_snapshots;
7400 	region->name = region_name;
7401 	region->size = region_size;
7402 	INIT_LIST_HEAD(&region->snapshot_list);
7403 	list_add_tail(&region->list, &devlink->region_list);
7404 	devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
7405 
7406 	mutex_unlock(&devlink->lock);
7407 	return region;
7408 
7409 unlock:
7410 	mutex_unlock(&devlink->lock);
7411 	return ERR_PTR(err);
7412 }
7413 EXPORT_SYMBOL_GPL(devlink_region_create);
7414 
7415 /**
7416  *	devlink_region_destroy - destroy address region
7417  *
7418  *	@region: devlink region to destroy
7419  */
devlink_region_destroy(struct devlink_region * region)7420 void devlink_region_destroy(struct devlink_region *region)
7421 {
7422 	struct devlink *devlink = region->devlink;
7423 	struct devlink_snapshot *snapshot, *ts;
7424 
7425 	mutex_lock(&devlink->lock);
7426 
7427 	/* Free all snapshots of region */
7428 	list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list)
7429 		devlink_region_snapshot_del(region, snapshot);
7430 
7431 	list_del(&region->list);
7432 
7433 	devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
7434 	mutex_unlock(&devlink->lock);
7435 	kfree(region);
7436 }
7437 EXPORT_SYMBOL_GPL(devlink_region_destroy);
7438 
7439 /**
7440  *	devlink_region_shapshot_id_get - get snapshot ID
7441  *
7442  *	This callback should be called when adding a new snapshot,
7443  *	Driver should use the same id for multiple snapshots taken
7444  *	on multiple regions at the same time/by the same trigger.
7445  *
7446  *	@devlink: devlink
7447  */
devlink_region_shapshot_id_get(struct devlink * devlink)7448 u32 devlink_region_shapshot_id_get(struct devlink *devlink)
7449 {
7450 	u32 id;
7451 
7452 	mutex_lock(&devlink->lock);
7453 	id = ++devlink->snapshot_id;
7454 	mutex_unlock(&devlink->lock);
7455 
7456 	return id;
7457 }
7458 EXPORT_SYMBOL_GPL(devlink_region_shapshot_id_get);
7459 
7460 /**
7461  *	devlink_region_snapshot_create - create a new snapshot
7462  *	This will add a new snapshot of a region. The snapshot
7463  *	will be stored on the region struct and can be accessed
7464  *	from devlink. This is useful for future	analyses of snapshots.
7465  *	Multiple snapshots can be created on a region.
7466  *	The @snapshot_id should be obtained using the getter function.
7467  *
7468  *	@region: devlink region of the snapshot
7469  *	@data: snapshot data
7470  *	@snapshot_id: snapshot id to be created
7471  *	@data_destructor: pointer to destructor function to free data
7472  */
devlink_region_snapshot_create(struct devlink_region * region,u8 * data,u32 snapshot_id,devlink_snapshot_data_dest_t * data_destructor)7473 int devlink_region_snapshot_create(struct devlink_region *region,
7474 				   u8 *data, u32 snapshot_id,
7475 				   devlink_snapshot_data_dest_t *data_destructor)
7476 {
7477 	struct devlink *devlink = region->devlink;
7478 	struct devlink_snapshot *snapshot;
7479 	int err;
7480 
7481 	mutex_lock(&devlink->lock);
7482 
7483 	/* check if region can hold one more snapshot */
7484 	if (region->cur_snapshots == region->max_snapshots) {
7485 		err = -ENOMEM;
7486 		goto unlock;
7487 	}
7488 
7489 	if (devlink_region_snapshot_get_by_id(region, snapshot_id)) {
7490 		err = -EEXIST;
7491 		goto unlock;
7492 	}
7493 
7494 	snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL);
7495 	if (!snapshot) {
7496 		err = -ENOMEM;
7497 		goto unlock;
7498 	}
7499 
7500 	snapshot->id = snapshot_id;
7501 	snapshot->region = region;
7502 	snapshot->data = data;
7503 	snapshot->data_destructor = data_destructor;
7504 
7505 	list_add_tail(&snapshot->list, &region->snapshot_list);
7506 
7507 	region->cur_snapshots++;
7508 
7509 	devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW);
7510 	mutex_unlock(&devlink->lock);
7511 	return 0;
7512 
7513 unlock:
7514 	mutex_unlock(&devlink->lock);
7515 	return err;
7516 }
7517 EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);
7518 
7519 #define DEVLINK_TRAP(_id, _type)					      \
7520 	{								      \
7521 		.type = DEVLINK_TRAP_TYPE_##_type,			      \
7522 		.id = DEVLINK_TRAP_GENERIC_ID_##_id,			      \
7523 		.name = DEVLINK_TRAP_GENERIC_NAME_##_id,		      \
7524 	}
7525 
7526 static const struct devlink_trap devlink_trap_generic[] = {
7527 	DEVLINK_TRAP(SMAC_MC, DROP),
7528 	DEVLINK_TRAP(VLAN_TAG_MISMATCH, DROP),
7529 	DEVLINK_TRAP(INGRESS_VLAN_FILTER, DROP),
7530 	DEVLINK_TRAP(INGRESS_STP_FILTER, DROP),
7531 	DEVLINK_TRAP(EMPTY_TX_LIST, DROP),
7532 	DEVLINK_TRAP(PORT_LOOPBACK_FILTER, DROP),
7533 	DEVLINK_TRAP(BLACKHOLE_ROUTE, DROP),
7534 	DEVLINK_TRAP(TTL_ERROR, EXCEPTION),
7535 	DEVLINK_TRAP(TAIL_DROP, DROP),
7536 };
7537 
7538 #define DEVLINK_TRAP_GROUP(_id)						      \
7539 	{								      \
7540 		.id = DEVLINK_TRAP_GROUP_GENERIC_ID_##_id,		      \
7541 		.name = DEVLINK_TRAP_GROUP_GENERIC_NAME_##_id,		      \
7542 	}
7543 
7544 static const struct devlink_trap_group devlink_trap_group_generic[] = {
7545 	DEVLINK_TRAP_GROUP(L2_DROPS),
7546 	DEVLINK_TRAP_GROUP(L3_DROPS),
7547 	DEVLINK_TRAP_GROUP(BUFFER_DROPS),
7548 };
7549 
devlink_trap_generic_verify(const struct devlink_trap * trap)7550 static int devlink_trap_generic_verify(const struct devlink_trap *trap)
7551 {
7552 	if (trap->id > DEVLINK_TRAP_GENERIC_ID_MAX)
7553 		return -EINVAL;
7554 
7555 	if (strcmp(trap->name, devlink_trap_generic[trap->id].name))
7556 		return -EINVAL;
7557 
7558 	if (trap->type != devlink_trap_generic[trap->id].type)
7559 		return -EINVAL;
7560 
7561 	return 0;
7562 }
7563 
devlink_trap_driver_verify(const struct devlink_trap * trap)7564 static int devlink_trap_driver_verify(const struct devlink_trap *trap)
7565 {
7566 	int i;
7567 
7568 	if (trap->id <= DEVLINK_TRAP_GENERIC_ID_MAX)
7569 		return -EINVAL;
7570 
7571 	for (i = 0; i < ARRAY_SIZE(devlink_trap_generic); i++) {
7572 		if (!strcmp(trap->name, devlink_trap_generic[i].name))
7573 			return -EEXIST;
7574 	}
7575 
7576 	return 0;
7577 }
7578 
devlink_trap_verify(const struct devlink_trap * trap)7579 static int devlink_trap_verify(const struct devlink_trap *trap)
7580 {
7581 	if (!trap || !trap->name || !trap->group.name)
7582 		return -EINVAL;
7583 
7584 	if (trap->generic)
7585 		return devlink_trap_generic_verify(trap);
7586 	else
7587 		return devlink_trap_driver_verify(trap);
7588 }
7589 
7590 static int
devlink_trap_group_generic_verify(const struct devlink_trap_group * group)7591 devlink_trap_group_generic_verify(const struct devlink_trap_group *group)
7592 {
7593 	if (group->id > DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
7594 		return -EINVAL;
7595 
7596 	if (strcmp(group->name, devlink_trap_group_generic[group->id].name))
7597 		return -EINVAL;
7598 
7599 	return 0;
7600 }
7601 
7602 static int
devlink_trap_group_driver_verify(const struct devlink_trap_group * group)7603 devlink_trap_group_driver_verify(const struct devlink_trap_group *group)
7604 {
7605 	int i;
7606 
7607 	if (group->id <= DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
7608 		return -EINVAL;
7609 
7610 	for (i = 0; i < ARRAY_SIZE(devlink_trap_group_generic); i++) {
7611 		if (!strcmp(group->name, devlink_trap_group_generic[i].name))
7612 			return -EEXIST;
7613 	}
7614 
7615 	return 0;
7616 }
7617 
devlink_trap_group_verify(const struct devlink_trap_group * group)7618 static int devlink_trap_group_verify(const struct devlink_trap_group *group)
7619 {
7620 	if (group->generic)
7621 		return devlink_trap_group_generic_verify(group);
7622 	else
7623 		return devlink_trap_group_driver_verify(group);
7624 }
7625 
7626 static void
devlink_trap_group_notify(struct devlink * devlink,const struct devlink_trap_group_item * group_item,enum devlink_command cmd)7627 devlink_trap_group_notify(struct devlink *devlink,
7628 			  const struct devlink_trap_group_item *group_item,
7629 			  enum devlink_command cmd)
7630 {
7631 	struct sk_buff *msg;
7632 	int err;
7633 
7634 	WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_GROUP_NEW &&
7635 		     cmd != DEVLINK_CMD_TRAP_GROUP_DEL);
7636 
7637 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7638 	if (!msg)
7639 		return;
7640 
7641 	err = devlink_nl_trap_group_fill(msg, devlink, group_item, cmd, 0, 0,
7642 					 0);
7643 	if (err) {
7644 		nlmsg_free(msg);
7645 		return;
7646 	}
7647 
7648 	genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
7649 				msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
7650 }
7651 
7652 static struct devlink_trap_group_item *
devlink_trap_group_item_create(struct devlink * devlink,const struct devlink_trap_group * group)7653 devlink_trap_group_item_create(struct devlink *devlink,
7654 			       const struct devlink_trap_group *group)
7655 {
7656 	struct devlink_trap_group_item *group_item;
7657 	int err;
7658 
7659 	err = devlink_trap_group_verify(group);
7660 	if (err)
7661 		return ERR_PTR(err);
7662 
7663 	group_item = kzalloc(sizeof(*group_item), GFP_KERNEL);
7664 	if (!group_item)
7665 		return ERR_PTR(-ENOMEM);
7666 
7667 	group_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
7668 	if (!group_item->stats) {
7669 		err = -ENOMEM;
7670 		goto err_stats_alloc;
7671 	}
7672 
7673 	group_item->group = group;
7674 	refcount_set(&group_item->refcount, 1);
7675 
7676 	if (devlink->ops->trap_group_init) {
7677 		err = devlink->ops->trap_group_init(devlink, group);
7678 		if (err)
7679 			goto err_group_init;
7680 	}
7681 
7682 	list_add_tail(&group_item->list, &devlink->trap_group_list);
7683 	devlink_trap_group_notify(devlink, group_item,
7684 				  DEVLINK_CMD_TRAP_GROUP_NEW);
7685 
7686 	return group_item;
7687 
7688 err_group_init:
7689 	free_percpu(group_item->stats);
7690 err_stats_alloc:
7691 	kfree(group_item);
7692 	return ERR_PTR(err);
7693 }
7694 
7695 static void
devlink_trap_group_item_destroy(struct devlink * devlink,struct devlink_trap_group_item * group_item)7696 devlink_trap_group_item_destroy(struct devlink *devlink,
7697 				struct devlink_trap_group_item *group_item)
7698 {
7699 	devlink_trap_group_notify(devlink, group_item,
7700 				  DEVLINK_CMD_TRAP_GROUP_DEL);
7701 	list_del(&group_item->list);
7702 	free_percpu(group_item->stats);
7703 	kfree(group_item);
7704 }
7705 
7706 static struct devlink_trap_group_item *
devlink_trap_group_item_get(struct devlink * devlink,const struct devlink_trap_group * group)7707 devlink_trap_group_item_get(struct devlink *devlink,
7708 			    const struct devlink_trap_group *group)
7709 {
7710 	struct devlink_trap_group_item *group_item;
7711 
7712 	group_item = devlink_trap_group_item_lookup(devlink, group->name);
7713 	if (group_item) {
7714 		refcount_inc(&group_item->refcount);
7715 		return group_item;
7716 	}
7717 
7718 	return devlink_trap_group_item_create(devlink, group);
7719 }
7720 
7721 static void
devlink_trap_group_item_put(struct devlink * devlink,struct devlink_trap_group_item * group_item)7722 devlink_trap_group_item_put(struct devlink *devlink,
7723 			    struct devlink_trap_group_item *group_item)
7724 {
7725 	if (!refcount_dec_and_test(&group_item->refcount))
7726 		return;
7727 
7728 	devlink_trap_group_item_destroy(devlink, group_item);
7729 }
7730 
7731 static int
devlink_trap_item_group_link(struct devlink * devlink,struct devlink_trap_item * trap_item)7732 devlink_trap_item_group_link(struct devlink *devlink,
7733 			     struct devlink_trap_item *trap_item)
7734 {
7735 	struct devlink_trap_group_item *group_item;
7736 
7737 	group_item = devlink_trap_group_item_get(devlink,
7738 						 &trap_item->trap->group);
7739 	if (IS_ERR(group_item))
7740 		return PTR_ERR(group_item);
7741 
7742 	trap_item->group_item = group_item;
7743 
7744 	return 0;
7745 }
7746 
7747 static void
devlink_trap_item_group_unlink(struct devlink * devlink,struct devlink_trap_item * trap_item)7748 devlink_trap_item_group_unlink(struct devlink *devlink,
7749 			       struct devlink_trap_item *trap_item)
7750 {
7751 	devlink_trap_group_item_put(devlink, trap_item->group_item);
7752 }
7753 
devlink_trap_notify(struct devlink * devlink,const struct devlink_trap_item * trap_item,enum devlink_command cmd)7754 static void devlink_trap_notify(struct devlink *devlink,
7755 				const struct devlink_trap_item *trap_item,
7756 				enum devlink_command cmd)
7757 {
7758 	struct sk_buff *msg;
7759 	int err;
7760 
7761 	WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_NEW &&
7762 		     cmd != DEVLINK_CMD_TRAP_DEL);
7763 
7764 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7765 	if (!msg)
7766 		return;
7767 
7768 	err = devlink_nl_trap_fill(msg, devlink, trap_item, cmd, 0, 0, 0);
7769 	if (err) {
7770 		nlmsg_free(msg);
7771 		return;
7772 	}
7773 
7774 	genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
7775 				msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
7776 }
7777 
7778 static int
devlink_trap_register(struct devlink * devlink,const struct devlink_trap * trap,void * priv)7779 devlink_trap_register(struct devlink *devlink,
7780 		      const struct devlink_trap *trap, void *priv)
7781 {
7782 	struct devlink_trap_item *trap_item;
7783 	int err;
7784 
7785 	if (devlink_trap_item_lookup(devlink, trap->name))
7786 		return -EEXIST;
7787 
7788 	trap_item = kzalloc(sizeof(*trap_item), GFP_KERNEL);
7789 	if (!trap_item)
7790 		return -ENOMEM;
7791 
7792 	trap_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
7793 	if (!trap_item->stats) {
7794 		err = -ENOMEM;
7795 		goto err_stats_alloc;
7796 	}
7797 
7798 	trap_item->trap = trap;
7799 	trap_item->action = trap->init_action;
7800 	trap_item->priv = priv;
7801 
7802 	err = devlink_trap_item_group_link(devlink, trap_item);
7803 	if (err)
7804 		goto err_group_link;
7805 
7806 	err = devlink->ops->trap_init(devlink, trap, trap_item);
7807 	if (err)
7808 		goto err_trap_init;
7809 
7810 	list_add_tail(&trap_item->list, &devlink->trap_list);
7811 	devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW);
7812 
7813 	return 0;
7814 
7815 err_trap_init:
7816 	devlink_trap_item_group_unlink(devlink, trap_item);
7817 err_group_link:
7818 	free_percpu(trap_item->stats);
7819 err_stats_alloc:
7820 	kfree(trap_item);
7821 	return err;
7822 }
7823 
devlink_trap_unregister(struct devlink * devlink,const struct devlink_trap * trap)7824 static void devlink_trap_unregister(struct devlink *devlink,
7825 				    const struct devlink_trap *trap)
7826 {
7827 	struct devlink_trap_item *trap_item;
7828 
7829 	trap_item = devlink_trap_item_lookup(devlink, trap->name);
7830 	if (WARN_ON_ONCE(!trap_item))
7831 		return;
7832 
7833 	devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL);
7834 	list_del(&trap_item->list);
7835 	if (devlink->ops->trap_fini)
7836 		devlink->ops->trap_fini(devlink, trap, trap_item);
7837 	devlink_trap_item_group_unlink(devlink, trap_item);
7838 	free_percpu(trap_item->stats);
7839 	kfree(trap_item);
7840 }
7841 
devlink_trap_disable(struct devlink * devlink,const struct devlink_trap * trap)7842 static void devlink_trap_disable(struct devlink *devlink,
7843 				 const struct devlink_trap *trap)
7844 {
7845 	struct devlink_trap_item *trap_item;
7846 
7847 	trap_item = devlink_trap_item_lookup(devlink, trap->name);
7848 	if (WARN_ON_ONCE(!trap_item))
7849 		return;
7850 
7851 	devlink->ops->trap_action_set(devlink, trap, DEVLINK_TRAP_ACTION_DROP);
7852 	trap_item->action = DEVLINK_TRAP_ACTION_DROP;
7853 }
7854 
7855 /**
7856  * devlink_traps_register - Register packet traps with devlink.
7857  * @devlink: devlink.
7858  * @traps: Packet traps.
7859  * @traps_count: Count of provided packet traps.
7860  * @priv: Driver private information.
7861  *
7862  * Return: Non-zero value on failure.
7863  */
devlink_traps_register(struct devlink * devlink,const struct devlink_trap * traps,size_t traps_count,void * priv)7864 int devlink_traps_register(struct devlink *devlink,
7865 			   const struct devlink_trap *traps,
7866 			   size_t traps_count, void *priv)
7867 {
7868 	int i, err;
7869 
7870 	if (!devlink->ops->trap_init || !devlink->ops->trap_action_set)
7871 		return -EINVAL;
7872 
7873 	mutex_lock(&devlink->lock);
7874 	for (i = 0; i < traps_count; i++) {
7875 		const struct devlink_trap *trap = &traps[i];
7876 
7877 		err = devlink_trap_verify(trap);
7878 		if (err)
7879 			goto err_trap_verify;
7880 
7881 		err = devlink_trap_register(devlink, trap, priv);
7882 		if (err)
7883 			goto err_trap_register;
7884 	}
7885 	mutex_unlock(&devlink->lock);
7886 
7887 	return 0;
7888 
7889 err_trap_register:
7890 err_trap_verify:
7891 	for (i--; i >= 0; i--)
7892 		devlink_trap_unregister(devlink, &traps[i]);
7893 	mutex_unlock(&devlink->lock);
7894 	return err;
7895 }
7896 EXPORT_SYMBOL_GPL(devlink_traps_register);
7897 
7898 /**
7899  * devlink_traps_unregister - Unregister packet traps from devlink.
7900  * @devlink: devlink.
7901  * @traps: Packet traps.
7902  * @traps_count: Count of provided packet traps.
7903  */
devlink_traps_unregister(struct devlink * devlink,const struct devlink_trap * traps,size_t traps_count)7904 void devlink_traps_unregister(struct devlink *devlink,
7905 			      const struct devlink_trap *traps,
7906 			      size_t traps_count)
7907 {
7908 	int i;
7909 
7910 	mutex_lock(&devlink->lock);
7911 	/* Make sure we do not have any packets in-flight while unregistering
7912 	 * traps by disabling all of them and waiting for a grace period.
7913 	 */
7914 	for (i = traps_count - 1; i >= 0; i--)
7915 		devlink_trap_disable(devlink, &traps[i]);
7916 	synchronize_rcu();
7917 	for (i = traps_count - 1; i >= 0; i--)
7918 		devlink_trap_unregister(devlink, &traps[i]);
7919 	mutex_unlock(&devlink->lock);
7920 }
7921 EXPORT_SYMBOL_GPL(devlink_traps_unregister);
7922 
7923 static void
devlink_trap_stats_update(struct devlink_stats __percpu * trap_stats,size_t skb_len)7924 devlink_trap_stats_update(struct devlink_stats __percpu *trap_stats,
7925 			  size_t skb_len)
7926 {
7927 	struct devlink_stats *stats;
7928 
7929 	stats = this_cpu_ptr(trap_stats);
7930 	u64_stats_update_begin(&stats->syncp);
7931 	stats->rx_bytes += skb_len;
7932 	stats->rx_packets++;
7933 	u64_stats_update_end(&stats->syncp);
7934 }
7935 
7936 static void
devlink_trap_report_metadata_fill(struct net_dm_hw_metadata * hw_metadata,const struct devlink_trap_item * trap_item,struct devlink_port * in_devlink_port)7937 devlink_trap_report_metadata_fill(struct net_dm_hw_metadata *hw_metadata,
7938 				  const struct devlink_trap_item *trap_item,
7939 				  struct devlink_port *in_devlink_port)
7940 {
7941 	struct devlink_trap_group_item *group_item = trap_item->group_item;
7942 
7943 	hw_metadata->trap_group_name = group_item->group->name;
7944 	hw_metadata->trap_name = trap_item->trap->name;
7945 
7946 	spin_lock(&in_devlink_port->type_lock);
7947 	if (in_devlink_port->type == DEVLINK_PORT_TYPE_ETH)
7948 		hw_metadata->input_dev = in_devlink_port->type_dev;
7949 	spin_unlock(&in_devlink_port->type_lock);
7950 }
7951 
7952 /**
7953  * devlink_trap_report - Report trapped packet to drop monitor.
7954  * @devlink: devlink.
7955  * @skb: Trapped packet.
7956  * @trap_ctx: Trap context.
7957  * @in_devlink_port: Input devlink port.
7958  */
devlink_trap_report(struct devlink * devlink,struct sk_buff * skb,void * trap_ctx,struct devlink_port * in_devlink_port)7959 void devlink_trap_report(struct devlink *devlink, struct sk_buff *skb,
7960 			 void *trap_ctx, struct devlink_port *in_devlink_port)
7961 {
7962 	struct devlink_trap_item *trap_item = trap_ctx;
7963 	struct net_dm_hw_metadata hw_metadata = {};
7964 
7965 	devlink_trap_stats_update(trap_item->stats, skb->len);
7966 	devlink_trap_stats_update(trap_item->group_item->stats, skb->len);
7967 
7968 	devlink_trap_report_metadata_fill(&hw_metadata, trap_item,
7969 					  in_devlink_port);
7970 	net_dm_hw_report(skb, &hw_metadata);
7971 }
7972 EXPORT_SYMBOL_GPL(devlink_trap_report);
7973 
7974 /**
7975  * devlink_trap_ctx_priv - Trap context to driver private information.
7976  * @trap_ctx: Trap context.
7977  *
7978  * Return: Driver private information passed during registration.
7979  */
devlink_trap_ctx_priv(void * trap_ctx)7980 void *devlink_trap_ctx_priv(void *trap_ctx)
7981 {
7982 	struct devlink_trap_item *trap_item = trap_ctx;
7983 
7984 	return trap_item->priv;
7985 }
7986 EXPORT_SYMBOL_GPL(devlink_trap_ctx_priv);
7987 
__devlink_compat_running_version(struct devlink * devlink,char * buf,size_t len)7988 static void __devlink_compat_running_version(struct devlink *devlink,
7989 					     char *buf, size_t len)
7990 {
7991 	const struct nlattr *nlattr;
7992 	struct devlink_info_req req;
7993 	struct sk_buff *msg;
7994 	int rem, err;
7995 
7996 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7997 	if (!msg)
7998 		return;
7999 
8000 	req.msg = msg;
8001 	err = devlink->ops->info_get(devlink, &req, NULL);
8002 	if (err)
8003 		goto free_msg;
8004 
8005 	nla_for_each_attr(nlattr, (void *)msg->data, msg->len, rem) {
8006 		const struct nlattr *kv;
8007 		int rem_kv;
8008 
8009 		if (nla_type(nlattr) != DEVLINK_ATTR_INFO_VERSION_RUNNING)
8010 			continue;
8011 
8012 		nla_for_each_nested(kv, nlattr, rem_kv) {
8013 			if (nla_type(kv) != DEVLINK_ATTR_INFO_VERSION_VALUE)
8014 				continue;
8015 
8016 			strlcat(buf, nla_data(kv), len);
8017 			strlcat(buf, " ", len);
8018 		}
8019 	}
8020 free_msg:
8021 	nlmsg_free(msg);
8022 }
8023 
devlink_compat_running_version(struct net_device * dev,char * buf,size_t len)8024 void devlink_compat_running_version(struct net_device *dev,
8025 				    char *buf, size_t len)
8026 {
8027 	struct devlink *devlink;
8028 
8029 	dev_hold(dev);
8030 	rtnl_unlock();
8031 
8032 	devlink = netdev_to_devlink(dev);
8033 	if (!devlink || !devlink->ops->info_get)
8034 		goto out;
8035 
8036 	mutex_lock(&devlink->lock);
8037 	__devlink_compat_running_version(devlink, buf, len);
8038 	mutex_unlock(&devlink->lock);
8039 
8040 out:
8041 	rtnl_lock();
8042 	dev_put(dev);
8043 }
8044 
devlink_compat_flash_update(struct net_device * dev,const char * file_name)8045 int devlink_compat_flash_update(struct net_device *dev, const char *file_name)
8046 {
8047 	struct devlink *devlink;
8048 	int ret;
8049 
8050 	dev_hold(dev);
8051 	rtnl_unlock();
8052 
8053 	devlink = netdev_to_devlink(dev);
8054 	if (!devlink || !devlink->ops->flash_update) {
8055 		ret = -EOPNOTSUPP;
8056 		goto out;
8057 	}
8058 
8059 	mutex_lock(&devlink->lock);
8060 	ret = devlink->ops->flash_update(devlink, file_name, NULL, NULL);
8061 	mutex_unlock(&devlink->lock);
8062 
8063 out:
8064 	rtnl_lock();
8065 	dev_put(dev);
8066 
8067 	return ret;
8068 }
8069 
devlink_compat_phys_port_name_get(struct net_device * dev,char * name,size_t len)8070 int devlink_compat_phys_port_name_get(struct net_device *dev,
8071 				      char *name, size_t len)
8072 {
8073 	struct devlink_port *devlink_port;
8074 
8075 	/* RTNL mutex is held here which ensures that devlink_port
8076 	 * instance cannot disappear in the middle. No need to take
8077 	 * any devlink lock as only permanent values are accessed.
8078 	 */
8079 	ASSERT_RTNL();
8080 
8081 	devlink_port = netdev_to_devlink_port(dev);
8082 	if (!devlink_port)
8083 		return -EOPNOTSUPP;
8084 
8085 	return __devlink_port_phys_port_name_get(devlink_port, name, len);
8086 }
8087 
devlink_compat_switch_id_get(struct net_device * dev,struct netdev_phys_item_id * ppid)8088 int devlink_compat_switch_id_get(struct net_device *dev,
8089 				 struct netdev_phys_item_id *ppid)
8090 {
8091 	struct devlink_port *devlink_port;
8092 
8093 	/* Caller must hold RTNL mutex or reference to dev, which ensures that
8094 	 * devlink_port instance cannot disappear in the middle. No need to take
8095 	 * any devlink lock as only permanent values are accessed.
8096 	 */
8097 	devlink_port = netdev_to_devlink_port(dev);
8098 	if (!devlink_port || !devlink_port->attrs.switch_port)
8099 		return -EOPNOTSUPP;
8100 
8101 	memcpy(ppid, &devlink_port->attrs.switch_id, sizeof(*ppid));
8102 
8103 	return 0;
8104 }
8105 
devlink_init(void)8106 static int __init devlink_init(void)
8107 {
8108 	return genl_register_family(&devlink_nl_family);
8109 }
8110 
8111 subsys_initcall(devlink_init);
8112