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