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