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