1 /*
2  * net/core/devlink.c - Network physical/parent device Netlink interface
3  *
4  * Heavily inspired by net/wireless/
5  * Copyright (c) 2016 Mellanox Technologies. All rights reserved.
6  * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  */
13 
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/types.h>
17 #include <linux/slab.h>
18 #include <linux/gfp.h>
19 #include <linux/device.h>
20 #include <linux/list.h>
21 #include <linux/netdevice.h>
22 #include <rdma/ib_verbs.h>
23 #include <net/netlink.h>
24 #include <net/genetlink.h>
25 #include <net/rtnetlink.h>
26 #include <net/net_namespace.h>
27 #include <net/sock.h>
28 #include <net/devlink.h>
29 #define CREATE_TRACE_POINTS
30 #include <trace/events/devlink.h>
31 
32 static struct devlink_dpipe_field devlink_dpipe_fields_ethernet[] = {
33 	{
34 		.name = "destination mac",
35 		.id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC,
36 		.bitwidth = 48,
37 	},
38 };
39 
40 struct devlink_dpipe_header devlink_dpipe_header_ethernet = {
41 	.name = "ethernet",
42 	.id = DEVLINK_DPIPE_HEADER_ETHERNET,
43 	.fields = devlink_dpipe_fields_ethernet,
44 	.fields_count = ARRAY_SIZE(devlink_dpipe_fields_ethernet),
45 	.global = true,
46 };
47 EXPORT_SYMBOL(devlink_dpipe_header_ethernet);
48 
49 static struct devlink_dpipe_field devlink_dpipe_fields_ipv4[] = {
50 	{
51 		.name = "destination ip",
52 		.id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP,
53 		.bitwidth = 32,
54 	},
55 };
56 
57 struct devlink_dpipe_header devlink_dpipe_header_ipv4 = {
58 	.name = "ipv4",
59 	.id = DEVLINK_DPIPE_HEADER_IPV4,
60 	.fields = devlink_dpipe_fields_ipv4,
61 	.fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv4),
62 	.global = true,
63 };
64 EXPORT_SYMBOL(devlink_dpipe_header_ipv4);
65 
66 static struct devlink_dpipe_field devlink_dpipe_fields_ipv6[] = {
67 	{
68 		.name = "destination ip",
69 		.id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP,
70 		.bitwidth = 128,
71 	},
72 };
73 
74 struct devlink_dpipe_header devlink_dpipe_header_ipv6 = {
75 	.name = "ipv6",
76 	.id = DEVLINK_DPIPE_HEADER_IPV6,
77 	.fields = devlink_dpipe_fields_ipv6,
78 	.fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv6),
79 	.global = true,
80 };
81 EXPORT_SYMBOL(devlink_dpipe_header_ipv6);
82 
83 EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg);
84 
85 static LIST_HEAD(devlink_list);
86 
87 /* devlink_mutex
88  *
89  * An overall lock guarding every operation coming from userspace.
90  * It also guards devlink devices list and it is taken when
91  * driver registers/unregisters it.
92  */
93 static DEFINE_MUTEX(devlink_mutex);
94 
devlink_net(const struct devlink * devlink)95 static struct net *devlink_net(const struct devlink *devlink)
96 {
97 	return read_pnet(&devlink->_net);
98 }
99 
devlink_net_set(struct devlink * devlink,struct net * net)100 static void devlink_net_set(struct devlink *devlink, struct net *net)
101 {
102 	write_pnet(&devlink->_net, net);
103 }
104 
devlink_get_from_attrs(struct net * net,struct nlattr ** attrs)105 static struct devlink *devlink_get_from_attrs(struct net *net,
106 					      struct nlattr **attrs)
107 {
108 	struct devlink *devlink;
109 	char *busname;
110 	char *devname;
111 
112 	if (!attrs[DEVLINK_ATTR_BUS_NAME] || !attrs[DEVLINK_ATTR_DEV_NAME])
113 		return ERR_PTR(-EINVAL);
114 
115 	busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]);
116 	devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
117 
118 	list_for_each_entry(devlink, &devlink_list, list) {
119 		if (strcmp(devlink->dev->bus->name, busname) == 0 &&
120 		    strcmp(dev_name(devlink->dev), devname) == 0 &&
121 		    net_eq(devlink_net(devlink), net))
122 			return devlink;
123 	}
124 
125 	return ERR_PTR(-ENODEV);
126 }
127 
devlink_get_from_info(struct genl_info * info)128 static struct devlink *devlink_get_from_info(struct genl_info *info)
129 {
130 	return devlink_get_from_attrs(genl_info_net(info), info->attrs);
131 }
132 
devlink_port_get_by_index(struct devlink * devlink,int port_index)133 static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink,
134 						      int port_index)
135 {
136 	struct devlink_port *devlink_port;
137 
138 	list_for_each_entry(devlink_port, &devlink->port_list, list) {
139 		if (devlink_port->index == port_index)
140 			return devlink_port;
141 	}
142 	return NULL;
143 }
144 
devlink_port_index_exists(struct devlink * devlink,int port_index)145 static bool devlink_port_index_exists(struct devlink *devlink, int port_index)
146 {
147 	return devlink_port_get_by_index(devlink, port_index);
148 }
149 
devlink_port_get_from_attrs(struct devlink * devlink,struct nlattr ** attrs)150 static struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink,
151 							struct nlattr **attrs)
152 {
153 	if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
154 		u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
155 		struct devlink_port *devlink_port;
156 
157 		devlink_port = devlink_port_get_by_index(devlink, port_index);
158 		if (!devlink_port)
159 			return ERR_PTR(-ENODEV);
160 		return devlink_port;
161 	}
162 	return ERR_PTR(-EINVAL);
163 }
164 
devlink_port_get_from_info(struct devlink * devlink,struct genl_info * info)165 static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink,
166 						       struct genl_info *info)
167 {
168 	return devlink_port_get_from_attrs(devlink, info->attrs);
169 }
170 
171 struct devlink_sb {
172 	struct list_head list;
173 	unsigned int index;
174 	u32 size;
175 	u16 ingress_pools_count;
176 	u16 egress_pools_count;
177 	u16 ingress_tc_count;
178 	u16 egress_tc_count;
179 };
180 
devlink_sb_pool_count(struct devlink_sb * devlink_sb)181 static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb)
182 {
183 	return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count;
184 }
185 
devlink_sb_get_by_index(struct devlink * devlink,unsigned int sb_index)186 static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink,
187 						  unsigned int sb_index)
188 {
189 	struct devlink_sb *devlink_sb;
190 
191 	list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
192 		if (devlink_sb->index == sb_index)
193 			return devlink_sb;
194 	}
195 	return NULL;
196 }
197 
devlink_sb_index_exists(struct devlink * devlink,unsigned int sb_index)198 static bool devlink_sb_index_exists(struct devlink *devlink,
199 				    unsigned int sb_index)
200 {
201 	return devlink_sb_get_by_index(devlink, sb_index);
202 }
203 
devlink_sb_get_from_attrs(struct devlink * devlink,struct nlattr ** attrs)204 static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink,
205 						    struct nlattr **attrs)
206 {
207 	if (attrs[DEVLINK_ATTR_SB_INDEX]) {
208 		u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]);
209 		struct devlink_sb *devlink_sb;
210 
211 		devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
212 		if (!devlink_sb)
213 			return ERR_PTR(-ENODEV);
214 		return devlink_sb;
215 	}
216 	return ERR_PTR(-EINVAL);
217 }
218 
devlink_sb_get_from_info(struct devlink * devlink,struct genl_info * info)219 static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink,
220 						   struct genl_info *info)
221 {
222 	return devlink_sb_get_from_attrs(devlink, info->attrs);
223 }
224 
devlink_sb_pool_index_get_from_attrs(struct devlink_sb * devlink_sb,struct nlattr ** attrs,u16 * p_pool_index)225 static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb,
226 						struct nlattr **attrs,
227 						u16 *p_pool_index)
228 {
229 	u16 val;
230 
231 	if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX])
232 		return -EINVAL;
233 
234 	val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]);
235 	if (val >= devlink_sb_pool_count(devlink_sb))
236 		return -EINVAL;
237 	*p_pool_index = val;
238 	return 0;
239 }
240 
devlink_sb_pool_index_get_from_info(struct devlink_sb * devlink_sb,struct genl_info * info,u16 * p_pool_index)241 static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb,
242 					       struct genl_info *info,
243 					       u16 *p_pool_index)
244 {
245 	return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs,
246 						    p_pool_index);
247 }
248 
249 static int
devlink_sb_pool_type_get_from_attrs(struct nlattr ** attrs,enum devlink_sb_pool_type * p_pool_type)250 devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs,
251 				    enum devlink_sb_pool_type *p_pool_type)
252 {
253 	u8 val;
254 
255 	if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE])
256 		return -EINVAL;
257 
258 	val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]);
259 	if (val != DEVLINK_SB_POOL_TYPE_INGRESS &&
260 	    val != DEVLINK_SB_POOL_TYPE_EGRESS)
261 		return -EINVAL;
262 	*p_pool_type = val;
263 	return 0;
264 }
265 
266 static int
devlink_sb_pool_type_get_from_info(struct genl_info * info,enum devlink_sb_pool_type * p_pool_type)267 devlink_sb_pool_type_get_from_info(struct genl_info *info,
268 				   enum devlink_sb_pool_type *p_pool_type)
269 {
270 	return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type);
271 }
272 
273 static int
devlink_sb_th_type_get_from_attrs(struct nlattr ** attrs,enum devlink_sb_threshold_type * p_th_type)274 devlink_sb_th_type_get_from_attrs(struct nlattr **attrs,
275 				  enum devlink_sb_threshold_type *p_th_type)
276 {
277 	u8 val;
278 
279 	if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE])
280 		return -EINVAL;
281 
282 	val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]);
283 	if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC &&
284 	    val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC)
285 		return -EINVAL;
286 	*p_th_type = val;
287 	return 0;
288 }
289 
290 static int
devlink_sb_th_type_get_from_info(struct genl_info * info,enum devlink_sb_threshold_type * p_th_type)291 devlink_sb_th_type_get_from_info(struct genl_info *info,
292 				 enum devlink_sb_threshold_type *p_th_type)
293 {
294 	return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type);
295 }
296 
297 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)298 devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb,
299 				   struct nlattr **attrs,
300 				   enum devlink_sb_pool_type pool_type,
301 				   u16 *p_tc_index)
302 {
303 	u16 val;
304 
305 	if (!attrs[DEVLINK_ATTR_SB_TC_INDEX])
306 		return -EINVAL;
307 
308 	val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]);
309 	if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS &&
310 	    val >= devlink_sb->ingress_tc_count)
311 		return -EINVAL;
312 	if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS &&
313 	    val >= devlink_sb->egress_tc_count)
314 		return -EINVAL;
315 	*p_tc_index = val;
316 	return 0;
317 }
318 
319 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)320 devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb,
321 				  struct genl_info *info,
322 				  enum devlink_sb_pool_type pool_type,
323 				  u16 *p_tc_index)
324 {
325 	return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs,
326 						  pool_type, p_tc_index);
327 }
328 
329 struct devlink_region {
330 	struct devlink *devlink;
331 	struct list_head list;
332 	const char *name;
333 	struct list_head snapshot_list;
334 	u32 max_snapshots;
335 	u32 cur_snapshots;
336 	u64 size;
337 };
338 
339 struct devlink_snapshot {
340 	struct list_head list;
341 	struct devlink_region *region;
342 	devlink_snapshot_data_dest_t *data_destructor;
343 	u64 data_len;
344 	u8 *data;
345 	u32 id;
346 };
347 
348 static struct devlink_region *
devlink_region_get_by_name(struct devlink * devlink,const char * region_name)349 devlink_region_get_by_name(struct devlink *devlink, const char *region_name)
350 {
351 	struct devlink_region *region;
352 
353 	list_for_each_entry(region, &devlink->region_list, list)
354 		if (!strcmp(region->name, region_name))
355 			return region;
356 
357 	return NULL;
358 }
359 
360 static struct devlink_snapshot *
devlink_region_snapshot_get_by_id(struct devlink_region * region,u32 id)361 devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id)
362 {
363 	struct devlink_snapshot *snapshot;
364 
365 	list_for_each_entry(snapshot, &region->snapshot_list, list)
366 		if (snapshot->id == id)
367 			return snapshot;
368 
369 	return NULL;
370 }
371 
devlink_region_snapshot_del(struct devlink_snapshot * snapshot)372 static void devlink_region_snapshot_del(struct devlink_snapshot *snapshot)
373 {
374 	snapshot->region->cur_snapshots--;
375 	list_del(&snapshot->list);
376 	(*snapshot->data_destructor)(snapshot->data);
377 	kfree(snapshot);
378 }
379 
380 #define DEVLINK_NL_FLAG_NEED_DEVLINK	BIT(0)
381 #define DEVLINK_NL_FLAG_NEED_PORT	BIT(1)
382 #define DEVLINK_NL_FLAG_NEED_SB		BIT(2)
383 
384 /* The per devlink instance lock is taken by default in the pre-doit
385  * operation, yet several commands do not require this. The global
386  * devlink lock is taken and protects from disruption by user-calls.
387  */
388 #define DEVLINK_NL_FLAG_NO_LOCK		BIT(3)
389 
devlink_nl_pre_doit(const struct genl_ops * ops,struct sk_buff * skb,struct genl_info * info)390 static int devlink_nl_pre_doit(const struct genl_ops *ops,
391 			       struct sk_buff *skb, struct genl_info *info)
392 {
393 	struct devlink *devlink;
394 	int err;
395 
396 	mutex_lock(&devlink_mutex);
397 	devlink = devlink_get_from_info(info);
398 	if (IS_ERR(devlink)) {
399 		mutex_unlock(&devlink_mutex);
400 		return PTR_ERR(devlink);
401 	}
402 	if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
403 		mutex_lock(&devlink->lock);
404 	if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) {
405 		info->user_ptr[0] = devlink;
406 	} else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) {
407 		struct devlink_port *devlink_port;
408 
409 		devlink_port = devlink_port_get_from_info(devlink, info);
410 		if (IS_ERR(devlink_port)) {
411 			err = PTR_ERR(devlink_port);
412 			goto unlock;
413 		}
414 		info->user_ptr[0] = devlink_port;
415 	}
416 	if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) {
417 		struct devlink_sb *devlink_sb;
418 
419 		devlink_sb = devlink_sb_get_from_info(devlink, info);
420 		if (IS_ERR(devlink_sb)) {
421 			err = PTR_ERR(devlink_sb);
422 			goto unlock;
423 		}
424 		info->user_ptr[1] = devlink_sb;
425 	}
426 	return 0;
427 
428 unlock:
429 	if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
430 		mutex_unlock(&devlink->lock);
431 	mutex_unlock(&devlink_mutex);
432 	return err;
433 }
434 
devlink_nl_post_doit(const struct genl_ops * ops,struct sk_buff * skb,struct genl_info * info)435 static void devlink_nl_post_doit(const struct genl_ops *ops,
436 				 struct sk_buff *skb, struct genl_info *info)
437 {
438 	struct devlink *devlink;
439 
440 	devlink = devlink_get_from_info(info);
441 	if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
442 		mutex_unlock(&devlink->lock);
443 	mutex_unlock(&devlink_mutex);
444 }
445 
446 static struct genl_family devlink_nl_family;
447 
448 enum devlink_multicast_groups {
449 	DEVLINK_MCGRP_CONFIG,
450 };
451 
452 static const struct genl_multicast_group devlink_nl_mcgrps[] = {
453 	[DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME },
454 };
455 
devlink_nl_put_handle(struct sk_buff * msg,struct devlink * devlink)456 static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
457 {
458 	if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
459 		return -EMSGSIZE;
460 	if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
461 		return -EMSGSIZE;
462 	return 0;
463 }
464 
devlink_nl_fill(struct sk_buff * msg,struct devlink * devlink,enum devlink_command cmd,u32 portid,u32 seq,int flags)465 static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
466 			   enum devlink_command cmd, u32 portid,
467 			   u32 seq, int flags)
468 {
469 	void *hdr;
470 
471 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
472 	if (!hdr)
473 		return -EMSGSIZE;
474 
475 	if (devlink_nl_put_handle(msg, devlink))
476 		goto nla_put_failure;
477 
478 	genlmsg_end(msg, hdr);
479 	return 0;
480 
481 nla_put_failure:
482 	genlmsg_cancel(msg, hdr);
483 	return -EMSGSIZE;
484 }
485 
devlink_notify(struct devlink * devlink,enum devlink_command cmd)486 static void devlink_notify(struct devlink *devlink, enum devlink_command cmd)
487 {
488 	struct sk_buff *msg;
489 	int err;
490 
491 	WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL);
492 
493 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
494 	if (!msg)
495 		return;
496 
497 	err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0);
498 	if (err) {
499 		nlmsg_free(msg);
500 		return;
501 	}
502 
503 	genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
504 				msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
505 }
506 
devlink_nl_port_attrs_put(struct sk_buff * msg,struct devlink_port * devlink_port)507 static int devlink_nl_port_attrs_put(struct sk_buff *msg,
508 				     struct devlink_port *devlink_port)
509 {
510 	struct devlink_port_attrs *attrs = &devlink_port->attrs;
511 
512 	if (!attrs->set)
513 		return 0;
514 	if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour))
515 		return -EMSGSIZE;
516 	if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER, attrs->port_number))
517 		return -EMSGSIZE;
518 	if (!attrs->split)
519 		return 0;
520 	if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP, attrs->port_number))
521 		return -EMSGSIZE;
522 	if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER,
523 			attrs->split_subport_number))
524 		return -EMSGSIZE;
525 	return 0;
526 }
527 
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)528 static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
529 				struct devlink_port *devlink_port,
530 				enum devlink_command cmd, u32 portid,
531 				u32 seq, int flags)
532 {
533 	void *hdr;
534 
535 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
536 	if (!hdr)
537 		return -EMSGSIZE;
538 
539 	if (devlink_nl_put_handle(msg, devlink))
540 		goto nla_put_failure;
541 	if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
542 		goto nla_put_failure;
543 	if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type))
544 		goto nla_put_failure;
545 	if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET &&
546 	    nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE,
547 			devlink_port->desired_type))
548 		goto nla_put_failure;
549 	if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) {
550 		struct net_device *netdev = devlink_port->type_dev;
551 
552 		if (netdev &&
553 		    (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX,
554 				 netdev->ifindex) ||
555 		     nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME,
556 				    netdev->name)))
557 			goto nla_put_failure;
558 	}
559 	if (devlink_port->type == DEVLINK_PORT_TYPE_IB) {
560 		struct ib_device *ibdev = devlink_port->type_dev;
561 
562 		if (ibdev &&
563 		    nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME,
564 				   ibdev->name))
565 			goto nla_put_failure;
566 	}
567 	if (devlink_nl_port_attrs_put(msg, devlink_port))
568 		goto nla_put_failure;
569 
570 	genlmsg_end(msg, hdr);
571 	return 0;
572 
573 nla_put_failure:
574 	genlmsg_cancel(msg, hdr);
575 	return -EMSGSIZE;
576 }
577 
devlink_port_notify(struct devlink_port * devlink_port,enum devlink_command cmd)578 static void devlink_port_notify(struct devlink_port *devlink_port,
579 				enum devlink_command cmd)
580 {
581 	struct devlink *devlink = devlink_port->devlink;
582 	struct sk_buff *msg;
583 	int err;
584 
585 	if (!devlink_port->registered)
586 		return;
587 
588 	WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL);
589 
590 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
591 	if (!msg)
592 		return;
593 
594 	err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0);
595 	if (err) {
596 		nlmsg_free(msg);
597 		return;
598 	}
599 
600 	genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
601 				msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
602 }
603 
devlink_nl_cmd_get_doit(struct sk_buff * skb,struct genl_info * info)604 static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info)
605 {
606 	struct devlink *devlink = info->user_ptr[0];
607 	struct sk_buff *msg;
608 	int err;
609 
610 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
611 	if (!msg)
612 		return -ENOMEM;
613 
614 	err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
615 			      info->snd_portid, info->snd_seq, 0);
616 	if (err) {
617 		nlmsg_free(msg);
618 		return err;
619 	}
620 
621 	return genlmsg_reply(msg, info);
622 }
623 
devlink_nl_cmd_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)624 static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg,
625 				     struct netlink_callback *cb)
626 {
627 	struct devlink *devlink;
628 	int start = cb->args[0];
629 	int idx = 0;
630 	int err;
631 
632 	mutex_lock(&devlink_mutex);
633 	list_for_each_entry(devlink, &devlink_list, list) {
634 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
635 			continue;
636 		if (idx < start) {
637 			idx++;
638 			continue;
639 		}
640 		err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
641 				      NETLINK_CB(cb->skb).portid,
642 				      cb->nlh->nlmsg_seq, NLM_F_MULTI);
643 		if (err)
644 			goto out;
645 		idx++;
646 	}
647 out:
648 	mutex_unlock(&devlink_mutex);
649 
650 	cb->args[0] = idx;
651 	return msg->len;
652 }
653 
devlink_nl_cmd_port_get_doit(struct sk_buff * skb,struct genl_info * info)654 static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb,
655 					struct genl_info *info)
656 {
657 	struct devlink_port *devlink_port = info->user_ptr[0];
658 	struct devlink *devlink = devlink_port->devlink;
659 	struct sk_buff *msg;
660 	int err;
661 
662 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
663 	if (!msg)
664 		return -ENOMEM;
665 
666 	err = devlink_nl_port_fill(msg, devlink, devlink_port,
667 				   DEVLINK_CMD_PORT_NEW,
668 				   info->snd_portid, info->snd_seq, 0);
669 	if (err) {
670 		nlmsg_free(msg);
671 		return err;
672 	}
673 
674 	return genlmsg_reply(msg, info);
675 }
676 
devlink_nl_cmd_port_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)677 static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg,
678 					  struct netlink_callback *cb)
679 {
680 	struct devlink *devlink;
681 	struct devlink_port *devlink_port;
682 	int start = cb->args[0];
683 	int idx = 0;
684 	int err;
685 
686 	mutex_lock(&devlink_mutex);
687 	list_for_each_entry(devlink, &devlink_list, list) {
688 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
689 			continue;
690 		mutex_lock(&devlink->lock);
691 		list_for_each_entry(devlink_port, &devlink->port_list, list) {
692 			if (idx < start) {
693 				idx++;
694 				continue;
695 			}
696 			err = devlink_nl_port_fill(msg, devlink, devlink_port,
697 						   DEVLINK_CMD_NEW,
698 						   NETLINK_CB(cb->skb).portid,
699 						   cb->nlh->nlmsg_seq,
700 						   NLM_F_MULTI);
701 			if (err) {
702 				mutex_unlock(&devlink->lock);
703 				goto out;
704 			}
705 			idx++;
706 		}
707 		mutex_unlock(&devlink->lock);
708 	}
709 out:
710 	mutex_unlock(&devlink_mutex);
711 
712 	cb->args[0] = idx;
713 	return msg->len;
714 }
715 
devlink_port_type_set(struct devlink * devlink,struct devlink_port * devlink_port,enum devlink_port_type port_type)716 static int devlink_port_type_set(struct devlink *devlink,
717 				 struct devlink_port *devlink_port,
718 				 enum devlink_port_type port_type)
719 
720 {
721 	int err;
722 
723 	if (devlink->ops && devlink->ops->port_type_set) {
724 		if (port_type == DEVLINK_PORT_TYPE_NOTSET)
725 			return -EINVAL;
726 		if (port_type == devlink_port->type)
727 			return 0;
728 		err = devlink->ops->port_type_set(devlink_port, port_type);
729 		if (err)
730 			return err;
731 		devlink_port->desired_type = port_type;
732 		devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
733 		return 0;
734 	}
735 	return -EOPNOTSUPP;
736 }
737 
devlink_nl_cmd_port_set_doit(struct sk_buff * skb,struct genl_info * info)738 static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb,
739 					struct genl_info *info)
740 {
741 	struct devlink_port *devlink_port = info->user_ptr[0];
742 	struct devlink *devlink = devlink_port->devlink;
743 	int err;
744 
745 	if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) {
746 		enum devlink_port_type port_type;
747 
748 		port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]);
749 		err = devlink_port_type_set(devlink, devlink_port, port_type);
750 		if (err)
751 			return err;
752 	}
753 	return 0;
754 }
755 
devlink_port_split(struct devlink * devlink,u32 port_index,u32 count,struct netlink_ext_ack * extack)756 static int devlink_port_split(struct devlink *devlink, u32 port_index,
757 			      u32 count, struct netlink_ext_ack *extack)
758 
759 {
760 	if (devlink->ops && devlink->ops->port_split)
761 		return devlink->ops->port_split(devlink, port_index, count,
762 						extack);
763 	return -EOPNOTSUPP;
764 }
765 
devlink_nl_cmd_port_split_doit(struct sk_buff * skb,struct genl_info * info)766 static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb,
767 					  struct genl_info *info)
768 {
769 	struct devlink *devlink = info->user_ptr[0];
770 	u32 port_index;
771 	u32 count;
772 
773 	if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] ||
774 	    !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT])
775 		return -EINVAL;
776 
777 	port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
778 	count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]);
779 	return devlink_port_split(devlink, port_index, count, info->extack);
780 }
781 
devlink_port_unsplit(struct devlink * devlink,u32 port_index,struct netlink_ext_ack * extack)782 static int devlink_port_unsplit(struct devlink *devlink, u32 port_index,
783 				struct netlink_ext_ack *extack)
784 
785 {
786 	if (devlink->ops && devlink->ops->port_unsplit)
787 		return devlink->ops->port_unsplit(devlink, port_index, extack);
788 	return -EOPNOTSUPP;
789 }
790 
devlink_nl_cmd_port_unsplit_doit(struct sk_buff * skb,struct genl_info * info)791 static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb,
792 					    struct genl_info *info)
793 {
794 	struct devlink *devlink = info->user_ptr[0];
795 	u32 port_index;
796 
797 	if (!info->attrs[DEVLINK_ATTR_PORT_INDEX])
798 		return -EINVAL;
799 
800 	port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
801 	return devlink_port_unsplit(devlink, port_index, info->extack);
802 }
803 
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)804 static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink,
805 			      struct devlink_sb *devlink_sb,
806 			      enum devlink_command cmd, u32 portid,
807 			      u32 seq, int flags)
808 {
809 	void *hdr;
810 
811 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
812 	if (!hdr)
813 		return -EMSGSIZE;
814 
815 	if (devlink_nl_put_handle(msg, devlink))
816 		goto nla_put_failure;
817 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
818 		goto nla_put_failure;
819 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size))
820 		goto nla_put_failure;
821 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT,
822 			devlink_sb->ingress_pools_count))
823 		goto nla_put_failure;
824 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT,
825 			devlink_sb->egress_pools_count))
826 		goto nla_put_failure;
827 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT,
828 			devlink_sb->ingress_tc_count))
829 		goto nla_put_failure;
830 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT,
831 			devlink_sb->egress_tc_count))
832 		goto nla_put_failure;
833 
834 	genlmsg_end(msg, hdr);
835 	return 0;
836 
837 nla_put_failure:
838 	genlmsg_cancel(msg, hdr);
839 	return -EMSGSIZE;
840 }
841 
devlink_nl_cmd_sb_get_doit(struct sk_buff * skb,struct genl_info * info)842 static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb,
843 				      struct genl_info *info)
844 {
845 	struct devlink *devlink = info->user_ptr[0];
846 	struct devlink_sb *devlink_sb = info->user_ptr[1];
847 	struct sk_buff *msg;
848 	int err;
849 
850 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
851 	if (!msg)
852 		return -ENOMEM;
853 
854 	err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
855 				 DEVLINK_CMD_SB_NEW,
856 				 info->snd_portid, info->snd_seq, 0);
857 	if (err) {
858 		nlmsg_free(msg);
859 		return err;
860 	}
861 
862 	return genlmsg_reply(msg, info);
863 }
864 
devlink_nl_cmd_sb_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)865 static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg,
866 					struct netlink_callback *cb)
867 {
868 	struct devlink *devlink;
869 	struct devlink_sb *devlink_sb;
870 	int start = cb->args[0];
871 	int idx = 0;
872 	int err;
873 
874 	mutex_lock(&devlink_mutex);
875 	list_for_each_entry(devlink, &devlink_list, list) {
876 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
877 			continue;
878 		mutex_lock(&devlink->lock);
879 		list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
880 			if (idx < start) {
881 				idx++;
882 				continue;
883 			}
884 			err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
885 						 DEVLINK_CMD_SB_NEW,
886 						 NETLINK_CB(cb->skb).portid,
887 						 cb->nlh->nlmsg_seq,
888 						 NLM_F_MULTI);
889 			if (err) {
890 				mutex_unlock(&devlink->lock);
891 				goto out;
892 			}
893 			idx++;
894 		}
895 		mutex_unlock(&devlink->lock);
896 	}
897 out:
898 	mutex_unlock(&devlink_mutex);
899 
900 	cb->args[0] = idx;
901 	return msg->len;
902 }
903 
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)904 static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink,
905 				   struct devlink_sb *devlink_sb,
906 				   u16 pool_index, enum devlink_command cmd,
907 				   u32 portid, u32 seq, int flags)
908 {
909 	struct devlink_sb_pool_info pool_info;
910 	void *hdr;
911 	int err;
912 
913 	err = devlink->ops->sb_pool_get(devlink, devlink_sb->index,
914 					pool_index, &pool_info);
915 	if (err)
916 		return err;
917 
918 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
919 	if (!hdr)
920 		return -EMSGSIZE;
921 
922 	if (devlink_nl_put_handle(msg, devlink))
923 		goto nla_put_failure;
924 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
925 		goto nla_put_failure;
926 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
927 		goto nla_put_failure;
928 	if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type))
929 		goto nla_put_failure;
930 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size))
931 		goto nla_put_failure;
932 	if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE,
933 		       pool_info.threshold_type))
934 		goto nla_put_failure;
935 
936 	genlmsg_end(msg, hdr);
937 	return 0;
938 
939 nla_put_failure:
940 	genlmsg_cancel(msg, hdr);
941 	return -EMSGSIZE;
942 }
943 
devlink_nl_cmd_sb_pool_get_doit(struct sk_buff * skb,struct genl_info * info)944 static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb,
945 					   struct genl_info *info)
946 {
947 	struct devlink *devlink = info->user_ptr[0];
948 	struct devlink_sb *devlink_sb = info->user_ptr[1];
949 	struct sk_buff *msg;
950 	u16 pool_index;
951 	int err;
952 
953 	err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
954 						  &pool_index);
955 	if (err)
956 		return err;
957 
958 	if (!devlink->ops || !devlink->ops->sb_pool_get)
959 		return -EOPNOTSUPP;
960 
961 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
962 	if (!msg)
963 		return -ENOMEM;
964 
965 	err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index,
966 				      DEVLINK_CMD_SB_POOL_NEW,
967 				      info->snd_portid, info->snd_seq, 0);
968 	if (err) {
969 		nlmsg_free(msg);
970 		return err;
971 	}
972 
973 	return genlmsg_reply(msg, info);
974 }
975 
__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)976 static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
977 				struct devlink *devlink,
978 				struct devlink_sb *devlink_sb,
979 				u32 portid, u32 seq)
980 {
981 	u16 pool_count = devlink_sb_pool_count(devlink_sb);
982 	u16 pool_index;
983 	int err;
984 
985 	for (pool_index = 0; pool_index < pool_count; pool_index++) {
986 		if (*p_idx < start) {
987 			(*p_idx)++;
988 			continue;
989 		}
990 		err = devlink_nl_sb_pool_fill(msg, devlink,
991 					      devlink_sb,
992 					      pool_index,
993 					      DEVLINK_CMD_SB_POOL_NEW,
994 					      portid, seq, NLM_F_MULTI);
995 		if (err)
996 			return err;
997 		(*p_idx)++;
998 	}
999 	return 0;
1000 }
1001 
devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)1002 static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg,
1003 					     struct netlink_callback *cb)
1004 {
1005 	struct devlink *devlink;
1006 	struct devlink_sb *devlink_sb;
1007 	int start = cb->args[0];
1008 	int idx = 0;
1009 	int err;
1010 
1011 	mutex_lock(&devlink_mutex);
1012 	list_for_each_entry(devlink, &devlink_list, list) {
1013 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1014 		    !devlink->ops || !devlink->ops->sb_pool_get)
1015 			continue;
1016 		mutex_lock(&devlink->lock);
1017 		list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1018 			err = __sb_pool_get_dumpit(msg, start, &idx, devlink,
1019 						   devlink_sb,
1020 						   NETLINK_CB(cb->skb).portid,
1021 						   cb->nlh->nlmsg_seq);
1022 			if (err && err != -EOPNOTSUPP) {
1023 				mutex_unlock(&devlink->lock);
1024 				goto out;
1025 			}
1026 		}
1027 		mutex_unlock(&devlink->lock);
1028 	}
1029 out:
1030 	mutex_unlock(&devlink_mutex);
1031 
1032 	cb->args[0] = idx;
1033 	return msg->len;
1034 }
1035 
devlink_sb_pool_set(struct devlink * devlink,unsigned int sb_index,u16 pool_index,u32 size,enum devlink_sb_threshold_type threshold_type)1036 static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index,
1037 			       u16 pool_index, u32 size,
1038 			       enum devlink_sb_threshold_type threshold_type)
1039 
1040 {
1041 	const struct devlink_ops *ops = devlink->ops;
1042 
1043 	if (ops && ops->sb_pool_set)
1044 		return ops->sb_pool_set(devlink, sb_index, pool_index,
1045 					size, threshold_type);
1046 	return -EOPNOTSUPP;
1047 }
1048 
devlink_nl_cmd_sb_pool_set_doit(struct sk_buff * skb,struct genl_info * info)1049 static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb,
1050 					   struct genl_info *info)
1051 {
1052 	struct devlink *devlink = info->user_ptr[0];
1053 	struct devlink_sb *devlink_sb = info->user_ptr[1];
1054 	enum devlink_sb_threshold_type threshold_type;
1055 	u16 pool_index;
1056 	u32 size;
1057 	int err;
1058 
1059 	err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1060 						  &pool_index);
1061 	if (err)
1062 		return err;
1063 
1064 	err = devlink_sb_th_type_get_from_info(info, &threshold_type);
1065 	if (err)
1066 		return err;
1067 
1068 	if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE])
1069 		return -EINVAL;
1070 
1071 	size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]);
1072 	return devlink_sb_pool_set(devlink, devlink_sb->index,
1073 				   pool_index, size, threshold_type);
1074 }
1075 
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)1076 static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
1077 					struct devlink *devlink,
1078 					struct devlink_port *devlink_port,
1079 					struct devlink_sb *devlink_sb,
1080 					u16 pool_index,
1081 					enum devlink_command cmd,
1082 					u32 portid, u32 seq, int flags)
1083 {
1084 	const struct devlink_ops *ops = devlink->ops;
1085 	u32 threshold;
1086 	void *hdr;
1087 	int err;
1088 
1089 	err = ops->sb_port_pool_get(devlink_port, devlink_sb->index,
1090 				    pool_index, &threshold);
1091 	if (err)
1092 		return err;
1093 
1094 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1095 	if (!hdr)
1096 		return -EMSGSIZE;
1097 
1098 	if (devlink_nl_put_handle(msg, devlink))
1099 		goto nla_put_failure;
1100 	if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1101 		goto nla_put_failure;
1102 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1103 		goto nla_put_failure;
1104 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
1105 		goto nla_put_failure;
1106 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1107 		goto nla_put_failure;
1108 
1109 	if (ops->sb_occ_port_pool_get) {
1110 		u32 cur;
1111 		u32 max;
1112 
1113 		err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index,
1114 						pool_index, &cur, &max);
1115 		if (err && err != -EOPNOTSUPP)
1116 			return err;
1117 		if (!err) {
1118 			if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
1119 				goto nla_put_failure;
1120 			if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
1121 				goto nla_put_failure;
1122 		}
1123 	}
1124 
1125 	genlmsg_end(msg, hdr);
1126 	return 0;
1127 
1128 nla_put_failure:
1129 	genlmsg_cancel(msg, hdr);
1130 	return -EMSGSIZE;
1131 }
1132 
devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff * skb,struct genl_info * info)1133 static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb,
1134 						struct genl_info *info)
1135 {
1136 	struct devlink_port *devlink_port = info->user_ptr[0];
1137 	struct devlink *devlink = devlink_port->devlink;
1138 	struct devlink_sb *devlink_sb = info->user_ptr[1];
1139 	struct sk_buff *msg;
1140 	u16 pool_index;
1141 	int err;
1142 
1143 	err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1144 						  &pool_index);
1145 	if (err)
1146 		return err;
1147 
1148 	if (!devlink->ops || !devlink->ops->sb_port_pool_get)
1149 		return -EOPNOTSUPP;
1150 
1151 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1152 	if (!msg)
1153 		return -ENOMEM;
1154 
1155 	err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port,
1156 					   devlink_sb, pool_index,
1157 					   DEVLINK_CMD_SB_PORT_POOL_NEW,
1158 					   info->snd_portid, info->snd_seq, 0);
1159 	if (err) {
1160 		nlmsg_free(msg);
1161 		return err;
1162 	}
1163 
1164 	return genlmsg_reply(msg, info);
1165 }
1166 
__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)1167 static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
1168 				     struct devlink *devlink,
1169 				     struct devlink_sb *devlink_sb,
1170 				     u32 portid, u32 seq)
1171 {
1172 	struct devlink_port *devlink_port;
1173 	u16 pool_count = devlink_sb_pool_count(devlink_sb);
1174 	u16 pool_index;
1175 	int err;
1176 
1177 	list_for_each_entry(devlink_port, &devlink->port_list, list) {
1178 		for (pool_index = 0; pool_index < pool_count; pool_index++) {
1179 			if (*p_idx < start) {
1180 				(*p_idx)++;
1181 				continue;
1182 			}
1183 			err = devlink_nl_sb_port_pool_fill(msg, devlink,
1184 							   devlink_port,
1185 							   devlink_sb,
1186 							   pool_index,
1187 							   DEVLINK_CMD_SB_PORT_POOL_NEW,
1188 							   portid, seq,
1189 							   NLM_F_MULTI);
1190 			if (err)
1191 				return err;
1192 			(*p_idx)++;
1193 		}
1194 	}
1195 	return 0;
1196 }
1197 
devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)1198 static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg,
1199 						  struct netlink_callback *cb)
1200 {
1201 	struct devlink *devlink;
1202 	struct devlink_sb *devlink_sb;
1203 	int start = cb->args[0];
1204 	int idx = 0;
1205 	int err;
1206 
1207 	mutex_lock(&devlink_mutex);
1208 	list_for_each_entry(devlink, &devlink_list, list) {
1209 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1210 		    !devlink->ops || !devlink->ops->sb_port_pool_get)
1211 			continue;
1212 		mutex_lock(&devlink->lock);
1213 		list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1214 			err = __sb_port_pool_get_dumpit(msg, start, &idx,
1215 							devlink, devlink_sb,
1216 							NETLINK_CB(cb->skb).portid,
1217 							cb->nlh->nlmsg_seq);
1218 			if (err && err != -EOPNOTSUPP) {
1219 				mutex_unlock(&devlink->lock);
1220 				goto out;
1221 			}
1222 		}
1223 		mutex_unlock(&devlink->lock);
1224 	}
1225 out:
1226 	mutex_unlock(&devlink_mutex);
1227 
1228 	cb->args[0] = idx;
1229 	return msg->len;
1230 }
1231 
devlink_sb_port_pool_set(struct devlink_port * devlink_port,unsigned int sb_index,u16 pool_index,u32 threshold)1232 static int devlink_sb_port_pool_set(struct devlink_port *devlink_port,
1233 				    unsigned int sb_index, u16 pool_index,
1234 				    u32 threshold)
1235 
1236 {
1237 	const struct devlink_ops *ops = devlink_port->devlink->ops;
1238 
1239 	if (ops && ops->sb_port_pool_set)
1240 		return ops->sb_port_pool_set(devlink_port, sb_index,
1241 					     pool_index, threshold);
1242 	return -EOPNOTSUPP;
1243 }
1244 
devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff * skb,struct genl_info * info)1245 static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb,
1246 						struct genl_info *info)
1247 {
1248 	struct devlink_port *devlink_port = info->user_ptr[0];
1249 	struct devlink_sb *devlink_sb = info->user_ptr[1];
1250 	u16 pool_index;
1251 	u32 threshold;
1252 	int err;
1253 
1254 	err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1255 						  &pool_index);
1256 	if (err)
1257 		return err;
1258 
1259 	if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1260 		return -EINVAL;
1261 
1262 	threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1263 	return devlink_sb_port_pool_set(devlink_port, devlink_sb->index,
1264 					pool_index, threshold);
1265 }
1266 
1267 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)1268 devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink,
1269 				struct devlink_port *devlink_port,
1270 				struct devlink_sb *devlink_sb, u16 tc_index,
1271 				enum devlink_sb_pool_type pool_type,
1272 				enum devlink_command cmd,
1273 				u32 portid, u32 seq, int flags)
1274 {
1275 	const struct devlink_ops *ops = devlink->ops;
1276 	u16 pool_index;
1277 	u32 threshold;
1278 	void *hdr;
1279 	int err;
1280 
1281 	err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index,
1282 				       tc_index, pool_type,
1283 				       &pool_index, &threshold);
1284 	if (err)
1285 		return err;
1286 
1287 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1288 	if (!hdr)
1289 		return -EMSGSIZE;
1290 
1291 	if (devlink_nl_put_handle(msg, devlink))
1292 		goto nla_put_failure;
1293 	if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1294 		goto nla_put_failure;
1295 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1296 		goto nla_put_failure;
1297 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index))
1298 		goto nla_put_failure;
1299 	if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type))
1300 		goto nla_put_failure;
1301 	if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
1302 		goto nla_put_failure;
1303 	if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1304 		goto nla_put_failure;
1305 
1306 	if (ops->sb_occ_tc_port_bind_get) {
1307 		u32 cur;
1308 		u32 max;
1309 
1310 		err = ops->sb_occ_tc_port_bind_get(devlink_port,
1311 						   devlink_sb->index,
1312 						   tc_index, pool_type,
1313 						   &cur, &max);
1314 		if (err && err != -EOPNOTSUPP)
1315 			return err;
1316 		if (!err) {
1317 			if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
1318 				goto nla_put_failure;
1319 			if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
1320 				goto nla_put_failure;
1321 		}
1322 	}
1323 
1324 	genlmsg_end(msg, hdr);
1325 	return 0;
1326 
1327 nla_put_failure:
1328 	genlmsg_cancel(msg, hdr);
1329 	return -EMSGSIZE;
1330 }
1331 
devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff * skb,struct genl_info * info)1332 static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb,
1333 						   struct genl_info *info)
1334 {
1335 	struct devlink_port *devlink_port = info->user_ptr[0];
1336 	struct devlink *devlink = devlink_port->devlink;
1337 	struct devlink_sb *devlink_sb = info->user_ptr[1];
1338 	struct sk_buff *msg;
1339 	enum devlink_sb_pool_type pool_type;
1340 	u16 tc_index;
1341 	int err;
1342 
1343 	err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1344 	if (err)
1345 		return err;
1346 
1347 	err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1348 						pool_type, &tc_index);
1349 	if (err)
1350 		return err;
1351 
1352 	if (!devlink->ops || !devlink->ops->sb_tc_pool_bind_get)
1353 		return -EOPNOTSUPP;
1354 
1355 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1356 	if (!msg)
1357 		return -ENOMEM;
1358 
1359 	err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port,
1360 					      devlink_sb, tc_index, pool_type,
1361 					      DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1362 					      info->snd_portid,
1363 					      info->snd_seq, 0);
1364 	if (err) {
1365 		nlmsg_free(msg);
1366 		return err;
1367 	}
1368 
1369 	return genlmsg_reply(msg, info);
1370 }
1371 
__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)1372 static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1373 					int start, int *p_idx,
1374 					struct devlink *devlink,
1375 					struct devlink_sb *devlink_sb,
1376 					u32 portid, u32 seq)
1377 {
1378 	struct devlink_port *devlink_port;
1379 	u16 tc_index;
1380 	int err;
1381 
1382 	list_for_each_entry(devlink_port, &devlink->port_list, list) {
1383 		for (tc_index = 0;
1384 		     tc_index < devlink_sb->ingress_tc_count; tc_index++) {
1385 			if (*p_idx < start) {
1386 				(*p_idx)++;
1387 				continue;
1388 			}
1389 			err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1390 							      devlink_port,
1391 							      devlink_sb,
1392 							      tc_index,
1393 							      DEVLINK_SB_POOL_TYPE_INGRESS,
1394 							      DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1395 							      portid, seq,
1396 							      NLM_F_MULTI);
1397 			if (err)
1398 				return err;
1399 			(*p_idx)++;
1400 		}
1401 		for (tc_index = 0;
1402 		     tc_index < devlink_sb->egress_tc_count; tc_index++) {
1403 			if (*p_idx < start) {
1404 				(*p_idx)++;
1405 				continue;
1406 			}
1407 			err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1408 							      devlink_port,
1409 							      devlink_sb,
1410 							      tc_index,
1411 							      DEVLINK_SB_POOL_TYPE_EGRESS,
1412 							      DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1413 							      portid, seq,
1414 							      NLM_F_MULTI);
1415 			if (err)
1416 				return err;
1417 			(*p_idx)++;
1418 		}
1419 	}
1420 	return 0;
1421 }
1422 
1423 static int
devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)1424 devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1425 					  struct netlink_callback *cb)
1426 {
1427 	struct devlink *devlink;
1428 	struct devlink_sb *devlink_sb;
1429 	int start = cb->args[0];
1430 	int idx = 0;
1431 	int err;
1432 
1433 	mutex_lock(&devlink_mutex);
1434 	list_for_each_entry(devlink, &devlink_list, list) {
1435 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1436 		    !devlink->ops || !devlink->ops->sb_tc_pool_bind_get)
1437 			continue;
1438 
1439 		mutex_lock(&devlink->lock);
1440 		list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1441 			err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx,
1442 							   devlink,
1443 							   devlink_sb,
1444 							   NETLINK_CB(cb->skb).portid,
1445 							   cb->nlh->nlmsg_seq);
1446 			if (err && err != -EOPNOTSUPP) {
1447 				mutex_unlock(&devlink->lock);
1448 				goto out;
1449 			}
1450 		}
1451 		mutex_unlock(&devlink->lock);
1452 	}
1453 out:
1454 	mutex_unlock(&devlink_mutex);
1455 
1456 	cb->args[0] = idx;
1457 	return msg->len;
1458 }
1459 
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)1460 static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
1461 				       unsigned int sb_index, u16 tc_index,
1462 				       enum devlink_sb_pool_type pool_type,
1463 				       u16 pool_index, u32 threshold)
1464 
1465 {
1466 	const struct devlink_ops *ops = devlink_port->devlink->ops;
1467 
1468 	if (ops && ops->sb_tc_pool_bind_set)
1469 		return ops->sb_tc_pool_bind_set(devlink_port, sb_index,
1470 						tc_index, pool_type,
1471 						pool_index, threshold);
1472 	return -EOPNOTSUPP;
1473 }
1474 
devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff * skb,struct genl_info * info)1475 static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb,
1476 						   struct genl_info *info)
1477 {
1478 	struct devlink_port *devlink_port = info->user_ptr[0];
1479 	struct devlink_sb *devlink_sb = info->user_ptr[1];
1480 	enum devlink_sb_pool_type pool_type;
1481 	u16 tc_index;
1482 	u16 pool_index;
1483 	u32 threshold;
1484 	int err;
1485 
1486 	err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1487 	if (err)
1488 		return err;
1489 
1490 	err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1491 						pool_type, &tc_index);
1492 	if (err)
1493 		return err;
1494 
1495 	err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1496 						  &pool_index);
1497 	if (err)
1498 		return err;
1499 
1500 	if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1501 		return -EINVAL;
1502 
1503 	threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1504 	return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index,
1505 					   tc_index, pool_type,
1506 					   pool_index, threshold);
1507 }
1508 
devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff * skb,struct genl_info * info)1509 static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb,
1510 					       struct genl_info *info)
1511 {
1512 	struct devlink *devlink = info->user_ptr[0];
1513 	struct devlink_sb *devlink_sb = info->user_ptr[1];
1514 	const struct devlink_ops *ops = devlink->ops;
1515 
1516 	if (ops && ops->sb_occ_snapshot)
1517 		return ops->sb_occ_snapshot(devlink, devlink_sb->index);
1518 	return -EOPNOTSUPP;
1519 }
1520 
devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff * skb,struct genl_info * info)1521 static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb,
1522 						struct genl_info *info)
1523 {
1524 	struct devlink *devlink = info->user_ptr[0];
1525 	struct devlink_sb *devlink_sb = info->user_ptr[1];
1526 	const struct devlink_ops *ops = devlink->ops;
1527 
1528 	if (ops && ops->sb_occ_max_clear)
1529 		return ops->sb_occ_max_clear(devlink, devlink_sb->index);
1530 	return -EOPNOTSUPP;
1531 }
1532 
devlink_nl_eswitch_fill(struct sk_buff * msg,struct devlink * devlink,enum devlink_command cmd,u32 portid,u32 seq,int flags)1533 static int devlink_nl_eswitch_fill(struct sk_buff *msg, struct devlink *devlink,
1534 				   enum devlink_command cmd, u32 portid,
1535 				   u32 seq, int flags)
1536 {
1537 	const struct devlink_ops *ops = devlink->ops;
1538 	u8 inline_mode, encap_mode;
1539 	void *hdr;
1540 	int err = 0;
1541 	u16 mode;
1542 
1543 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1544 	if (!hdr)
1545 		return -EMSGSIZE;
1546 
1547 	err = devlink_nl_put_handle(msg, devlink);
1548 	if (err)
1549 		goto nla_put_failure;
1550 
1551 	if (ops->eswitch_mode_get) {
1552 		err = ops->eswitch_mode_get(devlink, &mode);
1553 		if (err)
1554 			goto nla_put_failure;
1555 		err = nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode);
1556 		if (err)
1557 			goto nla_put_failure;
1558 	}
1559 
1560 	if (ops->eswitch_inline_mode_get) {
1561 		err = ops->eswitch_inline_mode_get(devlink, &inline_mode);
1562 		if (err)
1563 			goto nla_put_failure;
1564 		err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE,
1565 				 inline_mode);
1566 		if (err)
1567 			goto nla_put_failure;
1568 	}
1569 
1570 	if (ops->eswitch_encap_mode_get) {
1571 		err = ops->eswitch_encap_mode_get(devlink, &encap_mode);
1572 		if (err)
1573 			goto nla_put_failure;
1574 		err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, encap_mode);
1575 		if (err)
1576 			goto nla_put_failure;
1577 	}
1578 
1579 	genlmsg_end(msg, hdr);
1580 	return 0;
1581 
1582 nla_put_failure:
1583 	genlmsg_cancel(msg, hdr);
1584 	return err;
1585 }
1586 
devlink_nl_cmd_eswitch_get_doit(struct sk_buff * skb,struct genl_info * info)1587 static int devlink_nl_cmd_eswitch_get_doit(struct sk_buff *skb,
1588 					   struct genl_info *info)
1589 {
1590 	struct devlink *devlink = info->user_ptr[0];
1591 	const struct devlink_ops *ops = devlink->ops;
1592 	struct sk_buff *msg;
1593 	int err;
1594 
1595 	if (!ops)
1596 		return -EOPNOTSUPP;
1597 
1598 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1599 	if (!msg)
1600 		return -ENOMEM;
1601 
1602 	err = devlink_nl_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_GET,
1603 				      info->snd_portid, info->snd_seq, 0);
1604 
1605 	if (err) {
1606 		nlmsg_free(msg);
1607 		return err;
1608 	}
1609 
1610 	return genlmsg_reply(msg, info);
1611 }
1612 
devlink_nl_cmd_eswitch_set_doit(struct sk_buff * skb,struct genl_info * info)1613 static int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb,
1614 					   struct genl_info *info)
1615 {
1616 	struct devlink *devlink = info->user_ptr[0];
1617 	const struct devlink_ops *ops = devlink->ops;
1618 	u8 inline_mode, encap_mode;
1619 	int err = 0;
1620 	u16 mode;
1621 
1622 	if (!ops)
1623 		return -EOPNOTSUPP;
1624 
1625 	if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) {
1626 		if (!ops->eswitch_mode_set)
1627 			return -EOPNOTSUPP;
1628 		mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]);
1629 		err = ops->eswitch_mode_set(devlink, mode);
1630 		if (err)
1631 			return err;
1632 	}
1633 
1634 	if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) {
1635 		if (!ops->eswitch_inline_mode_set)
1636 			return -EOPNOTSUPP;
1637 		inline_mode = nla_get_u8(
1638 				info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]);
1639 		err = ops->eswitch_inline_mode_set(devlink, inline_mode);
1640 		if (err)
1641 			return err;
1642 	}
1643 
1644 	if (info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]) {
1645 		if (!ops->eswitch_encap_mode_set)
1646 			return -EOPNOTSUPP;
1647 		encap_mode = nla_get_u8(info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]);
1648 		err = ops->eswitch_encap_mode_set(devlink, encap_mode);
1649 		if (err)
1650 			return err;
1651 	}
1652 
1653 	return 0;
1654 }
1655 
devlink_dpipe_match_put(struct sk_buff * skb,struct devlink_dpipe_match * match)1656 int devlink_dpipe_match_put(struct sk_buff *skb,
1657 			    struct devlink_dpipe_match *match)
1658 {
1659 	struct devlink_dpipe_header *header = match->header;
1660 	struct devlink_dpipe_field *field = &header->fields[match->field_id];
1661 	struct nlattr *match_attr;
1662 
1663 	match_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_MATCH);
1664 	if (!match_attr)
1665 		return -EMSGSIZE;
1666 
1667 	if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_MATCH_TYPE, match->type) ||
1668 	    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, match->header_index) ||
1669 	    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
1670 	    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
1671 	    nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
1672 		goto nla_put_failure;
1673 
1674 	nla_nest_end(skb, match_attr);
1675 	return 0;
1676 
1677 nla_put_failure:
1678 	nla_nest_cancel(skb, match_attr);
1679 	return -EMSGSIZE;
1680 }
1681 EXPORT_SYMBOL_GPL(devlink_dpipe_match_put);
1682 
devlink_dpipe_matches_put(struct devlink_dpipe_table * table,struct sk_buff * skb)1683 static int devlink_dpipe_matches_put(struct devlink_dpipe_table *table,
1684 				     struct sk_buff *skb)
1685 {
1686 	struct nlattr *matches_attr;
1687 
1688 	matches_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLE_MATCHES);
1689 	if (!matches_attr)
1690 		return -EMSGSIZE;
1691 
1692 	if (table->table_ops->matches_dump(table->priv, skb))
1693 		goto nla_put_failure;
1694 
1695 	nla_nest_end(skb, matches_attr);
1696 	return 0;
1697 
1698 nla_put_failure:
1699 	nla_nest_cancel(skb, matches_attr);
1700 	return -EMSGSIZE;
1701 }
1702 
devlink_dpipe_action_put(struct sk_buff * skb,struct devlink_dpipe_action * action)1703 int devlink_dpipe_action_put(struct sk_buff *skb,
1704 			     struct devlink_dpipe_action *action)
1705 {
1706 	struct devlink_dpipe_header *header = action->header;
1707 	struct devlink_dpipe_field *field = &header->fields[action->field_id];
1708 	struct nlattr *action_attr;
1709 
1710 	action_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_ACTION);
1711 	if (!action_attr)
1712 		return -EMSGSIZE;
1713 
1714 	if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_ACTION_TYPE, action->type) ||
1715 	    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, action->header_index) ||
1716 	    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
1717 	    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
1718 	    nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
1719 		goto nla_put_failure;
1720 
1721 	nla_nest_end(skb, action_attr);
1722 	return 0;
1723 
1724 nla_put_failure:
1725 	nla_nest_cancel(skb, action_attr);
1726 	return -EMSGSIZE;
1727 }
1728 EXPORT_SYMBOL_GPL(devlink_dpipe_action_put);
1729 
devlink_dpipe_actions_put(struct devlink_dpipe_table * table,struct sk_buff * skb)1730 static int devlink_dpipe_actions_put(struct devlink_dpipe_table *table,
1731 				     struct sk_buff *skb)
1732 {
1733 	struct nlattr *actions_attr;
1734 
1735 	actions_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLE_ACTIONS);
1736 	if (!actions_attr)
1737 		return -EMSGSIZE;
1738 
1739 	if (table->table_ops->actions_dump(table->priv, skb))
1740 		goto nla_put_failure;
1741 
1742 	nla_nest_end(skb, actions_attr);
1743 	return 0;
1744 
1745 nla_put_failure:
1746 	nla_nest_cancel(skb, actions_attr);
1747 	return -EMSGSIZE;
1748 }
1749 
devlink_dpipe_table_put(struct sk_buff * skb,struct devlink_dpipe_table * table)1750 static int devlink_dpipe_table_put(struct sk_buff *skb,
1751 				   struct devlink_dpipe_table *table)
1752 {
1753 	struct nlattr *table_attr;
1754 	u64 table_size;
1755 
1756 	table_size = table->table_ops->size_get(table->priv);
1757 	table_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLE);
1758 	if (!table_attr)
1759 		return -EMSGSIZE;
1760 
1761 	if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) ||
1762 	    nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table_size,
1763 			      DEVLINK_ATTR_PAD))
1764 		goto nla_put_failure;
1765 	if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED,
1766 		       table->counters_enabled))
1767 		goto nla_put_failure;
1768 
1769 	if (table->resource_valid) {
1770 		if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID,
1771 				      table->resource_id, DEVLINK_ATTR_PAD) ||
1772 		    nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS,
1773 				      table->resource_units, DEVLINK_ATTR_PAD))
1774 			goto nla_put_failure;
1775 	}
1776 	if (devlink_dpipe_matches_put(table, skb))
1777 		goto nla_put_failure;
1778 
1779 	if (devlink_dpipe_actions_put(table, skb))
1780 		goto nla_put_failure;
1781 
1782 	nla_nest_end(skb, table_attr);
1783 	return 0;
1784 
1785 nla_put_failure:
1786 	nla_nest_cancel(skb, table_attr);
1787 	return -EMSGSIZE;
1788 }
1789 
devlink_dpipe_send_and_alloc_skb(struct sk_buff ** pskb,struct genl_info * info)1790 static int devlink_dpipe_send_and_alloc_skb(struct sk_buff **pskb,
1791 					    struct genl_info *info)
1792 {
1793 	int err;
1794 
1795 	if (*pskb) {
1796 		err = genlmsg_reply(*pskb, info);
1797 		if (err)
1798 			return err;
1799 	}
1800 	*pskb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
1801 	if (!*pskb)
1802 		return -ENOMEM;
1803 	return 0;
1804 }
1805 
devlink_dpipe_tables_fill(struct genl_info * info,enum devlink_command cmd,int flags,struct list_head * dpipe_tables,const char * table_name)1806 static int devlink_dpipe_tables_fill(struct genl_info *info,
1807 				     enum devlink_command cmd, int flags,
1808 				     struct list_head *dpipe_tables,
1809 				     const char *table_name)
1810 {
1811 	struct devlink *devlink = info->user_ptr[0];
1812 	struct devlink_dpipe_table *table;
1813 	struct nlattr *tables_attr;
1814 	struct sk_buff *skb = NULL;
1815 	struct nlmsghdr *nlh;
1816 	bool incomplete;
1817 	void *hdr;
1818 	int i;
1819 	int err;
1820 
1821 	table = list_first_entry(dpipe_tables,
1822 				 struct devlink_dpipe_table, list);
1823 start_again:
1824 	err = devlink_dpipe_send_and_alloc_skb(&skb, info);
1825 	if (err)
1826 		return err;
1827 
1828 	hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
1829 			  &devlink_nl_family, NLM_F_MULTI, cmd);
1830 	if (!hdr) {
1831 		nlmsg_free(skb);
1832 		return -EMSGSIZE;
1833 	}
1834 
1835 	if (devlink_nl_put_handle(skb, devlink))
1836 		goto nla_put_failure;
1837 	tables_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLES);
1838 	if (!tables_attr)
1839 		goto nla_put_failure;
1840 
1841 	i = 0;
1842 	incomplete = false;
1843 	list_for_each_entry_from(table, dpipe_tables, list) {
1844 		if (!table_name) {
1845 			err = devlink_dpipe_table_put(skb, table);
1846 			if (err) {
1847 				if (!i)
1848 					goto err_table_put;
1849 				incomplete = true;
1850 				break;
1851 			}
1852 		} else {
1853 			if (!strcmp(table->name, table_name)) {
1854 				err = devlink_dpipe_table_put(skb, table);
1855 				if (err)
1856 					break;
1857 			}
1858 		}
1859 		i++;
1860 	}
1861 
1862 	nla_nest_end(skb, tables_attr);
1863 	genlmsg_end(skb, hdr);
1864 	if (incomplete)
1865 		goto start_again;
1866 
1867 send_done:
1868 	nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
1869 			NLMSG_DONE, 0, flags | NLM_F_MULTI);
1870 	if (!nlh) {
1871 		err = devlink_dpipe_send_and_alloc_skb(&skb, info);
1872 		if (err)
1873 			return err;
1874 		goto send_done;
1875 	}
1876 
1877 	return genlmsg_reply(skb, info);
1878 
1879 nla_put_failure:
1880 	err = -EMSGSIZE;
1881 err_table_put:
1882 	nlmsg_free(skb);
1883 	return err;
1884 }
1885 
devlink_nl_cmd_dpipe_table_get(struct sk_buff * skb,struct genl_info * info)1886 static int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb,
1887 					  struct genl_info *info)
1888 {
1889 	struct devlink *devlink = info->user_ptr[0];
1890 	const char *table_name =  NULL;
1891 
1892 	if (info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME])
1893 		table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
1894 
1895 	return devlink_dpipe_tables_fill(info, DEVLINK_CMD_DPIPE_TABLE_GET, 0,
1896 					 &devlink->dpipe_table_list,
1897 					 table_name);
1898 }
1899 
devlink_dpipe_value_put(struct sk_buff * skb,struct devlink_dpipe_value * value)1900 static int devlink_dpipe_value_put(struct sk_buff *skb,
1901 				   struct devlink_dpipe_value *value)
1902 {
1903 	if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE,
1904 		    value->value_size, value->value))
1905 		return -EMSGSIZE;
1906 	if (value->mask)
1907 		if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE_MASK,
1908 			    value->value_size, value->mask))
1909 			return -EMSGSIZE;
1910 	if (value->mapping_valid)
1911 		if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_VALUE_MAPPING,
1912 				value->mapping_value))
1913 			return -EMSGSIZE;
1914 	return 0;
1915 }
1916 
devlink_dpipe_action_value_put(struct sk_buff * skb,struct devlink_dpipe_value * value)1917 static int devlink_dpipe_action_value_put(struct sk_buff *skb,
1918 					  struct devlink_dpipe_value *value)
1919 {
1920 	if (!value->action)
1921 		return -EINVAL;
1922 	if (devlink_dpipe_action_put(skb, value->action))
1923 		return -EMSGSIZE;
1924 	if (devlink_dpipe_value_put(skb, value))
1925 		return -EMSGSIZE;
1926 	return 0;
1927 }
1928 
devlink_dpipe_action_values_put(struct sk_buff * skb,struct devlink_dpipe_value * values,unsigned int values_count)1929 static int devlink_dpipe_action_values_put(struct sk_buff *skb,
1930 					   struct devlink_dpipe_value *values,
1931 					   unsigned int values_count)
1932 {
1933 	struct nlattr *action_attr;
1934 	int i;
1935 	int err;
1936 
1937 	for (i = 0; i < values_count; i++) {
1938 		action_attr = nla_nest_start(skb,
1939 					     DEVLINK_ATTR_DPIPE_ACTION_VALUE);
1940 		if (!action_attr)
1941 			return -EMSGSIZE;
1942 		err = devlink_dpipe_action_value_put(skb, &values[i]);
1943 		if (err)
1944 			goto err_action_value_put;
1945 		nla_nest_end(skb, action_attr);
1946 	}
1947 	return 0;
1948 
1949 err_action_value_put:
1950 	nla_nest_cancel(skb, action_attr);
1951 	return err;
1952 }
1953 
devlink_dpipe_match_value_put(struct sk_buff * skb,struct devlink_dpipe_value * value)1954 static int devlink_dpipe_match_value_put(struct sk_buff *skb,
1955 					 struct devlink_dpipe_value *value)
1956 {
1957 	if (!value->match)
1958 		return -EINVAL;
1959 	if (devlink_dpipe_match_put(skb, value->match))
1960 		return -EMSGSIZE;
1961 	if (devlink_dpipe_value_put(skb, value))
1962 		return -EMSGSIZE;
1963 	return 0;
1964 }
1965 
devlink_dpipe_match_values_put(struct sk_buff * skb,struct devlink_dpipe_value * values,unsigned int values_count)1966 static int devlink_dpipe_match_values_put(struct sk_buff *skb,
1967 					  struct devlink_dpipe_value *values,
1968 					  unsigned int values_count)
1969 {
1970 	struct nlattr *match_attr;
1971 	int i;
1972 	int err;
1973 
1974 	for (i = 0; i < values_count; i++) {
1975 		match_attr = nla_nest_start(skb,
1976 					    DEVLINK_ATTR_DPIPE_MATCH_VALUE);
1977 		if (!match_attr)
1978 			return -EMSGSIZE;
1979 		err = devlink_dpipe_match_value_put(skb, &values[i]);
1980 		if (err)
1981 			goto err_match_value_put;
1982 		nla_nest_end(skb, match_attr);
1983 	}
1984 	return 0;
1985 
1986 err_match_value_put:
1987 	nla_nest_cancel(skb, match_attr);
1988 	return err;
1989 }
1990 
devlink_dpipe_entry_put(struct sk_buff * skb,struct devlink_dpipe_entry * entry)1991 static int devlink_dpipe_entry_put(struct sk_buff *skb,
1992 				   struct devlink_dpipe_entry *entry)
1993 {
1994 	struct nlattr *entry_attr, *matches_attr, *actions_attr;
1995 	int err;
1996 
1997 	entry_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_ENTRY);
1998 	if (!entry_attr)
1999 		return  -EMSGSIZE;
2000 
2001 	if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_INDEX, entry->index,
2002 			      DEVLINK_ATTR_PAD))
2003 		goto nla_put_failure;
2004 	if (entry->counter_valid)
2005 		if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_COUNTER,
2006 				      entry->counter, DEVLINK_ATTR_PAD))
2007 			goto nla_put_failure;
2008 
2009 	matches_attr = nla_nest_start(skb,
2010 				      DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES);
2011 	if (!matches_attr)
2012 		goto nla_put_failure;
2013 
2014 	err = devlink_dpipe_match_values_put(skb, entry->match_values,
2015 					     entry->match_values_count);
2016 	if (err) {
2017 		nla_nest_cancel(skb, matches_attr);
2018 		goto err_match_values_put;
2019 	}
2020 	nla_nest_end(skb, matches_attr);
2021 
2022 	actions_attr = nla_nest_start(skb,
2023 				      DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES);
2024 	if (!actions_attr)
2025 		goto nla_put_failure;
2026 
2027 	err = devlink_dpipe_action_values_put(skb, entry->action_values,
2028 					      entry->action_values_count);
2029 	if (err) {
2030 		nla_nest_cancel(skb, actions_attr);
2031 		goto err_action_values_put;
2032 	}
2033 	nla_nest_end(skb, actions_attr);
2034 
2035 	nla_nest_end(skb, entry_attr);
2036 	return 0;
2037 
2038 nla_put_failure:
2039 	err = -EMSGSIZE;
2040 err_match_values_put:
2041 err_action_values_put:
2042 	nla_nest_cancel(skb, entry_attr);
2043 	return err;
2044 }
2045 
2046 static struct devlink_dpipe_table *
devlink_dpipe_table_find(struct list_head * dpipe_tables,const char * table_name)2047 devlink_dpipe_table_find(struct list_head *dpipe_tables,
2048 			 const char *table_name)
2049 {
2050 	struct devlink_dpipe_table *table;
2051 
2052 	list_for_each_entry_rcu(table, dpipe_tables, list) {
2053 		if (!strcmp(table->name, table_name))
2054 			return table;
2055 	}
2056 	return NULL;
2057 }
2058 
devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx * dump_ctx)2059 int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx)
2060 {
2061 	struct devlink *devlink;
2062 	int err;
2063 
2064 	err = devlink_dpipe_send_and_alloc_skb(&dump_ctx->skb,
2065 					       dump_ctx->info);
2066 	if (err)
2067 		return err;
2068 
2069 	dump_ctx->hdr = genlmsg_put(dump_ctx->skb,
2070 				    dump_ctx->info->snd_portid,
2071 				    dump_ctx->info->snd_seq,
2072 				    &devlink_nl_family, NLM_F_MULTI,
2073 				    dump_ctx->cmd);
2074 	if (!dump_ctx->hdr)
2075 		goto nla_put_failure;
2076 
2077 	devlink = dump_ctx->info->user_ptr[0];
2078 	if (devlink_nl_put_handle(dump_ctx->skb, devlink))
2079 		goto nla_put_failure;
2080 	dump_ctx->nest = nla_nest_start(dump_ctx->skb,
2081 					DEVLINK_ATTR_DPIPE_ENTRIES);
2082 	if (!dump_ctx->nest)
2083 		goto nla_put_failure;
2084 	return 0;
2085 
2086 nla_put_failure:
2087 	nlmsg_free(dump_ctx->skb);
2088 	return -EMSGSIZE;
2089 }
2090 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_prepare);
2091 
devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx * dump_ctx,struct devlink_dpipe_entry * entry)2092 int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx,
2093 				   struct devlink_dpipe_entry *entry)
2094 {
2095 	return devlink_dpipe_entry_put(dump_ctx->skb, entry);
2096 }
2097 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_append);
2098 
devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx * dump_ctx)2099 int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx)
2100 {
2101 	nla_nest_end(dump_ctx->skb, dump_ctx->nest);
2102 	genlmsg_end(dump_ctx->skb, dump_ctx->hdr);
2103 	return 0;
2104 }
2105 EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close);
2106 
devlink_dpipe_entry_clear(struct devlink_dpipe_entry * entry)2107 void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry)
2108 
2109 {
2110 	unsigned int value_count, value_index;
2111 	struct devlink_dpipe_value *value;
2112 
2113 	value = entry->action_values;
2114 	value_count = entry->action_values_count;
2115 	for (value_index = 0; value_index < value_count; value_index++) {
2116 		kfree(value[value_index].value);
2117 		kfree(value[value_index].mask);
2118 	}
2119 
2120 	value = entry->match_values;
2121 	value_count = entry->match_values_count;
2122 	for (value_index = 0; value_index < value_count; value_index++) {
2123 		kfree(value[value_index].value);
2124 		kfree(value[value_index].mask);
2125 	}
2126 }
2127 EXPORT_SYMBOL(devlink_dpipe_entry_clear);
2128 
devlink_dpipe_entries_fill(struct genl_info * info,enum devlink_command cmd,int flags,struct devlink_dpipe_table * table)2129 static int devlink_dpipe_entries_fill(struct genl_info *info,
2130 				      enum devlink_command cmd, int flags,
2131 				      struct devlink_dpipe_table *table)
2132 {
2133 	struct devlink_dpipe_dump_ctx dump_ctx;
2134 	struct nlmsghdr *nlh;
2135 	int err;
2136 
2137 	dump_ctx.skb = NULL;
2138 	dump_ctx.cmd = cmd;
2139 	dump_ctx.info = info;
2140 
2141 	err = table->table_ops->entries_dump(table->priv,
2142 					     table->counters_enabled,
2143 					     &dump_ctx);
2144 	if (err)
2145 		return err;
2146 
2147 send_done:
2148 	nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq,
2149 			NLMSG_DONE, 0, flags | NLM_F_MULTI);
2150 	if (!nlh) {
2151 		err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info);
2152 		if (err)
2153 			return err;
2154 		goto send_done;
2155 	}
2156 	return genlmsg_reply(dump_ctx.skb, info);
2157 }
2158 
devlink_nl_cmd_dpipe_entries_get(struct sk_buff * skb,struct genl_info * info)2159 static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb,
2160 					    struct genl_info *info)
2161 {
2162 	struct devlink *devlink = info->user_ptr[0];
2163 	struct devlink_dpipe_table *table;
2164 	const char *table_name;
2165 
2166 	if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME])
2167 		return -EINVAL;
2168 
2169 	table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
2170 	table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2171 					 table_name);
2172 	if (!table)
2173 		return -EINVAL;
2174 
2175 	if (!table->table_ops->entries_dump)
2176 		return -EINVAL;
2177 
2178 	return devlink_dpipe_entries_fill(info, DEVLINK_CMD_DPIPE_ENTRIES_GET,
2179 					  0, table);
2180 }
2181 
devlink_dpipe_fields_put(struct sk_buff * skb,const struct devlink_dpipe_header * header)2182 static int devlink_dpipe_fields_put(struct sk_buff *skb,
2183 				    const struct devlink_dpipe_header *header)
2184 {
2185 	struct devlink_dpipe_field *field;
2186 	struct nlattr *field_attr;
2187 	int i;
2188 
2189 	for (i = 0; i < header->fields_count; i++) {
2190 		field = &header->fields[i];
2191 		field_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_FIELD);
2192 		if (!field_attr)
2193 			return -EMSGSIZE;
2194 		if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_FIELD_NAME, field->name) ||
2195 		    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
2196 		    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, field->bitwidth) ||
2197 		    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, field->mapping_type))
2198 			goto nla_put_failure;
2199 		nla_nest_end(skb, field_attr);
2200 	}
2201 	return 0;
2202 
2203 nla_put_failure:
2204 	nla_nest_cancel(skb, field_attr);
2205 	return -EMSGSIZE;
2206 }
2207 
devlink_dpipe_header_put(struct sk_buff * skb,struct devlink_dpipe_header * header)2208 static int devlink_dpipe_header_put(struct sk_buff *skb,
2209 				    struct devlink_dpipe_header *header)
2210 {
2211 	struct nlattr *fields_attr, *header_attr;
2212 	int err;
2213 
2214 	header_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADER);
2215 	if (!header_attr)
2216 		return -EMSGSIZE;
2217 
2218 	if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_HEADER_NAME, header->name) ||
2219 	    nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
2220 	    nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
2221 		goto nla_put_failure;
2222 
2223 	fields_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADER_FIELDS);
2224 	if (!fields_attr)
2225 		goto nla_put_failure;
2226 
2227 	err = devlink_dpipe_fields_put(skb, header);
2228 	if (err) {
2229 		nla_nest_cancel(skb, fields_attr);
2230 		goto nla_put_failure;
2231 	}
2232 	nla_nest_end(skb, fields_attr);
2233 	nla_nest_end(skb, header_attr);
2234 	return 0;
2235 
2236 nla_put_failure:
2237 	err = -EMSGSIZE;
2238 	nla_nest_cancel(skb, header_attr);
2239 	return err;
2240 }
2241 
devlink_dpipe_headers_fill(struct genl_info * info,enum devlink_command cmd,int flags,struct devlink_dpipe_headers * dpipe_headers)2242 static int devlink_dpipe_headers_fill(struct genl_info *info,
2243 				      enum devlink_command cmd, int flags,
2244 				      struct devlink_dpipe_headers *
2245 				      dpipe_headers)
2246 {
2247 	struct devlink *devlink = info->user_ptr[0];
2248 	struct nlattr *headers_attr;
2249 	struct sk_buff *skb = NULL;
2250 	struct nlmsghdr *nlh;
2251 	void *hdr;
2252 	int i, j;
2253 	int err;
2254 
2255 	i = 0;
2256 start_again:
2257 	err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2258 	if (err)
2259 		return err;
2260 
2261 	hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
2262 			  &devlink_nl_family, NLM_F_MULTI, cmd);
2263 	if (!hdr) {
2264 		nlmsg_free(skb);
2265 		return -EMSGSIZE;
2266 	}
2267 
2268 	if (devlink_nl_put_handle(skb, devlink))
2269 		goto nla_put_failure;
2270 	headers_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADERS);
2271 	if (!headers_attr)
2272 		goto nla_put_failure;
2273 
2274 	j = 0;
2275 	for (; i < dpipe_headers->headers_count; i++) {
2276 		err = devlink_dpipe_header_put(skb, dpipe_headers->headers[i]);
2277 		if (err) {
2278 			if (!j)
2279 				goto err_table_put;
2280 			break;
2281 		}
2282 		j++;
2283 	}
2284 	nla_nest_end(skb, headers_attr);
2285 	genlmsg_end(skb, hdr);
2286 	if (i != dpipe_headers->headers_count)
2287 		goto start_again;
2288 
2289 send_done:
2290 	nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
2291 			NLMSG_DONE, 0, flags | NLM_F_MULTI);
2292 	if (!nlh) {
2293 		err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2294 		if (err)
2295 			return err;
2296 		goto send_done;
2297 	}
2298 	return genlmsg_reply(skb, info);
2299 
2300 nla_put_failure:
2301 	err = -EMSGSIZE;
2302 err_table_put:
2303 	nlmsg_free(skb);
2304 	return err;
2305 }
2306 
devlink_nl_cmd_dpipe_headers_get(struct sk_buff * skb,struct genl_info * info)2307 static int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb,
2308 					    struct genl_info *info)
2309 {
2310 	struct devlink *devlink = info->user_ptr[0];
2311 
2312 	if (!devlink->dpipe_headers)
2313 		return -EOPNOTSUPP;
2314 	return devlink_dpipe_headers_fill(info, DEVLINK_CMD_DPIPE_HEADERS_GET,
2315 					  0, devlink->dpipe_headers);
2316 }
2317 
devlink_dpipe_table_counters_set(struct devlink * devlink,const char * table_name,bool enable)2318 static int devlink_dpipe_table_counters_set(struct devlink *devlink,
2319 					    const char *table_name,
2320 					    bool enable)
2321 {
2322 	struct devlink_dpipe_table *table;
2323 
2324 	table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2325 					 table_name);
2326 	if (!table)
2327 		return -EINVAL;
2328 
2329 	if (table->counter_control_extern)
2330 		return -EOPNOTSUPP;
2331 
2332 	if (!(table->counters_enabled ^ enable))
2333 		return 0;
2334 
2335 	table->counters_enabled = enable;
2336 	if (table->table_ops->counters_set_update)
2337 		table->table_ops->counters_set_update(table->priv, enable);
2338 	return 0;
2339 }
2340 
devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff * skb,struct genl_info * info)2341 static int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb,
2342 						   struct genl_info *info)
2343 {
2344 	struct devlink *devlink = info->user_ptr[0];
2345 	const char *table_name;
2346 	bool counters_enable;
2347 
2348 	if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME] ||
2349 	    !info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED])
2350 		return -EINVAL;
2351 
2352 	table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
2353 	counters_enable = !!nla_get_u8(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]);
2354 
2355 	return devlink_dpipe_table_counters_set(devlink, table_name,
2356 						counters_enable);
2357 }
2358 
2359 static struct devlink_resource *
devlink_resource_find(struct devlink * devlink,struct devlink_resource * resource,u64 resource_id)2360 devlink_resource_find(struct devlink *devlink,
2361 		      struct devlink_resource *resource, u64 resource_id)
2362 {
2363 	struct list_head *resource_list;
2364 
2365 	if (resource)
2366 		resource_list = &resource->resource_list;
2367 	else
2368 		resource_list = &devlink->resource_list;
2369 
2370 	list_for_each_entry(resource, resource_list, list) {
2371 		struct devlink_resource *child_resource;
2372 
2373 		if (resource->id == resource_id)
2374 			return resource;
2375 
2376 		child_resource = devlink_resource_find(devlink, resource,
2377 						       resource_id);
2378 		if (child_resource)
2379 			return child_resource;
2380 	}
2381 	return NULL;
2382 }
2383 
2384 static void
devlink_resource_validate_children(struct devlink_resource * resource)2385 devlink_resource_validate_children(struct devlink_resource *resource)
2386 {
2387 	struct devlink_resource *child_resource;
2388 	bool size_valid = true;
2389 	u64 parts_size = 0;
2390 
2391 	if (list_empty(&resource->resource_list))
2392 		goto out;
2393 
2394 	list_for_each_entry(child_resource, &resource->resource_list, list)
2395 		parts_size += child_resource->size_new;
2396 
2397 	if (parts_size > resource->size_new)
2398 		size_valid = false;
2399 out:
2400 	resource->size_valid = size_valid;
2401 }
2402 
2403 static int
devlink_resource_validate_size(struct devlink_resource * resource,u64 size,struct netlink_ext_ack * extack)2404 devlink_resource_validate_size(struct devlink_resource *resource, u64 size,
2405 			       struct netlink_ext_ack *extack)
2406 {
2407 	u64 reminder;
2408 	int err = 0;
2409 
2410 	if (size > resource->size_params.size_max) {
2411 		NL_SET_ERR_MSG_MOD(extack, "Size larger than maximum");
2412 		err = -EINVAL;
2413 	}
2414 
2415 	if (size < resource->size_params.size_min) {
2416 		NL_SET_ERR_MSG_MOD(extack, "Size smaller than minimum");
2417 		err = -EINVAL;
2418 	}
2419 
2420 	div64_u64_rem(size, resource->size_params.size_granularity, &reminder);
2421 	if (reminder) {
2422 		NL_SET_ERR_MSG_MOD(extack, "Wrong granularity");
2423 		err = -EINVAL;
2424 	}
2425 
2426 	return err;
2427 }
2428 
devlink_nl_cmd_resource_set(struct sk_buff * skb,struct genl_info * info)2429 static int devlink_nl_cmd_resource_set(struct sk_buff *skb,
2430 				       struct genl_info *info)
2431 {
2432 	struct devlink *devlink = info->user_ptr[0];
2433 	struct devlink_resource *resource;
2434 	u64 resource_id;
2435 	u64 size;
2436 	int err;
2437 
2438 	if (!info->attrs[DEVLINK_ATTR_RESOURCE_ID] ||
2439 	    !info->attrs[DEVLINK_ATTR_RESOURCE_SIZE])
2440 		return -EINVAL;
2441 	resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]);
2442 
2443 	resource = devlink_resource_find(devlink, NULL, resource_id);
2444 	if (!resource)
2445 		return -EINVAL;
2446 
2447 	size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]);
2448 	err = devlink_resource_validate_size(resource, size, info->extack);
2449 	if (err)
2450 		return err;
2451 
2452 	resource->size_new = size;
2453 	devlink_resource_validate_children(resource);
2454 	if (resource->parent)
2455 		devlink_resource_validate_children(resource->parent);
2456 	return 0;
2457 }
2458 
2459 static int
devlink_resource_size_params_put(struct devlink_resource * resource,struct sk_buff * skb)2460 devlink_resource_size_params_put(struct devlink_resource *resource,
2461 				 struct sk_buff *skb)
2462 {
2463 	struct devlink_resource_size_params *size_params;
2464 
2465 	size_params = &resource->size_params;
2466 	if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN,
2467 			      size_params->size_granularity, DEVLINK_ATTR_PAD) ||
2468 	    nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX,
2469 			      size_params->size_max, DEVLINK_ATTR_PAD) ||
2470 	    nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN,
2471 			      size_params->size_min, DEVLINK_ATTR_PAD) ||
2472 	    nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit))
2473 		return -EMSGSIZE;
2474 	return 0;
2475 }
2476 
devlink_resource_occ_put(struct devlink_resource * resource,struct sk_buff * skb)2477 static int devlink_resource_occ_put(struct devlink_resource *resource,
2478 				    struct sk_buff *skb)
2479 {
2480 	if (!resource->occ_get)
2481 		return 0;
2482 	return nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC,
2483 				 resource->occ_get(resource->occ_get_priv),
2484 				 DEVLINK_ATTR_PAD);
2485 }
2486 
devlink_resource_put(struct devlink * devlink,struct sk_buff * skb,struct devlink_resource * resource)2487 static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb,
2488 				struct devlink_resource *resource)
2489 {
2490 	struct devlink_resource *child_resource;
2491 	struct nlattr *child_resource_attr;
2492 	struct nlattr *resource_attr;
2493 
2494 	resource_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE);
2495 	if (!resource_attr)
2496 		return -EMSGSIZE;
2497 
2498 	if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) ||
2499 	    nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size,
2500 			      DEVLINK_ATTR_PAD) ||
2501 	    nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id,
2502 			      DEVLINK_ATTR_PAD))
2503 		goto nla_put_failure;
2504 	if (resource->size != resource->size_new)
2505 		nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW,
2506 				  resource->size_new, DEVLINK_ATTR_PAD);
2507 	if (devlink_resource_occ_put(resource, skb))
2508 		goto nla_put_failure;
2509 	if (devlink_resource_size_params_put(resource, skb))
2510 		goto nla_put_failure;
2511 	if (list_empty(&resource->resource_list))
2512 		goto out;
2513 
2514 	if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID,
2515 		       resource->size_valid))
2516 		goto nla_put_failure;
2517 
2518 	child_resource_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE_LIST);
2519 	if (!child_resource_attr)
2520 		goto nla_put_failure;
2521 
2522 	list_for_each_entry(child_resource, &resource->resource_list, list) {
2523 		if (devlink_resource_put(devlink, skb, child_resource))
2524 			goto resource_put_failure;
2525 	}
2526 
2527 	nla_nest_end(skb, child_resource_attr);
2528 out:
2529 	nla_nest_end(skb, resource_attr);
2530 	return 0;
2531 
2532 resource_put_failure:
2533 	nla_nest_cancel(skb, child_resource_attr);
2534 nla_put_failure:
2535 	nla_nest_cancel(skb, resource_attr);
2536 	return -EMSGSIZE;
2537 }
2538 
devlink_resource_fill(struct genl_info * info,enum devlink_command cmd,int flags)2539 static int devlink_resource_fill(struct genl_info *info,
2540 				 enum devlink_command cmd, int flags)
2541 {
2542 	struct devlink *devlink = info->user_ptr[0];
2543 	struct devlink_resource *resource;
2544 	struct nlattr *resources_attr;
2545 	struct sk_buff *skb = NULL;
2546 	struct nlmsghdr *nlh;
2547 	bool incomplete;
2548 	void *hdr;
2549 	int i;
2550 	int err;
2551 
2552 	resource = list_first_entry(&devlink->resource_list,
2553 				    struct devlink_resource, list);
2554 start_again:
2555 	err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2556 	if (err)
2557 		return err;
2558 
2559 	hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
2560 			  &devlink_nl_family, NLM_F_MULTI, cmd);
2561 	if (!hdr) {
2562 		nlmsg_free(skb);
2563 		return -EMSGSIZE;
2564 	}
2565 
2566 	if (devlink_nl_put_handle(skb, devlink))
2567 		goto nla_put_failure;
2568 
2569 	resources_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE_LIST);
2570 	if (!resources_attr)
2571 		goto nla_put_failure;
2572 
2573 	incomplete = false;
2574 	i = 0;
2575 	list_for_each_entry_from(resource, &devlink->resource_list, list) {
2576 		err = devlink_resource_put(devlink, skb, resource);
2577 		if (err) {
2578 			if (!i)
2579 				goto err_resource_put;
2580 			incomplete = true;
2581 			break;
2582 		}
2583 		i++;
2584 	}
2585 	nla_nest_end(skb, resources_attr);
2586 	genlmsg_end(skb, hdr);
2587 	if (incomplete)
2588 		goto start_again;
2589 send_done:
2590 	nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
2591 			NLMSG_DONE, 0, flags | NLM_F_MULTI);
2592 	if (!nlh) {
2593 		err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2594 		if (err)
2595 			return err;
2596 		goto send_done;
2597 	}
2598 	return genlmsg_reply(skb, info);
2599 
2600 nla_put_failure:
2601 	err = -EMSGSIZE;
2602 err_resource_put:
2603 	nlmsg_free(skb);
2604 	return err;
2605 }
2606 
devlink_nl_cmd_resource_dump(struct sk_buff * skb,struct genl_info * info)2607 static int devlink_nl_cmd_resource_dump(struct sk_buff *skb,
2608 					struct genl_info *info)
2609 {
2610 	struct devlink *devlink = info->user_ptr[0];
2611 
2612 	if (list_empty(&devlink->resource_list))
2613 		return -EOPNOTSUPP;
2614 
2615 	return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0);
2616 }
2617 
2618 static int
devlink_resources_validate(struct devlink * devlink,struct devlink_resource * resource,struct genl_info * info)2619 devlink_resources_validate(struct devlink *devlink,
2620 			   struct devlink_resource *resource,
2621 			   struct genl_info *info)
2622 {
2623 	struct list_head *resource_list;
2624 	int err = 0;
2625 
2626 	if (resource)
2627 		resource_list = &resource->resource_list;
2628 	else
2629 		resource_list = &devlink->resource_list;
2630 
2631 	list_for_each_entry(resource, resource_list, list) {
2632 		if (!resource->size_valid)
2633 			return -EINVAL;
2634 		err = devlink_resources_validate(devlink, resource, info);
2635 		if (err)
2636 			return err;
2637 	}
2638 	return err;
2639 }
2640 
devlink_nl_cmd_reload(struct sk_buff * skb,struct genl_info * info)2641 static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
2642 {
2643 	struct devlink *devlink = info->user_ptr[0];
2644 	int err;
2645 
2646 	if (!devlink->ops->reload)
2647 		return -EOPNOTSUPP;
2648 
2649 	err = devlink_resources_validate(devlink, NULL, info);
2650 	if (err) {
2651 		NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed");
2652 		return err;
2653 	}
2654 	return devlink->ops->reload(devlink, info->extack);
2655 }
2656 
2657 static const struct devlink_param devlink_param_generic[] = {
2658 	{
2659 		.id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET,
2660 		.name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME,
2661 		.type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE,
2662 	},
2663 	{
2664 		.id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
2665 		.name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME,
2666 		.type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE,
2667 	},
2668 	{
2669 		.id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV,
2670 		.name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME,
2671 		.type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE,
2672 	},
2673 	{
2674 		.id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT,
2675 		.name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME,
2676 		.type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE,
2677 	},
2678 };
2679 
devlink_param_generic_verify(const struct devlink_param * param)2680 static int devlink_param_generic_verify(const struct devlink_param *param)
2681 {
2682 	/* verify it match generic parameter by id and name */
2683 	if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX)
2684 		return -EINVAL;
2685 	if (strcmp(param->name, devlink_param_generic[param->id].name))
2686 		return -ENOENT;
2687 
2688 	WARN_ON(param->type != devlink_param_generic[param->id].type);
2689 
2690 	return 0;
2691 }
2692 
devlink_param_driver_verify(const struct devlink_param * param)2693 static int devlink_param_driver_verify(const struct devlink_param *param)
2694 {
2695 	int i;
2696 
2697 	if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX)
2698 		return -EINVAL;
2699 	/* verify no such name in generic params */
2700 	for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++)
2701 		if (!strcmp(param->name, devlink_param_generic[i].name))
2702 			return -EEXIST;
2703 
2704 	return 0;
2705 }
2706 
2707 static struct devlink_param_item *
devlink_param_find_by_name(struct list_head * param_list,const char * param_name)2708 devlink_param_find_by_name(struct list_head *param_list,
2709 			   const char *param_name)
2710 {
2711 	struct devlink_param_item *param_item;
2712 
2713 	list_for_each_entry(param_item, param_list, list)
2714 		if (!strcmp(param_item->param->name, param_name))
2715 			return param_item;
2716 	return NULL;
2717 }
2718 
2719 static struct devlink_param_item *
devlink_param_find_by_id(struct list_head * param_list,u32 param_id)2720 devlink_param_find_by_id(struct list_head *param_list, u32 param_id)
2721 {
2722 	struct devlink_param_item *param_item;
2723 
2724 	list_for_each_entry(param_item, param_list, list)
2725 		if (param_item->param->id == param_id)
2726 			return param_item;
2727 	return NULL;
2728 }
2729 
2730 static bool
devlink_param_cmode_is_supported(const struct devlink_param * param,enum devlink_param_cmode cmode)2731 devlink_param_cmode_is_supported(const struct devlink_param *param,
2732 				 enum devlink_param_cmode cmode)
2733 {
2734 	return test_bit(cmode, &param->supported_cmodes);
2735 }
2736 
devlink_param_get(struct devlink * devlink,const struct devlink_param * param,struct devlink_param_gset_ctx * ctx)2737 static int devlink_param_get(struct devlink *devlink,
2738 			     const struct devlink_param *param,
2739 			     struct devlink_param_gset_ctx *ctx)
2740 {
2741 	if (!param->get)
2742 		return -EOPNOTSUPP;
2743 	return param->get(devlink, param->id, ctx);
2744 }
2745 
devlink_param_set(struct devlink * devlink,const struct devlink_param * param,struct devlink_param_gset_ctx * ctx)2746 static int devlink_param_set(struct devlink *devlink,
2747 			     const struct devlink_param *param,
2748 			     struct devlink_param_gset_ctx *ctx)
2749 {
2750 	if (!param->set)
2751 		return -EOPNOTSUPP;
2752 	return param->set(devlink, param->id, ctx);
2753 }
2754 
2755 static int
devlink_param_type_to_nla_type(enum devlink_param_type param_type)2756 devlink_param_type_to_nla_type(enum devlink_param_type param_type)
2757 {
2758 	switch (param_type) {
2759 	case DEVLINK_PARAM_TYPE_U8:
2760 		return NLA_U8;
2761 	case DEVLINK_PARAM_TYPE_U16:
2762 		return NLA_U16;
2763 	case DEVLINK_PARAM_TYPE_U32:
2764 		return NLA_U32;
2765 	case DEVLINK_PARAM_TYPE_STRING:
2766 		return NLA_STRING;
2767 	case DEVLINK_PARAM_TYPE_BOOL:
2768 		return NLA_FLAG;
2769 	default:
2770 		return -EINVAL;
2771 	}
2772 }
2773 
2774 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)2775 devlink_nl_param_value_fill_one(struct sk_buff *msg,
2776 				enum devlink_param_type type,
2777 				enum devlink_param_cmode cmode,
2778 				union devlink_param_value val)
2779 {
2780 	struct nlattr *param_value_attr;
2781 
2782 	param_value_attr = nla_nest_start(msg, DEVLINK_ATTR_PARAM_VALUE);
2783 	if (!param_value_attr)
2784 		goto nla_put_failure;
2785 
2786 	if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
2787 		goto value_nest_cancel;
2788 
2789 	switch (type) {
2790 	case DEVLINK_PARAM_TYPE_U8:
2791 		if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8))
2792 			goto value_nest_cancel;
2793 		break;
2794 	case DEVLINK_PARAM_TYPE_U16:
2795 		if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16))
2796 			goto value_nest_cancel;
2797 		break;
2798 	case DEVLINK_PARAM_TYPE_U32:
2799 		if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32))
2800 			goto value_nest_cancel;
2801 		break;
2802 	case DEVLINK_PARAM_TYPE_STRING:
2803 		if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
2804 				   val.vstr))
2805 			goto value_nest_cancel;
2806 		break;
2807 	case DEVLINK_PARAM_TYPE_BOOL:
2808 		if (val.vbool &&
2809 		    nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA))
2810 			goto value_nest_cancel;
2811 		break;
2812 	}
2813 
2814 	nla_nest_end(msg, param_value_attr);
2815 	return 0;
2816 
2817 value_nest_cancel:
2818 	nla_nest_cancel(msg, param_value_attr);
2819 nla_put_failure:
2820 	return -EMSGSIZE;
2821 }
2822 
devlink_nl_param_fill(struct sk_buff * msg,struct devlink * devlink,struct devlink_param_item * param_item,enum devlink_command cmd,u32 portid,u32 seq,int flags)2823 static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
2824 				 struct devlink_param_item *param_item,
2825 				 enum devlink_command cmd,
2826 				 u32 portid, u32 seq, int flags)
2827 {
2828 	union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
2829 	const struct devlink_param *param = param_item->param;
2830 	struct devlink_param_gset_ctx ctx;
2831 	struct nlattr *param_values_list;
2832 	struct nlattr *param_attr;
2833 	int nla_type;
2834 	void *hdr;
2835 	int err;
2836 	int i;
2837 
2838 	/* Get value from driver part to driverinit configuration mode */
2839 	for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
2840 		if (!devlink_param_cmode_is_supported(param, i))
2841 			continue;
2842 		if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
2843 			if (!param_item->driverinit_value_valid)
2844 				return -EOPNOTSUPP;
2845 			param_value[i] = param_item->driverinit_value;
2846 		} else {
2847 			ctx.cmode = i;
2848 			err = devlink_param_get(devlink, param, &ctx);
2849 			if (err)
2850 				return err;
2851 			param_value[i] = ctx.val;
2852 		}
2853 	}
2854 
2855 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
2856 	if (!hdr)
2857 		return -EMSGSIZE;
2858 
2859 	if (devlink_nl_put_handle(msg, devlink))
2860 		goto genlmsg_cancel;
2861 	param_attr = nla_nest_start(msg, DEVLINK_ATTR_PARAM);
2862 	if (!param_attr)
2863 		goto genlmsg_cancel;
2864 	if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name))
2865 		goto param_nest_cancel;
2866 	if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC))
2867 		goto param_nest_cancel;
2868 
2869 	nla_type = devlink_param_type_to_nla_type(param->type);
2870 	if (nla_type < 0)
2871 		goto param_nest_cancel;
2872 	if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type))
2873 		goto param_nest_cancel;
2874 
2875 	param_values_list = nla_nest_start(msg, DEVLINK_ATTR_PARAM_VALUES_LIST);
2876 	if (!param_values_list)
2877 		goto param_nest_cancel;
2878 
2879 	for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
2880 		if (!devlink_param_cmode_is_supported(param, i))
2881 			continue;
2882 		err = devlink_nl_param_value_fill_one(msg, param->type,
2883 						      i, param_value[i]);
2884 		if (err)
2885 			goto values_list_nest_cancel;
2886 	}
2887 
2888 	nla_nest_end(msg, param_values_list);
2889 	nla_nest_end(msg, param_attr);
2890 	genlmsg_end(msg, hdr);
2891 	return 0;
2892 
2893 values_list_nest_cancel:
2894 	nla_nest_end(msg, param_values_list);
2895 param_nest_cancel:
2896 	nla_nest_cancel(msg, param_attr);
2897 genlmsg_cancel:
2898 	genlmsg_cancel(msg, hdr);
2899 	return -EMSGSIZE;
2900 }
2901 
devlink_param_notify(struct devlink * devlink,struct devlink_param_item * param_item,enum devlink_command cmd)2902 static void devlink_param_notify(struct devlink *devlink,
2903 				 struct devlink_param_item *param_item,
2904 				 enum devlink_command cmd)
2905 {
2906 	struct sk_buff *msg;
2907 	int err;
2908 
2909 	WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL);
2910 
2911 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2912 	if (!msg)
2913 		return;
2914 	err = devlink_nl_param_fill(msg, devlink, param_item, cmd, 0, 0, 0);
2915 	if (err) {
2916 		nlmsg_free(msg);
2917 		return;
2918 	}
2919 
2920 	genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
2921 				msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
2922 }
2923 
devlink_nl_cmd_param_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)2924 static int devlink_nl_cmd_param_get_dumpit(struct sk_buff *msg,
2925 					   struct netlink_callback *cb)
2926 {
2927 	struct devlink_param_item *param_item;
2928 	struct devlink *devlink;
2929 	int start = cb->args[0];
2930 	int idx = 0;
2931 	int err;
2932 
2933 	mutex_lock(&devlink_mutex);
2934 	list_for_each_entry(devlink, &devlink_list, list) {
2935 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
2936 			continue;
2937 		mutex_lock(&devlink->lock);
2938 		list_for_each_entry(param_item, &devlink->param_list, list) {
2939 			if (idx < start) {
2940 				idx++;
2941 				continue;
2942 			}
2943 			err = devlink_nl_param_fill(msg, devlink, param_item,
2944 						    DEVLINK_CMD_PARAM_GET,
2945 						    NETLINK_CB(cb->skb).portid,
2946 						    cb->nlh->nlmsg_seq,
2947 						    NLM_F_MULTI);
2948 			if (err) {
2949 				mutex_unlock(&devlink->lock);
2950 				goto out;
2951 			}
2952 			idx++;
2953 		}
2954 		mutex_unlock(&devlink->lock);
2955 	}
2956 out:
2957 	mutex_unlock(&devlink_mutex);
2958 
2959 	cb->args[0] = idx;
2960 	return msg->len;
2961 }
2962 
2963 static int
devlink_param_type_get_from_info(struct genl_info * info,enum devlink_param_type * param_type)2964 devlink_param_type_get_from_info(struct genl_info *info,
2965 				 enum devlink_param_type *param_type)
2966 {
2967 	if (!info->attrs[DEVLINK_ATTR_PARAM_TYPE])
2968 		return -EINVAL;
2969 
2970 	switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) {
2971 	case NLA_U8:
2972 		*param_type = DEVLINK_PARAM_TYPE_U8;
2973 		break;
2974 	case NLA_U16:
2975 		*param_type = DEVLINK_PARAM_TYPE_U16;
2976 		break;
2977 	case NLA_U32:
2978 		*param_type = DEVLINK_PARAM_TYPE_U32;
2979 		break;
2980 	case NLA_STRING:
2981 		*param_type = DEVLINK_PARAM_TYPE_STRING;
2982 		break;
2983 	case NLA_FLAG:
2984 		*param_type = DEVLINK_PARAM_TYPE_BOOL;
2985 		break;
2986 	default:
2987 		return -EINVAL;
2988 	}
2989 
2990 	return 0;
2991 }
2992 
2993 static int
devlink_param_value_get_from_info(const struct devlink_param * param,struct genl_info * info,union devlink_param_value * value)2994 devlink_param_value_get_from_info(const struct devlink_param *param,
2995 				  struct genl_info *info,
2996 				  union devlink_param_value *value)
2997 {
2998 	int len;
2999 
3000 	if (param->type != DEVLINK_PARAM_TYPE_BOOL &&
3001 	    !info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])
3002 		return -EINVAL;
3003 
3004 	switch (param->type) {
3005 	case DEVLINK_PARAM_TYPE_U8:
3006 		value->vu8 = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
3007 		break;
3008 	case DEVLINK_PARAM_TYPE_U16:
3009 		value->vu16 = nla_get_u16(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
3010 		break;
3011 	case DEVLINK_PARAM_TYPE_U32:
3012 		value->vu32 = nla_get_u32(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
3013 		break;
3014 	case DEVLINK_PARAM_TYPE_STRING:
3015 		len = strnlen(nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]),
3016 			      nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]));
3017 		if (len == nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) ||
3018 		    len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
3019 			return -EINVAL;
3020 		strcpy(value->vstr,
3021 		       nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]));
3022 		break;
3023 	case DEVLINK_PARAM_TYPE_BOOL:
3024 		value->vbool = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA] ?
3025 			       true : false;
3026 		break;
3027 	}
3028 	return 0;
3029 }
3030 
3031 static struct devlink_param_item *
devlink_param_get_from_info(struct devlink * devlink,struct genl_info * info)3032 devlink_param_get_from_info(struct devlink *devlink,
3033 			    struct genl_info *info)
3034 {
3035 	char *param_name;
3036 
3037 	if (!info->attrs[DEVLINK_ATTR_PARAM_NAME])
3038 		return NULL;
3039 
3040 	param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]);
3041 	return devlink_param_find_by_name(&devlink->param_list, param_name);
3042 }
3043 
devlink_nl_cmd_param_get_doit(struct sk_buff * skb,struct genl_info * info)3044 static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb,
3045 					 struct genl_info *info)
3046 {
3047 	struct devlink *devlink = info->user_ptr[0];
3048 	struct devlink_param_item *param_item;
3049 	struct sk_buff *msg;
3050 	int err;
3051 
3052 	param_item = devlink_param_get_from_info(devlink, info);
3053 	if (!param_item)
3054 		return -EINVAL;
3055 
3056 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3057 	if (!msg)
3058 		return -ENOMEM;
3059 
3060 	err = devlink_nl_param_fill(msg, devlink, param_item,
3061 				    DEVLINK_CMD_PARAM_GET,
3062 				    info->snd_portid, info->snd_seq, 0);
3063 	if (err) {
3064 		nlmsg_free(msg);
3065 		return err;
3066 	}
3067 
3068 	return genlmsg_reply(msg, info);
3069 }
3070 
devlink_nl_cmd_param_set_doit(struct sk_buff * skb,struct genl_info * info)3071 static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb,
3072 					 struct genl_info *info)
3073 {
3074 	struct devlink *devlink = info->user_ptr[0];
3075 	enum devlink_param_type param_type;
3076 	struct devlink_param_gset_ctx ctx;
3077 	enum devlink_param_cmode cmode;
3078 	struct devlink_param_item *param_item;
3079 	const struct devlink_param *param;
3080 	union devlink_param_value value;
3081 	int err = 0;
3082 
3083 	param_item = devlink_param_get_from_info(devlink, info);
3084 	if (!param_item)
3085 		return -EINVAL;
3086 	param = param_item->param;
3087 	err = devlink_param_type_get_from_info(info, &param_type);
3088 	if (err)
3089 		return err;
3090 	if (param_type != param->type)
3091 		return -EINVAL;
3092 	err = devlink_param_value_get_from_info(param, info, &value);
3093 	if (err)
3094 		return err;
3095 	if (param->validate) {
3096 		err = param->validate(devlink, param->id, value, info->extack);
3097 		if (err)
3098 			return err;
3099 	}
3100 
3101 	if (!info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE])
3102 		return -EINVAL;
3103 	cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
3104 	if (!devlink_param_cmode_is_supported(param, cmode))
3105 		return -EOPNOTSUPP;
3106 
3107 	if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
3108 		if (param->type == DEVLINK_PARAM_TYPE_STRING)
3109 			strcpy(param_item->driverinit_value.vstr, value.vstr);
3110 		else
3111 			param_item->driverinit_value = value;
3112 		param_item->driverinit_value_valid = true;
3113 	} else {
3114 		if (!param->set)
3115 			return -EOPNOTSUPP;
3116 		ctx.val = value;
3117 		ctx.cmode = cmode;
3118 		err = devlink_param_set(devlink, param, &ctx);
3119 		if (err)
3120 			return err;
3121 	}
3122 
3123 	devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW);
3124 	return 0;
3125 }
3126 
devlink_param_register_one(struct devlink * devlink,const struct devlink_param * param)3127 static int devlink_param_register_one(struct devlink *devlink,
3128 				      const struct devlink_param *param)
3129 {
3130 	struct devlink_param_item *param_item;
3131 
3132 	if (devlink_param_find_by_name(&devlink->param_list,
3133 				       param->name))
3134 		return -EEXIST;
3135 
3136 	if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
3137 		WARN_ON(param->get || param->set);
3138 	else
3139 		WARN_ON(!param->get || !param->set);
3140 
3141 	param_item = kzalloc(sizeof(*param_item), GFP_KERNEL);
3142 	if (!param_item)
3143 		return -ENOMEM;
3144 	param_item->param = param;
3145 
3146 	list_add_tail(&param_item->list, &devlink->param_list);
3147 	devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW);
3148 	return 0;
3149 }
3150 
devlink_param_unregister_one(struct devlink * devlink,const struct devlink_param * param)3151 static void devlink_param_unregister_one(struct devlink *devlink,
3152 					 const struct devlink_param *param)
3153 {
3154 	struct devlink_param_item *param_item;
3155 
3156 	param_item = devlink_param_find_by_name(&devlink->param_list,
3157 						param->name);
3158 	WARN_ON(!param_item);
3159 	devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_DEL);
3160 	list_del(&param_item->list);
3161 	kfree(param_item);
3162 }
3163 
devlink_nl_region_snapshot_id_put(struct sk_buff * msg,struct devlink * devlink,struct devlink_snapshot * snapshot)3164 static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg,
3165 					     struct devlink *devlink,
3166 					     struct devlink_snapshot *snapshot)
3167 {
3168 	struct nlattr *snap_attr;
3169 	int err;
3170 
3171 	snap_attr = nla_nest_start(msg, DEVLINK_ATTR_REGION_SNAPSHOT);
3172 	if (!snap_attr)
3173 		return -EINVAL;
3174 
3175 	err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id);
3176 	if (err)
3177 		goto nla_put_failure;
3178 
3179 	nla_nest_end(msg, snap_attr);
3180 	return 0;
3181 
3182 nla_put_failure:
3183 	nla_nest_cancel(msg, snap_attr);
3184 	return err;
3185 }
3186 
devlink_nl_region_snapshots_id_put(struct sk_buff * msg,struct devlink * devlink,struct devlink_region * region)3187 static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg,
3188 					      struct devlink *devlink,
3189 					      struct devlink_region *region)
3190 {
3191 	struct devlink_snapshot *snapshot;
3192 	struct nlattr *snapshots_attr;
3193 	int err;
3194 
3195 	snapshots_attr = nla_nest_start(msg, DEVLINK_ATTR_REGION_SNAPSHOTS);
3196 	if (!snapshots_attr)
3197 		return -EINVAL;
3198 
3199 	list_for_each_entry(snapshot, &region->snapshot_list, list) {
3200 		err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot);
3201 		if (err)
3202 			goto nla_put_failure;
3203 	}
3204 
3205 	nla_nest_end(msg, snapshots_attr);
3206 	return 0;
3207 
3208 nla_put_failure:
3209 	nla_nest_cancel(msg, snapshots_attr);
3210 	return err;
3211 }
3212 
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)3213 static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink,
3214 				  enum devlink_command cmd, u32 portid,
3215 				  u32 seq, int flags,
3216 				  struct devlink_region *region)
3217 {
3218 	void *hdr;
3219 	int err;
3220 
3221 	hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
3222 	if (!hdr)
3223 		return -EMSGSIZE;
3224 
3225 	err = devlink_nl_put_handle(msg, devlink);
3226 	if (err)
3227 		goto nla_put_failure;
3228 
3229 	err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->name);
3230 	if (err)
3231 		goto nla_put_failure;
3232 
3233 	err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
3234 				region->size,
3235 				DEVLINK_ATTR_PAD);
3236 	if (err)
3237 		goto nla_put_failure;
3238 
3239 	err = devlink_nl_region_snapshots_id_put(msg, devlink, region);
3240 	if (err)
3241 		goto nla_put_failure;
3242 
3243 	genlmsg_end(msg, hdr);
3244 	return 0;
3245 
3246 nla_put_failure:
3247 	genlmsg_cancel(msg, hdr);
3248 	return err;
3249 }
3250 
devlink_nl_region_notify(struct devlink_region * region,struct devlink_snapshot * snapshot,enum devlink_command cmd)3251 static void devlink_nl_region_notify(struct devlink_region *region,
3252 				     struct devlink_snapshot *snapshot,
3253 				     enum devlink_command cmd)
3254 {
3255 	struct devlink *devlink = region->devlink;
3256 	struct sk_buff *msg;
3257 	void *hdr;
3258 	int err;
3259 
3260 	WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL);
3261 
3262 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3263 	if (!msg)
3264 		return;
3265 
3266 	hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd);
3267 	if (!hdr)
3268 		goto out_free_msg;
3269 
3270 	err = devlink_nl_put_handle(msg, devlink);
3271 	if (err)
3272 		goto out_cancel_msg;
3273 
3274 	err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME,
3275 			     region->name);
3276 	if (err)
3277 		goto out_cancel_msg;
3278 
3279 	if (snapshot) {
3280 		err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID,
3281 				  snapshot->id);
3282 		if (err)
3283 			goto out_cancel_msg;
3284 	} else {
3285 		err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
3286 					region->size, DEVLINK_ATTR_PAD);
3287 		if (err)
3288 			goto out_cancel_msg;
3289 	}
3290 	genlmsg_end(msg, hdr);
3291 
3292 	genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
3293 				msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
3294 
3295 	return;
3296 
3297 out_cancel_msg:
3298 	genlmsg_cancel(msg, hdr);
3299 out_free_msg:
3300 	nlmsg_free(msg);
3301 }
3302 
devlink_nl_cmd_region_get_doit(struct sk_buff * skb,struct genl_info * info)3303 static int devlink_nl_cmd_region_get_doit(struct sk_buff *skb,
3304 					  struct genl_info *info)
3305 {
3306 	struct devlink *devlink = info->user_ptr[0];
3307 	struct devlink_region *region;
3308 	const char *region_name;
3309 	struct sk_buff *msg;
3310 	int err;
3311 
3312 	if (!info->attrs[DEVLINK_ATTR_REGION_NAME])
3313 		return -EINVAL;
3314 
3315 	region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
3316 	region = devlink_region_get_by_name(devlink, region_name);
3317 	if (!region)
3318 		return -EINVAL;
3319 
3320 	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3321 	if (!msg)
3322 		return -ENOMEM;
3323 
3324 	err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET,
3325 				     info->snd_portid, info->snd_seq, 0,
3326 				     region);
3327 	if (err) {
3328 		nlmsg_free(msg);
3329 		return err;
3330 	}
3331 
3332 	return genlmsg_reply(msg, info);
3333 }
3334 
devlink_nl_cmd_region_get_dumpit(struct sk_buff * msg,struct netlink_callback * cb)3335 static int devlink_nl_cmd_region_get_dumpit(struct sk_buff *msg,
3336 					    struct netlink_callback *cb)
3337 {
3338 	struct devlink_region *region;
3339 	struct devlink *devlink;
3340 	int start = cb->args[0];
3341 	int idx = 0;
3342 	int err;
3343 
3344 	mutex_lock(&devlink_mutex);
3345 	list_for_each_entry(devlink, &devlink_list, list) {
3346 		if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3347 			continue;
3348 
3349 		mutex_lock(&devlink->lock);
3350 		list_for_each_entry(region, &devlink->region_list, list) {
3351 			if (idx < start) {
3352 				idx++;
3353 				continue;
3354 			}
3355 			err = devlink_nl_region_fill(msg, devlink,
3356 						     DEVLINK_CMD_REGION_GET,
3357 						     NETLINK_CB(cb->skb).portid,
3358 						     cb->nlh->nlmsg_seq,
3359 						     NLM_F_MULTI, region);
3360 			if (err) {
3361 				mutex_unlock(&devlink->lock);
3362 				goto out;
3363 			}
3364 			idx++;
3365 		}
3366 		mutex_unlock(&devlink->lock);
3367 	}
3368 out:
3369 	mutex_unlock(&devlink_mutex);
3370 	cb->args[0] = idx;
3371 	return msg->len;
3372 }
3373 
devlink_nl_cmd_region_del(struct sk_buff * skb,struct genl_info * info)3374 static int devlink_nl_cmd_region_del(struct sk_buff *skb,
3375 				     struct genl_info *info)
3376 {
3377 	struct devlink *devlink = info->user_ptr[0];
3378 	struct devlink_snapshot *snapshot;
3379 	struct devlink_region *region;
3380 	const char *region_name;
3381 	u32 snapshot_id;
3382 
3383 	if (!info->attrs[DEVLINK_ATTR_REGION_NAME] ||
3384 	    !info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID])
3385 		return -EINVAL;
3386 
3387 	region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
3388 	snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
3389 
3390 	region = devlink_region_get_by_name(devlink, region_name);
3391 	if (!region)
3392 		return -EINVAL;
3393 
3394 	snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
3395 	if (!snapshot)
3396 		return -EINVAL;
3397 
3398 	devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL);
3399 	devlink_region_snapshot_del(snapshot);
3400 	return 0;
3401 }
3402 
devlink_nl_cmd_region_read_chunk_fill(struct sk_buff * msg,struct devlink * devlink,u8 * chunk,u32 chunk_size,u64 addr)3403 static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg,
3404 						 struct devlink *devlink,
3405 						 u8 *chunk, u32 chunk_size,
3406 						 u64 addr)
3407 {
3408 	struct nlattr *chunk_attr;
3409 	int err;
3410 
3411 	chunk_attr = nla_nest_start(msg, DEVLINK_ATTR_REGION_CHUNK);
3412 	if (!chunk_attr)
3413 		return -EINVAL;
3414 
3415 	err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk);
3416 	if (err)
3417 		goto nla_put_failure;
3418 
3419 	err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr,
3420 				DEVLINK_ATTR_PAD);
3421 	if (err)
3422 		goto nla_put_failure;
3423 
3424 	nla_nest_end(msg, chunk_attr);
3425 	return 0;
3426 
3427 nla_put_failure:
3428 	nla_nest_cancel(msg, chunk_attr);
3429 	return err;
3430 }
3431 
3432 #define DEVLINK_REGION_READ_CHUNK_SIZE 256
3433 
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)3434 static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb,
3435 						struct devlink *devlink,
3436 						struct devlink_region *region,
3437 						struct nlattr **attrs,
3438 						u64 start_offset,
3439 						u64 end_offset,
3440 						bool dump,
3441 						u64 *new_offset)
3442 {
3443 	struct devlink_snapshot *snapshot;
3444 	u64 curr_offset = start_offset;
3445 	u32 snapshot_id;
3446 	int err = 0;
3447 
3448 	*new_offset = start_offset;
3449 
3450 	snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
3451 	snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
3452 	if (!snapshot)
3453 		return -EINVAL;
3454 
3455 	if (end_offset > snapshot->data_len || dump)
3456 		end_offset = snapshot->data_len;
3457 
3458 	while (curr_offset < end_offset) {
3459 		u32 data_size;
3460 		u8 *data;
3461 
3462 		if (end_offset - curr_offset < DEVLINK_REGION_READ_CHUNK_SIZE)
3463 			data_size = end_offset - curr_offset;
3464 		else
3465 			data_size = DEVLINK_REGION_READ_CHUNK_SIZE;
3466 
3467 		data = &snapshot->data[curr_offset];
3468 		err = devlink_nl_cmd_region_read_chunk_fill(skb, devlink,
3469 							    data, data_size,
3470 							    curr_offset);
3471 		if (err)
3472 			break;
3473 
3474 		curr_offset += data_size;
3475 	}
3476 	*new_offset = curr_offset;
3477 
3478 	return err;
3479 }
3480 
devlink_nl_cmd_region_read_dumpit(struct sk_buff * skb,struct netlink_callback * cb)3481 static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
3482 					     struct netlink_callback *cb)
3483 {
3484 	u64 ret_offset, start_offset, end_offset = 0;
3485 	struct nlattr *attrs[DEVLINK_ATTR_MAX + 1];
3486 	const struct genl_ops *ops = cb->data;
3487 	struct devlink_region *region;
3488 	struct nlattr *chunks_attr;
3489 	const char *region_name;
3490 	struct devlink *devlink;
3491 	bool dump = true;
3492 	void *hdr;
3493 	int err;
3494 
3495 	start_offset = *((u64 *)&cb->args[0]);
3496 
3497 	err = nlmsg_parse(cb->nlh, GENL_HDRLEN + devlink_nl_family.hdrsize,
3498 			  attrs, DEVLINK_ATTR_MAX, ops->policy, NULL);
3499 	if (err)
3500 		goto out;
3501 
3502 	devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
3503 	if (IS_ERR(devlink))
3504 		goto out;
3505 
3506 	mutex_lock(&devlink_mutex);
3507 	mutex_lock(&devlink->lock);
3508 
3509 	if (!attrs[DEVLINK_ATTR_REGION_NAME] ||
3510 	    !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID])
3511 		goto out_unlock;
3512 
3513 	region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]);
3514 	region = devlink_region_get_by_name(devlink, region_name);
3515 	if (!region)
3516 		goto out_unlock;
3517 
3518 	hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
3519 			  &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
3520 			  DEVLINK_CMD_REGION_READ);
3521 	if (!hdr)
3522 		goto out_unlock;
3523 
3524 	err = devlink_nl_put_handle(skb, devlink);
3525 	if (err)
3526 		goto nla_put_failure;
3527 
3528 	err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
3529 	if (err)
3530 		goto nla_put_failure;
3531 
3532 	chunks_attr = nla_nest_start(skb, DEVLINK_ATTR_REGION_CHUNKS);
3533 	if (!chunks_attr)
3534 		goto nla_put_failure;
3535 
3536 	if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] &&
3537 	    attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) {
3538 		if (!start_offset)
3539 			start_offset =
3540 				nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
3541 
3542 		end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
3543 		end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]);
3544 		dump = false;
3545 	}
3546 
3547 	err = devlink_nl_region_read_snapshot_fill(skb, devlink,
3548 						   region, attrs,
3549 						   start_offset,
3550 						   end_offset, dump,
3551 						   &ret_offset);
3552 
3553 	if (err && err != -EMSGSIZE)
3554 		goto nla_put_failure;
3555 
3556 	/* Check if there was any progress done to prevent infinite loop */
3557 	if (ret_offset == start_offset)
3558 		goto nla_put_failure;
3559 
3560 	*((u64 *)&cb->args[0]) = ret_offset;
3561 
3562 	nla_nest_end(skb, chunks_attr);
3563 	genlmsg_end(skb, hdr);
3564 	mutex_unlock(&devlink->lock);
3565 	mutex_unlock(&devlink_mutex);
3566 
3567 	return skb->len;
3568 
3569 nla_put_failure:
3570 	genlmsg_cancel(skb, hdr);
3571 out_unlock:
3572 	mutex_unlock(&devlink->lock);
3573 	mutex_unlock(&devlink_mutex);
3574 out:
3575 	return 0;
3576 }
3577 
3578 static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
3579 	[DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
3580 	[DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
3581 	[DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 },
3582 	[DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 },
3583 	[DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 },
3584 	[DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 },
3585 	[DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 },
3586 	[DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 },
3587 	[DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 },
3588 	[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 },
3589 	[DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 },
3590 	[DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 },
3591 	[DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 },
3592 	[DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 },
3593 	[DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 },
3594 	[DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING },
3595 	[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 },
3596 	[DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64},
3597 	[DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64},
3598 	[DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING },
3599 	[DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 },
3600 	[DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 },
3601 	[DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING },
3602 	[DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 },
3603 };
3604 
3605 static const struct genl_ops devlink_nl_ops[] = {
3606 	{
3607 		.cmd = DEVLINK_CMD_GET,
3608 		.doit = devlink_nl_cmd_get_doit,
3609 		.dumpit = devlink_nl_cmd_get_dumpit,
3610 		.policy = devlink_nl_policy,
3611 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
3612 		/* can be retrieved by unprivileged users */
3613 	},
3614 	{
3615 		.cmd = DEVLINK_CMD_PORT_GET,
3616 		.doit = devlink_nl_cmd_port_get_doit,
3617 		.dumpit = devlink_nl_cmd_port_get_dumpit,
3618 		.policy = devlink_nl_policy,
3619 		.internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
3620 		/* can be retrieved by unprivileged users */
3621 	},
3622 	{
3623 		.cmd = DEVLINK_CMD_PORT_SET,
3624 		.doit = devlink_nl_cmd_port_set_doit,
3625 		.policy = devlink_nl_policy,
3626 		.flags = GENL_ADMIN_PERM,
3627 		.internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
3628 	},
3629 	{
3630 		.cmd = DEVLINK_CMD_PORT_SPLIT,
3631 		.doit = devlink_nl_cmd_port_split_doit,
3632 		.policy = devlink_nl_policy,
3633 		.flags = GENL_ADMIN_PERM,
3634 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
3635 				  DEVLINK_NL_FLAG_NO_LOCK,
3636 	},
3637 	{
3638 		.cmd = DEVLINK_CMD_PORT_UNSPLIT,
3639 		.doit = devlink_nl_cmd_port_unsplit_doit,
3640 		.policy = devlink_nl_policy,
3641 		.flags = GENL_ADMIN_PERM,
3642 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
3643 				  DEVLINK_NL_FLAG_NO_LOCK,
3644 	},
3645 	{
3646 		.cmd = DEVLINK_CMD_SB_GET,
3647 		.doit = devlink_nl_cmd_sb_get_doit,
3648 		.dumpit = devlink_nl_cmd_sb_get_dumpit,
3649 		.policy = devlink_nl_policy,
3650 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
3651 				  DEVLINK_NL_FLAG_NEED_SB,
3652 		/* can be retrieved by unprivileged users */
3653 	},
3654 	{
3655 		.cmd = DEVLINK_CMD_SB_POOL_GET,
3656 		.doit = devlink_nl_cmd_sb_pool_get_doit,
3657 		.dumpit = devlink_nl_cmd_sb_pool_get_dumpit,
3658 		.policy = devlink_nl_policy,
3659 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
3660 				  DEVLINK_NL_FLAG_NEED_SB,
3661 		/* can be retrieved by unprivileged users */
3662 	},
3663 	{
3664 		.cmd = DEVLINK_CMD_SB_POOL_SET,
3665 		.doit = devlink_nl_cmd_sb_pool_set_doit,
3666 		.policy = devlink_nl_policy,
3667 		.flags = GENL_ADMIN_PERM,
3668 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
3669 				  DEVLINK_NL_FLAG_NEED_SB,
3670 	},
3671 	{
3672 		.cmd = DEVLINK_CMD_SB_PORT_POOL_GET,
3673 		.doit = devlink_nl_cmd_sb_port_pool_get_doit,
3674 		.dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit,
3675 		.policy = devlink_nl_policy,
3676 		.internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
3677 				  DEVLINK_NL_FLAG_NEED_SB,
3678 		/* can be retrieved by unprivileged users */
3679 	},
3680 	{
3681 		.cmd = DEVLINK_CMD_SB_PORT_POOL_SET,
3682 		.doit = devlink_nl_cmd_sb_port_pool_set_doit,
3683 		.policy = devlink_nl_policy,
3684 		.flags = GENL_ADMIN_PERM,
3685 		.internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
3686 				  DEVLINK_NL_FLAG_NEED_SB,
3687 	},
3688 	{
3689 		.cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET,
3690 		.doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit,
3691 		.dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit,
3692 		.policy = devlink_nl_policy,
3693 		.internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
3694 				  DEVLINK_NL_FLAG_NEED_SB,
3695 		/* can be retrieved by unprivileged users */
3696 	},
3697 	{
3698 		.cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET,
3699 		.doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit,
3700 		.policy = devlink_nl_policy,
3701 		.flags = GENL_ADMIN_PERM,
3702 		.internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
3703 				  DEVLINK_NL_FLAG_NEED_SB,
3704 	},
3705 	{
3706 		.cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT,
3707 		.doit = devlink_nl_cmd_sb_occ_snapshot_doit,
3708 		.policy = devlink_nl_policy,
3709 		.flags = GENL_ADMIN_PERM,
3710 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
3711 				  DEVLINK_NL_FLAG_NEED_SB,
3712 	},
3713 	{
3714 		.cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR,
3715 		.doit = devlink_nl_cmd_sb_occ_max_clear_doit,
3716 		.policy = devlink_nl_policy,
3717 		.flags = GENL_ADMIN_PERM,
3718 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
3719 				  DEVLINK_NL_FLAG_NEED_SB,
3720 	},
3721 	{
3722 		.cmd = DEVLINK_CMD_ESWITCH_GET,
3723 		.doit = devlink_nl_cmd_eswitch_get_doit,
3724 		.policy = devlink_nl_policy,
3725 		.flags = GENL_ADMIN_PERM,
3726 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
3727 	},
3728 	{
3729 		.cmd = DEVLINK_CMD_ESWITCH_SET,
3730 		.doit = devlink_nl_cmd_eswitch_set_doit,
3731 		.policy = devlink_nl_policy,
3732 		.flags = GENL_ADMIN_PERM,
3733 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
3734 				  DEVLINK_NL_FLAG_NO_LOCK,
3735 	},
3736 	{
3737 		.cmd = DEVLINK_CMD_DPIPE_TABLE_GET,
3738 		.doit = devlink_nl_cmd_dpipe_table_get,
3739 		.policy = devlink_nl_policy,
3740 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
3741 		/* can be retrieved by unprivileged users */
3742 	},
3743 	{
3744 		.cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET,
3745 		.doit = devlink_nl_cmd_dpipe_entries_get,
3746 		.policy = devlink_nl_policy,
3747 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
3748 		/* can be retrieved by unprivileged users */
3749 	},
3750 	{
3751 		.cmd = DEVLINK_CMD_DPIPE_HEADERS_GET,
3752 		.doit = devlink_nl_cmd_dpipe_headers_get,
3753 		.policy = devlink_nl_policy,
3754 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
3755 		/* can be retrieved by unprivileged users */
3756 	},
3757 	{
3758 		.cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET,
3759 		.doit = devlink_nl_cmd_dpipe_table_counters_set,
3760 		.policy = devlink_nl_policy,
3761 		.flags = GENL_ADMIN_PERM,
3762 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
3763 	},
3764 	{
3765 		.cmd = DEVLINK_CMD_RESOURCE_SET,
3766 		.doit = devlink_nl_cmd_resource_set,
3767 		.policy = devlink_nl_policy,
3768 		.flags = GENL_ADMIN_PERM,
3769 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
3770 	},
3771 	{
3772 		.cmd = DEVLINK_CMD_RESOURCE_DUMP,
3773 		.doit = devlink_nl_cmd_resource_dump,
3774 		.policy = devlink_nl_policy,
3775 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
3776 		/* can be retrieved by unprivileged users */
3777 	},
3778 	{
3779 		.cmd = DEVLINK_CMD_RELOAD,
3780 		.doit = devlink_nl_cmd_reload,
3781 		.policy = devlink_nl_policy,
3782 		.flags = GENL_ADMIN_PERM,
3783 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
3784 				  DEVLINK_NL_FLAG_NO_LOCK,
3785 	},
3786 	{
3787 		.cmd = DEVLINK_CMD_PARAM_GET,
3788 		.doit = devlink_nl_cmd_param_get_doit,
3789 		.dumpit = devlink_nl_cmd_param_get_dumpit,
3790 		.policy = devlink_nl_policy,
3791 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
3792 		/* can be retrieved by unprivileged users */
3793 	},
3794 	{
3795 		.cmd = DEVLINK_CMD_PARAM_SET,
3796 		.doit = devlink_nl_cmd_param_set_doit,
3797 		.policy = devlink_nl_policy,
3798 		.flags = GENL_ADMIN_PERM,
3799 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
3800 	},
3801 	{
3802 		.cmd = DEVLINK_CMD_REGION_GET,
3803 		.doit = devlink_nl_cmd_region_get_doit,
3804 		.dumpit = devlink_nl_cmd_region_get_dumpit,
3805 		.policy = devlink_nl_policy,
3806 		.flags = GENL_ADMIN_PERM,
3807 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
3808 	},
3809 	{
3810 		.cmd = DEVLINK_CMD_REGION_DEL,
3811 		.doit = devlink_nl_cmd_region_del,
3812 		.policy = devlink_nl_policy,
3813 		.flags = GENL_ADMIN_PERM,
3814 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
3815 	},
3816 	{
3817 		.cmd = DEVLINK_CMD_REGION_READ,
3818 		.dumpit = devlink_nl_cmd_region_read_dumpit,
3819 		.policy = devlink_nl_policy,
3820 		.flags = GENL_ADMIN_PERM,
3821 		.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
3822 	},
3823 };
3824 
3825 static struct genl_family devlink_nl_family __ro_after_init = {
3826 	.name		= DEVLINK_GENL_NAME,
3827 	.version	= DEVLINK_GENL_VERSION,
3828 	.maxattr	= DEVLINK_ATTR_MAX,
3829 	.netnsok	= true,
3830 	.pre_doit	= devlink_nl_pre_doit,
3831 	.post_doit	= devlink_nl_post_doit,
3832 	.module		= THIS_MODULE,
3833 	.ops		= devlink_nl_ops,
3834 	.n_ops		= ARRAY_SIZE(devlink_nl_ops),
3835 	.mcgrps		= devlink_nl_mcgrps,
3836 	.n_mcgrps	= ARRAY_SIZE(devlink_nl_mcgrps),
3837 };
3838 
3839 /**
3840  *	devlink_alloc - Allocate new devlink instance resources
3841  *
3842  *	@ops: ops
3843  *	@priv_size: size of user private data
3844  *
3845  *	Allocate new devlink instance resources, including devlink index
3846  *	and name.
3847  */
devlink_alloc(const struct devlink_ops * ops,size_t priv_size)3848 struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
3849 {
3850 	struct devlink *devlink;
3851 
3852 	devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL);
3853 	if (!devlink)
3854 		return NULL;
3855 	devlink->ops = ops;
3856 	devlink_net_set(devlink, &init_net);
3857 	INIT_LIST_HEAD(&devlink->port_list);
3858 	INIT_LIST_HEAD(&devlink->sb_list);
3859 	INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list);
3860 	INIT_LIST_HEAD(&devlink->resource_list);
3861 	INIT_LIST_HEAD(&devlink->param_list);
3862 	INIT_LIST_HEAD(&devlink->region_list);
3863 	mutex_init(&devlink->lock);
3864 	return devlink;
3865 }
3866 EXPORT_SYMBOL_GPL(devlink_alloc);
3867 
3868 /**
3869  *	devlink_register - Register devlink instance
3870  *
3871  *	@devlink: devlink
3872  */
devlink_register(struct devlink * devlink,struct device * dev)3873 int devlink_register(struct devlink *devlink, struct device *dev)
3874 {
3875 	mutex_lock(&devlink_mutex);
3876 	devlink->dev = dev;
3877 	list_add_tail(&devlink->list, &devlink_list);
3878 	devlink_notify(devlink, DEVLINK_CMD_NEW);
3879 	mutex_unlock(&devlink_mutex);
3880 	return 0;
3881 }
3882 EXPORT_SYMBOL_GPL(devlink_register);
3883 
3884 /**
3885  *	devlink_unregister - Unregister devlink instance
3886  *
3887  *	@devlink: devlink
3888  */
devlink_unregister(struct devlink * devlink)3889 void devlink_unregister(struct devlink *devlink)
3890 {
3891 	mutex_lock(&devlink_mutex);
3892 	devlink_notify(devlink, DEVLINK_CMD_DEL);
3893 	list_del(&devlink->list);
3894 	mutex_unlock(&devlink_mutex);
3895 }
3896 EXPORT_SYMBOL_GPL(devlink_unregister);
3897 
3898 /**
3899  *	devlink_free - Free devlink instance resources
3900  *
3901  *	@devlink: devlink
3902  */
devlink_free(struct devlink * devlink)3903 void devlink_free(struct devlink *devlink)
3904 {
3905 	kfree(devlink);
3906 }
3907 EXPORT_SYMBOL_GPL(devlink_free);
3908 
3909 /**
3910  *	devlink_port_register - Register devlink port
3911  *
3912  *	@devlink: devlink
3913  *	@devlink_port: devlink port
3914  *	@port_index
3915  *
3916  *	Register devlink port with provided port index. User can use
3917  *	any indexing, even hw-related one. devlink_port structure
3918  *	is convenient to be embedded inside user driver private structure.
3919  *	Note that the caller should take care of zeroing the devlink_port
3920  *	structure.
3921  */
devlink_port_register(struct devlink * devlink,struct devlink_port * devlink_port,unsigned int port_index)3922 int devlink_port_register(struct devlink *devlink,
3923 			  struct devlink_port *devlink_port,
3924 			  unsigned int port_index)
3925 {
3926 	mutex_lock(&devlink->lock);
3927 	if (devlink_port_index_exists(devlink, port_index)) {
3928 		mutex_unlock(&devlink->lock);
3929 		return -EEXIST;
3930 	}
3931 	devlink_port->devlink = devlink;
3932 	devlink_port->index = port_index;
3933 	devlink_port->registered = true;
3934 	list_add_tail(&devlink_port->list, &devlink->port_list);
3935 	mutex_unlock(&devlink->lock);
3936 	devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
3937 	return 0;
3938 }
3939 EXPORT_SYMBOL_GPL(devlink_port_register);
3940 
3941 /**
3942  *	devlink_port_unregister - Unregister devlink port
3943  *
3944  *	@devlink_port: devlink port
3945  */
devlink_port_unregister(struct devlink_port * devlink_port)3946 void devlink_port_unregister(struct devlink_port *devlink_port)
3947 {
3948 	struct devlink *devlink = devlink_port->devlink;
3949 
3950 	devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
3951 	mutex_lock(&devlink->lock);
3952 	list_del(&devlink_port->list);
3953 	mutex_unlock(&devlink->lock);
3954 }
3955 EXPORT_SYMBOL_GPL(devlink_port_unregister);
3956 
__devlink_port_type_set(struct devlink_port * devlink_port,enum devlink_port_type type,void * type_dev)3957 static void __devlink_port_type_set(struct devlink_port *devlink_port,
3958 				    enum devlink_port_type type,
3959 				    void *type_dev)
3960 {
3961 	devlink_port->type = type;
3962 	devlink_port->type_dev = type_dev;
3963 	devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
3964 }
3965 
3966 /**
3967  *	devlink_port_type_eth_set - Set port type to Ethernet
3968  *
3969  *	@devlink_port: devlink port
3970  *	@netdev: related netdevice
3971  */
devlink_port_type_eth_set(struct devlink_port * devlink_port,struct net_device * netdev)3972 void devlink_port_type_eth_set(struct devlink_port *devlink_port,
3973 			       struct net_device *netdev)
3974 {
3975 	return __devlink_port_type_set(devlink_port,
3976 				       DEVLINK_PORT_TYPE_ETH, netdev);
3977 }
3978 EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
3979 
3980 /**
3981  *	devlink_port_type_ib_set - Set port type to InfiniBand
3982  *
3983  *	@devlink_port: devlink port
3984  *	@ibdev: related IB device
3985  */
devlink_port_type_ib_set(struct devlink_port * devlink_port,struct ib_device * ibdev)3986 void devlink_port_type_ib_set(struct devlink_port *devlink_port,
3987 			      struct ib_device *ibdev)
3988 {
3989 	return __devlink_port_type_set(devlink_port,
3990 				       DEVLINK_PORT_TYPE_IB, ibdev);
3991 }
3992 EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
3993 
3994 /**
3995  *	devlink_port_type_clear - Clear port type
3996  *
3997  *	@devlink_port: devlink port
3998  */
devlink_port_type_clear(struct devlink_port * devlink_port)3999 void devlink_port_type_clear(struct devlink_port *devlink_port)
4000 {
4001 	return __devlink_port_type_set(devlink_port,
4002 				       DEVLINK_PORT_TYPE_NOTSET, NULL);
4003 }
4004 EXPORT_SYMBOL_GPL(devlink_port_type_clear);
4005 
4006 /**
4007  *	devlink_port_attrs_set - Set port attributes
4008  *
4009  *	@devlink_port: devlink port
4010  *	@flavour: flavour of the port
4011  *	@port_number: number of the port that is facing user, for example
4012  *	              the front panel port number
4013  *	@split: indicates if this is split port
4014  *	@split_subport_number: if the port is split, this is the number
4015  *	                       of subport.
4016  */
devlink_port_attrs_set(struct devlink_port * devlink_port,enum devlink_port_flavour flavour,u32 port_number,bool split,u32 split_subport_number)4017 void devlink_port_attrs_set(struct devlink_port *devlink_port,
4018 			    enum devlink_port_flavour flavour,
4019 			    u32 port_number, bool split,
4020 			    u32 split_subport_number)
4021 {
4022 	struct devlink_port_attrs *attrs = &devlink_port->attrs;
4023 
4024 	attrs->set = true;
4025 	attrs->flavour = flavour;
4026 	attrs->port_number = port_number;
4027 	attrs->split = split;
4028 	attrs->split_subport_number = split_subport_number;
4029 	devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
4030 }
4031 EXPORT_SYMBOL_GPL(devlink_port_attrs_set);
4032 
devlink_port_get_phys_port_name(struct devlink_port * devlink_port,char * name,size_t len)4033 int devlink_port_get_phys_port_name(struct devlink_port *devlink_port,
4034 				    char *name, size_t len)
4035 {
4036 	struct devlink_port_attrs *attrs = &devlink_port->attrs;
4037 	int n = 0;
4038 
4039 	if (!attrs->set)
4040 		return -EOPNOTSUPP;
4041 
4042 	switch (attrs->flavour) {
4043 	case DEVLINK_PORT_FLAVOUR_PHYSICAL:
4044 		if (!attrs->split)
4045 			n = snprintf(name, len, "p%u", attrs->port_number);
4046 		else
4047 			n = snprintf(name, len, "p%us%u", attrs->port_number,
4048 				     attrs->split_subport_number);
4049 		break;
4050 	case DEVLINK_PORT_FLAVOUR_CPU:
4051 	case DEVLINK_PORT_FLAVOUR_DSA:
4052 		/* As CPU and DSA ports do not have a netdevice associated
4053 		 * case should not ever happen.
4054 		 */
4055 		WARN_ON(1);
4056 		return -EINVAL;
4057 	}
4058 
4059 	if (n >= len)
4060 		return -EINVAL;
4061 
4062 	return 0;
4063 }
4064 EXPORT_SYMBOL_GPL(devlink_port_get_phys_port_name);
4065 
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)4066 int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
4067 			u32 size, u16 ingress_pools_count,
4068 			u16 egress_pools_count, u16 ingress_tc_count,
4069 			u16 egress_tc_count)
4070 {
4071 	struct devlink_sb *devlink_sb;
4072 	int err = 0;
4073 
4074 	mutex_lock(&devlink->lock);
4075 	if (devlink_sb_index_exists(devlink, sb_index)) {
4076 		err = -EEXIST;
4077 		goto unlock;
4078 	}
4079 
4080 	devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL);
4081 	if (!devlink_sb) {
4082 		err = -ENOMEM;
4083 		goto unlock;
4084 	}
4085 	devlink_sb->index = sb_index;
4086 	devlink_sb->size = size;
4087 	devlink_sb->ingress_pools_count = ingress_pools_count;
4088 	devlink_sb->egress_pools_count = egress_pools_count;
4089 	devlink_sb->ingress_tc_count = ingress_tc_count;
4090 	devlink_sb->egress_tc_count = egress_tc_count;
4091 	list_add_tail(&devlink_sb->list, &devlink->sb_list);
4092 unlock:
4093 	mutex_unlock(&devlink->lock);
4094 	return err;
4095 }
4096 EXPORT_SYMBOL_GPL(devlink_sb_register);
4097 
devlink_sb_unregister(struct devlink * devlink,unsigned int sb_index)4098 void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index)
4099 {
4100 	struct devlink_sb *devlink_sb;
4101 
4102 	mutex_lock(&devlink->lock);
4103 	devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
4104 	WARN_ON(!devlink_sb);
4105 	list_del(&devlink_sb->list);
4106 	mutex_unlock(&devlink->lock);
4107 	kfree(devlink_sb);
4108 }
4109 EXPORT_SYMBOL_GPL(devlink_sb_unregister);
4110 
4111 /**
4112  *	devlink_dpipe_headers_register - register dpipe headers
4113  *
4114  *	@devlink: devlink
4115  *	@dpipe_headers: dpipe header array
4116  *
4117  *	Register the headers supported by hardware.
4118  */
devlink_dpipe_headers_register(struct devlink * devlink,struct devlink_dpipe_headers * dpipe_headers)4119 int devlink_dpipe_headers_register(struct devlink *devlink,
4120 				   struct devlink_dpipe_headers *dpipe_headers)
4121 {
4122 	mutex_lock(&devlink->lock);
4123 	devlink->dpipe_headers = dpipe_headers;
4124 	mutex_unlock(&devlink->lock);
4125 	return 0;
4126 }
4127 EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register);
4128 
4129 /**
4130  *	devlink_dpipe_headers_unregister - unregister dpipe headers
4131  *
4132  *	@devlink: devlink
4133  *
4134  *	Unregister the headers supported by hardware.
4135  */
devlink_dpipe_headers_unregister(struct devlink * devlink)4136 void devlink_dpipe_headers_unregister(struct devlink *devlink)
4137 {
4138 	mutex_lock(&devlink->lock);
4139 	devlink->dpipe_headers = NULL;
4140 	mutex_unlock(&devlink->lock);
4141 }
4142 EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister);
4143 
4144 /**
4145  *	devlink_dpipe_table_counter_enabled - check if counter allocation
4146  *					      required
4147  *	@devlink: devlink
4148  *	@table_name: tables name
4149  *
4150  *	Used by driver to check if counter allocation is required.
4151  *	After counter allocation is turned on the table entries
4152  *	are updated to include counter statistics.
4153  *
4154  *	After that point on the driver must respect the counter
4155  *	state so that each entry added to the table is added
4156  *	with a counter.
4157  */
devlink_dpipe_table_counter_enabled(struct devlink * devlink,const char * table_name)4158 bool devlink_dpipe_table_counter_enabled(struct devlink *devlink,
4159 					 const char *table_name)
4160 {
4161 	struct devlink_dpipe_table *table;
4162 	bool enabled;
4163 
4164 	rcu_read_lock();
4165 	table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
4166 					 table_name);
4167 	enabled = false;
4168 	if (table)
4169 		enabled = table->counters_enabled;
4170 	rcu_read_unlock();
4171 	return enabled;
4172 }
4173 EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled);
4174 
4175 /**
4176  *	devlink_dpipe_table_register - register dpipe table
4177  *
4178  *	@devlink: devlink
4179  *	@table_name: table name
4180  *	@table_ops: table ops
4181  *	@priv: priv
4182  *	@counter_control_extern: external control for counters
4183  */
devlink_dpipe_table_register(struct devlink * devlink,const char * table_name,struct devlink_dpipe_table_ops * table_ops,void * priv,bool counter_control_extern)4184 int devlink_dpipe_table_register(struct devlink *devlink,
4185 				 const char *table_name,
4186 				 struct devlink_dpipe_table_ops *table_ops,
4187 				 void *priv, bool counter_control_extern)
4188 {
4189 	struct devlink_dpipe_table *table;
4190 
4191 	if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name))
4192 		return -EEXIST;
4193 
4194 	if (WARN_ON(!table_ops->size_get))
4195 		return -EINVAL;
4196 
4197 	table = kzalloc(sizeof(*table), GFP_KERNEL);
4198 	if (!table)
4199 		return -ENOMEM;
4200 
4201 	table->name = table_name;
4202 	table->table_ops = table_ops;
4203 	table->priv = priv;
4204 	table->counter_control_extern = counter_control_extern;
4205 
4206 	mutex_lock(&devlink->lock);
4207 	list_add_tail_rcu(&table->list, &devlink->dpipe_table_list);
4208 	mutex_unlock(&devlink->lock);
4209 	return 0;
4210 }
4211 EXPORT_SYMBOL_GPL(devlink_dpipe_table_register);
4212 
4213 /**
4214  *	devlink_dpipe_table_unregister - unregister dpipe table
4215  *
4216  *	@devlink: devlink
4217  *	@table_name: table name
4218  */
devlink_dpipe_table_unregister(struct devlink * devlink,const char * table_name)4219 void devlink_dpipe_table_unregister(struct devlink *devlink,
4220 				    const char *table_name)
4221 {
4222 	struct devlink_dpipe_table *table;
4223 
4224 	mutex_lock(&devlink->lock);
4225 	table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
4226 					 table_name);
4227 	if (!table)
4228 		goto unlock;
4229 	list_del_rcu(&table->list);
4230 	mutex_unlock(&devlink->lock);
4231 	kfree_rcu(table, rcu);
4232 	return;
4233 unlock:
4234 	mutex_unlock(&devlink->lock);
4235 }
4236 EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister);
4237 
4238 /**
4239  *	devlink_resource_register - devlink resource register
4240  *
4241  *	@devlink: devlink
4242  *	@resource_name: resource's name
4243  *	@top_hierarchy: top hierarchy
4244  *	@reload_required: reload is required for new configuration to
4245  *			  apply
4246  *	@resource_size: resource's size
4247  *	@resource_id: resource's id
4248  *	@parent_reosurce_id: resource's parent id
4249  *	@size params: size parameters
4250  */
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)4251 int devlink_resource_register(struct devlink *devlink,
4252 			      const char *resource_name,
4253 			      u64 resource_size,
4254 			      u64 resource_id,
4255 			      u64 parent_resource_id,
4256 			      const struct devlink_resource_size_params *size_params)
4257 {
4258 	struct devlink_resource *resource;
4259 	struct list_head *resource_list;
4260 	bool top_hierarchy;
4261 	int err = 0;
4262 
4263 	top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP;
4264 
4265 	mutex_lock(&devlink->lock);
4266 	resource = devlink_resource_find(devlink, NULL, resource_id);
4267 	if (resource) {
4268 		err = -EINVAL;
4269 		goto out;
4270 	}
4271 
4272 	resource = kzalloc(sizeof(*resource), GFP_KERNEL);
4273 	if (!resource) {
4274 		err = -ENOMEM;
4275 		goto out;
4276 	}
4277 
4278 	if (top_hierarchy) {
4279 		resource_list = &devlink->resource_list;
4280 	} else {
4281 		struct devlink_resource *parent_resource;
4282 
4283 		parent_resource = devlink_resource_find(devlink, NULL,
4284 							parent_resource_id);
4285 		if (parent_resource) {
4286 			resource_list = &parent_resource->resource_list;
4287 			resource->parent = parent_resource;
4288 		} else {
4289 			kfree(resource);
4290 			err = -EINVAL;
4291 			goto out;
4292 		}
4293 	}
4294 
4295 	resource->name = resource_name;
4296 	resource->size = resource_size;
4297 	resource->size_new = resource_size;
4298 	resource->id = resource_id;
4299 	resource->size_valid = true;
4300 	memcpy(&resource->size_params, size_params,
4301 	       sizeof(resource->size_params));
4302 	INIT_LIST_HEAD(&resource->resource_list);
4303 	list_add_tail(&resource->list, resource_list);
4304 out:
4305 	mutex_unlock(&devlink->lock);
4306 	return err;
4307 }
4308 EXPORT_SYMBOL_GPL(devlink_resource_register);
4309 
4310 /**
4311  *	devlink_resources_unregister - free all resources
4312  *
4313  *	@devlink: devlink
4314  *	@resource: resource
4315  */
devlink_resources_unregister(struct devlink * devlink,struct devlink_resource * resource)4316 void devlink_resources_unregister(struct devlink *devlink,
4317 				  struct devlink_resource *resource)
4318 {
4319 	struct devlink_resource *tmp, *child_resource;
4320 	struct list_head *resource_list;
4321 
4322 	if (resource)
4323 		resource_list = &resource->resource_list;
4324 	else
4325 		resource_list = &devlink->resource_list;
4326 
4327 	if (!resource)
4328 		mutex_lock(&devlink->lock);
4329 
4330 	list_for_each_entry_safe(child_resource, tmp, resource_list, list) {
4331 		devlink_resources_unregister(devlink, child_resource);
4332 		list_del(&child_resource->list);
4333 		kfree(child_resource);
4334 	}
4335 
4336 	if (!resource)
4337 		mutex_unlock(&devlink->lock);
4338 }
4339 EXPORT_SYMBOL_GPL(devlink_resources_unregister);
4340 
4341 /**
4342  *	devlink_resource_size_get - get and update size
4343  *
4344  *	@devlink: devlink
4345  *	@resource_id: the requested resource id
4346  *	@p_resource_size: ptr to update
4347  */
devlink_resource_size_get(struct devlink * devlink,u64 resource_id,u64 * p_resource_size)4348 int devlink_resource_size_get(struct devlink *devlink,
4349 			      u64 resource_id,
4350 			      u64 *p_resource_size)
4351 {
4352 	struct devlink_resource *resource;
4353 	int err = 0;
4354 
4355 	mutex_lock(&devlink->lock);
4356 	resource = devlink_resource_find(devlink, NULL, resource_id);
4357 	if (!resource) {
4358 		err = -EINVAL;
4359 		goto out;
4360 	}
4361 	*p_resource_size = resource->size_new;
4362 	resource->size = resource->size_new;
4363 out:
4364 	mutex_unlock(&devlink->lock);
4365 	return err;
4366 }
4367 EXPORT_SYMBOL_GPL(devlink_resource_size_get);
4368 
4369 /**
4370  *	devlink_dpipe_table_resource_set - set the resource id
4371  *
4372  *	@devlink: devlink
4373  *	@table_name: table name
4374  *	@resource_id: resource id
4375  *	@resource_units: number of resource's units consumed per table's entry
4376  */
devlink_dpipe_table_resource_set(struct devlink * devlink,const char * table_name,u64 resource_id,u64 resource_units)4377 int devlink_dpipe_table_resource_set(struct devlink *devlink,
4378 				     const char *table_name, u64 resource_id,
4379 				     u64 resource_units)
4380 {
4381 	struct devlink_dpipe_table *table;
4382 	int err = 0;
4383 
4384 	mutex_lock(&devlink->lock);
4385 	table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
4386 					 table_name);
4387 	if (!table) {
4388 		err = -EINVAL;
4389 		goto out;
4390 	}
4391 	table->resource_id = resource_id;
4392 	table->resource_units = resource_units;
4393 	table->resource_valid = true;
4394 out:
4395 	mutex_unlock(&devlink->lock);
4396 	return err;
4397 }
4398 EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set);
4399 
4400 /**
4401  *	devlink_resource_occ_get_register - register occupancy getter
4402  *
4403  *	@devlink: devlink
4404  *	@resource_id: resource id
4405  *	@occ_get: occupancy getter callback
4406  *	@occ_get_priv: occupancy getter callback priv
4407  */
devlink_resource_occ_get_register(struct devlink * devlink,u64 resource_id,devlink_resource_occ_get_t * occ_get,void * occ_get_priv)4408 void devlink_resource_occ_get_register(struct devlink *devlink,
4409 				       u64 resource_id,
4410 				       devlink_resource_occ_get_t *occ_get,
4411 				       void *occ_get_priv)
4412 {
4413 	struct devlink_resource *resource;
4414 
4415 	mutex_lock(&devlink->lock);
4416 	resource = devlink_resource_find(devlink, NULL, resource_id);
4417 	if (WARN_ON(!resource))
4418 		goto out;
4419 	WARN_ON(resource->occ_get);
4420 
4421 	resource->occ_get = occ_get;
4422 	resource->occ_get_priv = occ_get_priv;
4423 out:
4424 	mutex_unlock(&devlink->lock);
4425 }
4426 EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register);
4427 
4428 /**
4429  *	devlink_resource_occ_get_unregister - unregister occupancy getter
4430  *
4431  *	@devlink: devlink
4432  *	@resource_id: resource id
4433  */
devlink_resource_occ_get_unregister(struct devlink * devlink,u64 resource_id)4434 void devlink_resource_occ_get_unregister(struct devlink *devlink,
4435 					 u64 resource_id)
4436 {
4437 	struct devlink_resource *resource;
4438 
4439 	mutex_lock(&devlink->lock);
4440 	resource = devlink_resource_find(devlink, NULL, resource_id);
4441 	if (WARN_ON(!resource))
4442 		goto out;
4443 	WARN_ON(!resource->occ_get);
4444 
4445 	resource->occ_get = NULL;
4446 	resource->occ_get_priv = NULL;
4447 out:
4448 	mutex_unlock(&devlink->lock);
4449 }
4450 EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister);
4451 
4452 /**
4453  *	devlink_params_register - register configuration parameters
4454  *
4455  *	@devlink: devlink
4456  *	@params: configuration parameters array
4457  *	@params_count: number of parameters provided
4458  *
4459  *	Register the configuration parameters supported by the driver.
4460  */
devlink_params_register(struct devlink * devlink,const struct devlink_param * params,size_t params_count)4461 int devlink_params_register(struct devlink *devlink,
4462 			    const struct devlink_param *params,
4463 			    size_t params_count)
4464 {
4465 	const struct devlink_param *param = params;
4466 	int i;
4467 	int err;
4468 
4469 	mutex_lock(&devlink->lock);
4470 	for (i = 0; i < params_count; i++, param++) {
4471 		if (!param || !param->name || !param->supported_cmodes) {
4472 			err = -EINVAL;
4473 			goto rollback;
4474 		}
4475 		if (param->generic) {
4476 			err = devlink_param_generic_verify(param);
4477 			if (err)
4478 				goto rollback;
4479 		} else {
4480 			err = devlink_param_driver_verify(param);
4481 			if (err)
4482 				goto rollback;
4483 		}
4484 		err = devlink_param_register_one(devlink, param);
4485 		if (err)
4486 			goto rollback;
4487 	}
4488 
4489 	mutex_unlock(&devlink->lock);
4490 	return 0;
4491 
4492 rollback:
4493 	if (!i)
4494 		goto unlock;
4495 	for (param--; i > 0; i--, param--)
4496 		devlink_param_unregister_one(devlink, param);
4497 unlock:
4498 	mutex_unlock(&devlink->lock);
4499 	return err;
4500 }
4501 EXPORT_SYMBOL_GPL(devlink_params_register);
4502 
4503 /**
4504  *	devlink_params_unregister - unregister configuration parameters
4505  *	@devlink: devlink
4506  *	@params: configuration parameters to unregister
4507  *	@params_count: number of parameters provided
4508  */
devlink_params_unregister(struct devlink * devlink,const struct devlink_param * params,size_t params_count)4509 void devlink_params_unregister(struct devlink *devlink,
4510 			       const struct devlink_param *params,
4511 			       size_t params_count)
4512 {
4513 	const struct devlink_param *param = params;
4514 	int i;
4515 
4516 	mutex_lock(&devlink->lock);
4517 	for (i = 0; i < params_count; i++, param++)
4518 		devlink_param_unregister_one(devlink, param);
4519 	mutex_unlock(&devlink->lock);
4520 }
4521 EXPORT_SYMBOL_GPL(devlink_params_unregister);
4522 
4523 /**
4524  *	devlink_param_driverinit_value_get - get configuration parameter
4525  *					     value for driver initializing
4526  *
4527  *	@devlink: devlink
4528  *	@param_id: parameter ID
4529  *	@init_val: value of parameter in driverinit configuration mode
4530  *
4531  *	This function should be used by the driver to get driverinit
4532  *	configuration for initialization after reload command.
4533  */
devlink_param_driverinit_value_get(struct devlink * devlink,u32 param_id,union devlink_param_value * init_val)4534 int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
4535 				       union devlink_param_value *init_val)
4536 {
4537 	struct devlink_param_item *param_item;
4538 
4539 	if (!devlink->ops || !devlink->ops->reload)
4540 		return -EOPNOTSUPP;
4541 
4542 	param_item = devlink_param_find_by_id(&devlink->param_list, param_id);
4543 	if (!param_item)
4544 		return -EINVAL;
4545 
4546 	if (!param_item->driverinit_value_valid ||
4547 	    !devlink_param_cmode_is_supported(param_item->param,
4548 					      DEVLINK_PARAM_CMODE_DRIVERINIT))
4549 		return -EOPNOTSUPP;
4550 
4551 	if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
4552 		strcpy(init_val->vstr, param_item->driverinit_value.vstr);
4553 	else
4554 		*init_val = param_item->driverinit_value;
4555 
4556 	return 0;
4557 }
4558 EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_get);
4559 
4560 /**
4561  *	devlink_param_driverinit_value_set - set value of configuration
4562  *					     parameter for driverinit
4563  *					     configuration mode
4564  *
4565  *	@devlink: devlink
4566  *	@param_id: parameter ID
4567  *	@init_val: value of parameter to set for driverinit configuration mode
4568  *
4569  *	This function should be used by the driver to set driverinit
4570  *	configuration mode default value.
4571  */
devlink_param_driverinit_value_set(struct devlink * devlink,u32 param_id,union devlink_param_value init_val)4572 int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
4573 				       union devlink_param_value init_val)
4574 {
4575 	struct devlink_param_item *param_item;
4576 
4577 	param_item = devlink_param_find_by_id(&devlink->param_list, param_id);
4578 	if (!param_item)
4579 		return -EINVAL;
4580 
4581 	if (!devlink_param_cmode_is_supported(param_item->param,
4582 					      DEVLINK_PARAM_CMODE_DRIVERINIT))
4583 		return -EOPNOTSUPP;
4584 
4585 	if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
4586 		strcpy(param_item->driverinit_value.vstr, init_val.vstr);
4587 	else
4588 		param_item->driverinit_value = init_val;
4589 	param_item->driverinit_value_valid = true;
4590 
4591 	devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW);
4592 	return 0;
4593 }
4594 EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_set);
4595 
4596 /**
4597  *	devlink_param_value_changed - notify devlink on a parameter's value
4598  *				      change. Should be called by the driver
4599  *				      right after the change.
4600  *
4601  *	@devlink: devlink
4602  *	@param_id: parameter ID
4603  *
4604  *	This function should be used by the driver to notify devlink on value
4605  *	change, excluding driverinit configuration mode.
4606  *	For driverinit configuration mode driver should use the function
4607  *	devlink_param_driverinit_value_set() instead.
4608  */
devlink_param_value_changed(struct devlink * devlink,u32 param_id)4609 void devlink_param_value_changed(struct devlink *devlink, u32 param_id)
4610 {
4611 	struct devlink_param_item *param_item;
4612 
4613 	param_item = devlink_param_find_by_id(&devlink->param_list, param_id);
4614 	WARN_ON(!param_item);
4615 
4616 	devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW);
4617 }
4618 EXPORT_SYMBOL_GPL(devlink_param_value_changed);
4619 
4620 /**
4621  *	devlink_param_value_str_fill - Safely fill-up the string preventing
4622  *				       from overflow of the preallocated buffer
4623  *
4624  *	@dst_val: destination devlink_param_value
4625  *	@src: source buffer
4626  */
devlink_param_value_str_fill(union devlink_param_value * dst_val,const char * src)4627 void devlink_param_value_str_fill(union devlink_param_value *dst_val,
4628 				  const char *src)
4629 {
4630 	size_t len;
4631 
4632 	len = strlcpy(dst_val->vstr, src, __DEVLINK_PARAM_MAX_STRING_VALUE);
4633 	WARN_ON(len >= __DEVLINK_PARAM_MAX_STRING_VALUE);
4634 }
4635 EXPORT_SYMBOL_GPL(devlink_param_value_str_fill);
4636 
4637 /**
4638  *	devlink_region_create - create a new address region
4639  *
4640  *	@devlink: devlink
4641  *	@region_name: region name
4642  *	@region_max_snapshots: Maximum supported number of snapshots for region
4643  *	@region_size: size of region
4644  */
devlink_region_create(struct devlink * devlink,const char * region_name,u32 region_max_snapshots,u64 region_size)4645 struct devlink_region *devlink_region_create(struct devlink *devlink,
4646 					     const char *region_name,
4647 					     u32 region_max_snapshots,
4648 					     u64 region_size)
4649 {
4650 	struct devlink_region *region;
4651 	int err = 0;
4652 
4653 	mutex_lock(&devlink->lock);
4654 
4655 	if (devlink_region_get_by_name(devlink, region_name)) {
4656 		err = -EEXIST;
4657 		goto unlock;
4658 	}
4659 
4660 	region = kzalloc(sizeof(*region), GFP_KERNEL);
4661 	if (!region) {
4662 		err = -ENOMEM;
4663 		goto unlock;
4664 	}
4665 
4666 	region->devlink = devlink;
4667 	region->max_snapshots = region_max_snapshots;
4668 	region->name = region_name;
4669 	region->size = region_size;
4670 	INIT_LIST_HEAD(&region->snapshot_list);
4671 	list_add_tail(&region->list, &devlink->region_list);
4672 	devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
4673 
4674 	mutex_unlock(&devlink->lock);
4675 	return region;
4676 
4677 unlock:
4678 	mutex_unlock(&devlink->lock);
4679 	return ERR_PTR(err);
4680 }
4681 EXPORT_SYMBOL_GPL(devlink_region_create);
4682 
4683 /**
4684  *	devlink_region_destroy - destroy address region
4685  *
4686  *	@region: devlink region to destroy
4687  */
devlink_region_destroy(struct devlink_region * region)4688 void devlink_region_destroy(struct devlink_region *region)
4689 {
4690 	struct devlink *devlink = region->devlink;
4691 	struct devlink_snapshot *snapshot, *ts;
4692 
4693 	mutex_lock(&devlink->lock);
4694 
4695 	/* Free all snapshots of region */
4696 	list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list)
4697 		devlink_region_snapshot_del(snapshot);
4698 
4699 	list_del(&region->list);
4700 
4701 	devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
4702 	mutex_unlock(&devlink->lock);
4703 	kfree(region);
4704 }
4705 EXPORT_SYMBOL_GPL(devlink_region_destroy);
4706 
4707 /**
4708  *	devlink_region_shapshot_id_get - get snapshot ID
4709  *
4710  *	This callback should be called when adding a new snapshot,
4711  *	Driver should use the same id for multiple snapshots taken
4712  *	on multiple regions at the same time/by the same trigger.
4713  *
4714  *	@devlink: devlink
4715  */
devlink_region_shapshot_id_get(struct devlink * devlink)4716 u32 devlink_region_shapshot_id_get(struct devlink *devlink)
4717 {
4718 	u32 id;
4719 
4720 	mutex_lock(&devlink->lock);
4721 	id = ++devlink->snapshot_id;
4722 	mutex_unlock(&devlink->lock);
4723 
4724 	return id;
4725 }
4726 EXPORT_SYMBOL_GPL(devlink_region_shapshot_id_get);
4727 
4728 /**
4729  *	devlink_region_snapshot_create - create a new snapshot
4730  *	This will add a new snapshot of a region. The snapshot
4731  *	will be stored on the region struct and can be accessed
4732  *	from devlink. This is useful for future	analyses of snapshots.
4733  *	Multiple snapshots can be created on a region.
4734  *	The @snapshot_id should be obtained using the getter function.
4735  *
4736  *	@devlink_region: devlink region of the snapshot
4737  *	@data_len: size of snapshot data
4738  *	@data: snapshot data
4739  *	@snapshot_id: snapshot id to be created
4740  *	@data_destructor: pointer to destructor function to free data
4741  */
devlink_region_snapshot_create(struct devlink_region * region,u64 data_len,u8 * data,u32 snapshot_id,devlink_snapshot_data_dest_t * data_destructor)4742 int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len,
4743 				   u8 *data, u32 snapshot_id,
4744 				   devlink_snapshot_data_dest_t *data_destructor)
4745 {
4746 	struct devlink *devlink = region->devlink;
4747 	struct devlink_snapshot *snapshot;
4748 	int err;
4749 
4750 	mutex_lock(&devlink->lock);
4751 
4752 	/* check if region can hold one more snapshot */
4753 	if (region->cur_snapshots == region->max_snapshots) {
4754 		err = -ENOMEM;
4755 		goto unlock;
4756 	}
4757 
4758 	if (devlink_region_snapshot_get_by_id(region, snapshot_id)) {
4759 		err = -EEXIST;
4760 		goto unlock;
4761 	}
4762 
4763 	snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL);
4764 	if (!snapshot) {
4765 		err = -ENOMEM;
4766 		goto unlock;
4767 	}
4768 
4769 	snapshot->id = snapshot_id;
4770 	snapshot->region = region;
4771 	snapshot->data = data;
4772 	snapshot->data_len = data_len;
4773 	snapshot->data_destructor = data_destructor;
4774 
4775 	list_add_tail(&snapshot->list, &region->snapshot_list);
4776 
4777 	region->cur_snapshots++;
4778 
4779 	devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW);
4780 	mutex_unlock(&devlink->lock);
4781 	return 0;
4782 
4783 unlock:
4784 	mutex_unlock(&devlink->lock);
4785 	return err;
4786 }
4787 EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);
4788 
devlink_module_init(void)4789 static int __init devlink_module_init(void)
4790 {
4791 	return genl_register_family(&devlink_nl_family);
4792 }
4793 
devlink_module_exit(void)4794 static void __exit devlink_module_exit(void)
4795 {
4796 	genl_unregister_family(&devlink_nl_family);
4797 }
4798 
4799 module_init(devlink_module_init);
4800 module_exit(devlink_module_exit);
4801 
4802 MODULE_LICENSE("GPL v2");
4803 MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
4804 MODULE_DESCRIPTION("Network physical device Netlink interface");
4805 MODULE_ALIAS_GENL_FAMILY(DEVLINK_GENL_NAME);
4806