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