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