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