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