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