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