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