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