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