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