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