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