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