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