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