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