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