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