net/mlx5: Add support for devlink reload action fw activate
[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 },
036467c3 3524};
eabaef18
MS
3525
3526static int devlink_param_generic_verify(const struct devlink_param *param)
3527{
3528 /* verify it match generic parameter by id and name */
3529 if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX)
3530 return -EINVAL;
3531 if (strcmp(param->name, devlink_param_generic[param->id].name))
3532 return -ENOENT;
3533
3534 WARN_ON(param->type != devlink_param_generic[param->id].type);
3535
3536 return 0;
3537}
3538
3539static int devlink_param_driver_verify(const struct devlink_param *param)
3540{
3541 int i;
3542
3543 if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX)
3544 return -EINVAL;
3545 /* verify no such name in generic params */
3546 for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++)
3547 if (!strcmp(param->name, devlink_param_generic[i].name))
3548 return -EEXIST;
3549
3550 return 0;
3551}
3552
3553static struct devlink_param_item *
3554devlink_param_find_by_name(struct list_head *param_list,
3555 const char *param_name)
3556{
3557 struct devlink_param_item *param_item;
3558
3559 list_for_each_entry(param_item, param_list, list)
3560 if (!strcmp(param_item->param->name, param_name))
3561 return param_item;
3562 return NULL;
3563}
3564
ec01aeb1
MS
3565static struct devlink_param_item *
3566devlink_param_find_by_id(struct list_head *param_list, u32 param_id)
3567{
3568 struct devlink_param_item *param_item;
3569
3570 list_for_each_entry(param_item, param_list, list)
3571 if (param_item->param->id == param_id)
3572 return param_item;
3573 return NULL;
3574}
3575
45f05def
MS
3576static bool
3577devlink_param_cmode_is_supported(const struct devlink_param *param,
3578 enum devlink_param_cmode cmode)
3579{
3580 return test_bit(cmode, &param->supported_cmodes);
3581}
3582
3583static int devlink_param_get(struct devlink *devlink,
3584 const struct devlink_param *param,
3585 struct devlink_param_gset_ctx *ctx)
3586{
3587 if (!param->get)
3588 return -EOPNOTSUPP;
3589 return param->get(devlink, param->id, ctx);
3590}
3591
e3b7ca18
MS
3592static int devlink_param_set(struct devlink *devlink,
3593 const struct devlink_param *param,
3594 struct devlink_param_gset_ctx *ctx)
3595{
3596 if (!param->set)
3597 return -EOPNOTSUPP;
3598 return param->set(devlink, param->id, ctx);
3599}
3600
45f05def
MS
3601static int
3602devlink_param_type_to_nla_type(enum devlink_param_type param_type)
3603{
3604 switch (param_type) {
3605 case DEVLINK_PARAM_TYPE_U8:
3606 return NLA_U8;
3607 case DEVLINK_PARAM_TYPE_U16:
3608 return NLA_U16;
3609 case DEVLINK_PARAM_TYPE_U32:
3610 return NLA_U32;
3611 case DEVLINK_PARAM_TYPE_STRING:
3612 return NLA_STRING;
3613 case DEVLINK_PARAM_TYPE_BOOL:
3614 return NLA_FLAG;
3615 default:
3616 return -EINVAL;
3617 }
3618}
3619
3620static int
3621devlink_nl_param_value_fill_one(struct sk_buff *msg,
3622 enum devlink_param_type type,
3623 enum devlink_param_cmode cmode,
3624 union devlink_param_value val)
3625{
3626 struct nlattr *param_value_attr;
3627
ae0be8de
MK
3628 param_value_attr = nla_nest_start_noflag(msg,
3629 DEVLINK_ATTR_PARAM_VALUE);
45f05def
MS
3630 if (!param_value_attr)
3631 goto nla_put_failure;
3632
3633 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
3634 goto value_nest_cancel;
3635
3636 switch (type) {
3637 case DEVLINK_PARAM_TYPE_U8:
3638 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8))
3639 goto value_nest_cancel;
3640 break;
3641 case DEVLINK_PARAM_TYPE_U16:
3642 if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16))
3643 goto value_nest_cancel;
3644 break;
3645 case DEVLINK_PARAM_TYPE_U32:
3646 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32))
3647 goto value_nest_cancel;
3648 break;
3649 case DEVLINK_PARAM_TYPE_STRING:
3650 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
3651 val.vstr))
3652 goto value_nest_cancel;
3653 break;
3654 case DEVLINK_PARAM_TYPE_BOOL:
3655 if (val.vbool &&
3656 nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA))
3657 goto value_nest_cancel;
3658 break;
3659 }
3660
3661 nla_nest_end(msg, param_value_attr);
3662 return 0;
3663
3664value_nest_cancel:
3665 nla_nest_cancel(msg, param_value_attr);
3666nla_put_failure:
3667 return -EMSGSIZE;
3668}
3669
3670static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
f4601dee 3671 unsigned int port_index,
45f05def
MS
3672 struct devlink_param_item *param_item,
3673 enum devlink_command cmd,
3674 u32 portid, u32 seq, int flags)
3675{
3676 union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
7c62cfb8 3677 bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
45f05def
MS
3678 const struct devlink_param *param = param_item->param;
3679 struct devlink_param_gset_ctx ctx;
3680 struct nlattr *param_values_list;
3681 struct nlattr *param_attr;
3682 int nla_type;
3683 void *hdr;
3684 int err;
3685 int i;
3686
3687 /* Get value from driver part to driverinit configuration mode */
3688 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
3689 if (!devlink_param_cmode_is_supported(param, i))
3690 continue;
3691 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
3692 if (!param_item->driverinit_value_valid)
3693 return -EOPNOTSUPP;
3694 param_value[i] = param_item->driverinit_value;
3695 } else {
7c62cfb8
JP
3696 if (!param_item->published)
3697 continue;
45f05def
MS
3698 ctx.cmode = i;
3699 err = devlink_param_get(devlink, param, &ctx);
3700 if (err)
3701 return err;
3702 param_value[i] = ctx.val;
3703 }
7c62cfb8 3704 param_value_set[i] = true;
45f05def
MS
3705 }
3706
3707 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
3708 if (!hdr)
3709 return -EMSGSIZE;
3710
3711 if (devlink_nl_put_handle(msg, devlink))
3712 goto genlmsg_cancel;
f4601dee 3713
c1e5786d
VV
3714 if (cmd == DEVLINK_CMD_PORT_PARAM_GET ||
3715 cmd == DEVLINK_CMD_PORT_PARAM_NEW ||
3716 cmd == DEVLINK_CMD_PORT_PARAM_DEL)
f4601dee
VV
3717 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index))
3718 goto genlmsg_cancel;
3719
ae0be8de 3720 param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM);
45f05def
MS
3721 if (!param_attr)
3722 goto genlmsg_cancel;
3723 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name))
3724 goto param_nest_cancel;
3725 if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC))
3726 goto param_nest_cancel;
3727
3728 nla_type = devlink_param_type_to_nla_type(param->type);
3729 if (nla_type < 0)
3730 goto param_nest_cancel;
3731 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type))
3732 goto param_nest_cancel;
3733
ae0be8de
MK
3734 param_values_list = nla_nest_start_noflag(msg,
3735 DEVLINK_ATTR_PARAM_VALUES_LIST);
45f05def
MS
3736 if (!param_values_list)
3737 goto param_nest_cancel;
3738
3739 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
7c62cfb8 3740 if (!param_value_set[i])
45f05def
MS
3741 continue;
3742 err = devlink_nl_param_value_fill_one(msg, param->type,
3743 i, param_value[i]);
3744 if (err)
3745 goto values_list_nest_cancel;
3746 }
3747
3748 nla_nest_end(msg, param_values_list);
3749 nla_nest_end(msg, param_attr);
3750 genlmsg_end(msg, hdr);
3751 return 0;
3752
3753values_list_nest_cancel:
3754 nla_nest_end(msg, param_values_list);
3755param_nest_cancel:
3756 nla_nest_cancel(msg, param_attr);
3757genlmsg_cancel:
3758 genlmsg_cancel(msg, hdr);
3759 return -EMSGSIZE;
3760}
3761
ea601e17 3762static void devlink_param_notify(struct devlink *devlink,
c1e5786d 3763 unsigned int port_index,
ea601e17
MS
3764 struct devlink_param_item *param_item,
3765 enum devlink_command cmd)
3766{
3767 struct sk_buff *msg;
3768 int err;
3769
c1e5786d
VV
3770 WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL &&
3771 cmd != DEVLINK_CMD_PORT_PARAM_NEW &&
3772 cmd != DEVLINK_CMD_PORT_PARAM_DEL);
ea601e17
MS
3773
3774 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3775 if (!msg)
3776 return;
c1e5786d
VV
3777 err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd,
3778 0, 0, 0);
ea601e17
MS
3779 if (err) {
3780 nlmsg_free(msg);
3781 return;
3782 }
3783
3784 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
3785 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
3786}
3787
45f05def
MS
3788static int devlink_nl_cmd_param_get_dumpit(struct sk_buff *msg,
3789 struct netlink_callback *cb)
3790{
3791 struct devlink_param_item *param_item;
3792 struct devlink *devlink;
3793 int start = cb->args[0];
3794 int idx = 0;
c62c2cfb 3795 int err = 0;
45f05def
MS
3796
3797 mutex_lock(&devlink_mutex);
3798 list_for_each_entry(devlink, &devlink_list, list) {
3799 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3800 continue;
3801 mutex_lock(&devlink->lock);
3802 list_for_each_entry(param_item, &devlink->param_list, list) {
3803 if (idx < start) {
3804 idx++;
3805 continue;
3806 }
f4601dee 3807 err = devlink_nl_param_fill(msg, devlink, 0, param_item,
45f05def
MS
3808 DEVLINK_CMD_PARAM_GET,
3809 NETLINK_CB(cb->skb).portid,
3810 cb->nlh->nlmsg_seq,
3811 NLM_F_MULTI);
82274d07
JK
3812 if (err == -EOPNOTSUPP) {
3813 err = 0;
3814 } else if (err) {
45f05def
MS
3815 mutex_unlock(&devlink->lock);
3816 goto out;
3817 }
3818 idx++;
3819 }
3820 mutex_unlock(&devlink->lock);
3821 }
3822out:
3823 mutex_unlock(&devlink_mutex);
3824
c62c2cfb
JP
3825 if (err != -EMSGSIZE)
3826 return err;
3827
45f05def
MS
3828 cb->args[0] = idx;
3829 return msg->len;
3830}
3831
e3b7ca18
MS
3832static int
3833devlink_param_type_get_from_info(struct genl_info *info,
3834 enum devlink_param_type *param_type)
3835{
3836 if (!info->attrs[DEVLINK_ATTR_PARAM_TYPE])
3837 return -EINVAL;
3838
3839 switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) {
3840 case NLA_U8:
3841 *param_type = DEVLINK_PARAM_TYPE_U8;
3842 break;
3843 case NLA_U16:
3844 *param_type = DEVLINK_PARAM_TYPE_U16;
3845 break;
3846 case NLA_U32:
3847 *param_type = DEVLINK_PARAM_TYPE_U32;
3848 break;
3849 case NLA_STRING:
3850 *param_type = DEVLINK_PARAM_TYPE_STRING;
3851 break;
3852 case NLA_FLAG:
3853 *param_type = DEVLINK_PARAM_TYPE_BOOL;
3854 break;
3855 default:
3856 return -EINVAL;
3857 }
3858
3859 return 0;
3860}
3861
3862static int
3863devlink_param_value_get_from_info(const struct devlink_param *param,
3864 struct genl_info *info,
3865 union devlink_param_value *value)
3866{
8750939b 3867 struct nlattr *param_data;
f355cfcd
MS
3868 int len;
3869
8750939b
JK
3870 param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA];
3871
3872 if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data)
e3b7ca18
MS
3873 return -EINVAL;
3874
3875 switch (param->type) {
3876 case DEVLINK_PARAM_TYPE_U8:
8750939b
JK
3877 if (nla_len(param_data) != sizeof(u8))
3878 return -EINVAL;
3879 value->vu8 = nla_get_u8(param_data);
e3b7ca18
MS
3880 break;
3881 case DEVLINK_PARAM_TYPE_U16:
8750939b
JK
3882 if (nla_len(param_data) != sizeof(u16))
3883 return -EINVAL;
3884 value->vu16 = nla_get_u16(param_data);
e3b7ca18
MS
3885 break;
3886 case DEVLINK_PARAM_TYPE_U32:
8750939b
JK
3887 if (nla_len(param_data) != sizeof(u32))
3888 return -EINVAL;
3889 value->vu32 = nla_get_u32(param_data);
e3b7ca18
MS
3890 break;
3891 case DEVLINK_PARAM_TYPE_STRING:
8750939b
JK
3892 len = strnlen(nla_data(param_data), nla_len(param_data));
3893 if (len == nla_len(param_data) ||
bde74ad1 3894 len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
e3b7ca18 3895 return -EINVAL;
8750939b 3896 strcpy(value->vstr, nla_data(param_data));
e3b7ca18
MS
3897 break;
3898 case DEVLINK_PARAM_TYPE_BOOL:
8750939b
JK
3899 if (param_data && nla_len(param_data))
3900 return -EINVAL;
3901 value->vbool = nla_get_flag(param_data);
e3b7ca18
MS
3902 break;
3903 }
3904 return 0;
3905}
3906
45f05def 3907static struct devlink_param_item *
f4601dee 3908devlink_param_get_from_info(struct list_head *param_list,
45f05def
MS
3909 struct genl_info *info)
3910{
3911 char *param_name;
3912
3913 if (!info->attrs[DEVLINK_ATTR_PARAM_NAME])
3914 return NULL;
3915
3916 param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]);
f4601dee 3917 return devlink_param_find_by_name(param_list, param_name);
45f05def
MS
3918}
3919
3920static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb,
3921 struct genl_info *info)
3922{
3923 struct devlink *devlink = info->user_ptr[0];
3924 struct devlink_param_item *param_item;
3925 struct sk_buff *msg;
3926 int err;
3927
f4601dee 3928 param_item = devlink_param_get_from_info(&devlink->param_list, info);
45f05def
MS
3929 if (!param_item)
3930 return -EINVAL;
3931
3932 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3933 if (!msg)
3934 return -ENOMEM;
3935
f4601dee 3936 err = devlink_nl_param_fill(msg, devlink, 0, param_item,
45f05def
MS
3937 DEVLINK_CMD_PARAM_GET,
3938 info->snd_portid, info->snd_seq, 0);
3939 if (err) {
3940 nlmsg_free(msg);
3941 return err;
3942 }
3943
3944 return genlmsg_reply(msg, info);
3945}
3946
9c54873b 3947static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
c1e5786d 3948 unsigned int port_index,
9c54873b
VV
3949 struct list_head *param_list,
3950 struct genl_info *info,
3951 enum devlink_command cmd)
e3b7ca18 3952{
e3b7ca18
MS
3953 enum devlink_param_type param_type;
3954 struct devlink_param_gset_ctx ctx;
3955 enum devlink_param_cmode cmode;
3956 struct devlink_param_item *param_item;
3957 const struct devlink_param *param;
3958 union devlink_param_value value;
3959 int err = 0;
3960
9c54873b 3961 param_item = devlink_param_get_from_info(param_list, info);
e3b7ca18
MS
3962 if (!param_item)
3963 return -EINVAL;
3964 param = param_item->param;
3965 err = devlink_param_type_get_from_info(info, &param_type);
3966 if (err)
3967 return err;
3968 if (param_type != param->type)
3969 return -EINVAL;
3970 err = devlink_param_value_get_from_info(param, info, &value);
3971 if (err)
3972 return err;
3973 if (param->validate) {
3974 err = param->validate(devlink, param->id, value, info->extack);
3975 if (err)
3976 return err;
3977 }
3978
3979 if (!info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE])
3980 return -EINVAL;
3981 cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
3982 if (!devlink_param_cmode_is_supported(param, cmode))
3983 return -EOPNOTSUPP;
3984
3985 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
1276534c
MS
3986 if (param->type == DEVLINK_PARAM_TYPE_STRING)
3987 strcpy(param_item->driverinit_value.vstr, value.vstr);
3988 else
3989 param_item->driverinit_value = value;
e3b7ca18
MS
3990 param_item->driverinit_value_valid = true;
3991 } else {
3992 if (!param->set)
3993 return -EOPNOTSUPP;
3994 ctx.val = value;
3995 ctx.cmode = cmode;
3996 err = devlink_param_set(devlink, param, &ctx);
3997 if (err)
3998 return err;
3999 }
4000
c1e5786d 4001 devlink_param_notify(devlink, port_index, param_item, cmd);
e3b7ca18
MS
4002 return 0;
4003}
4004
9c54873b
VV
4005static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb,
4006 struct genl_info *info)
4007{
4008 struct devlink *devlink = info->user_ptr[0];
4009
c1e5786d 4010 return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->param_list,
9c54873b
VV
4011 info, DEVLINK_CMD_PARAM_NEW);
4012}
4013
eabaef18 4014static int devlink_param_register_one(struct devlink *devlink,
c1e5786d 4015 unsigned int port_index,
39e6160e 4016 struct list_head *param_list,
c1e5786d
VV
4017 const struct devlink_param *param,
4018 enum devlink_command cmd)
eabaef18
MS
4019{
4020 struct devlink_param_item *param_item;
4021
39e6160e 4022 if (devlink_param_find_by_name(param_list, param->name))
eabaef18
MS
4023 return -EEXIST;
4024
4025 if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
4026 WARN_ON(param->get || param->set);
4027 else
4028 WARN_ON(!param->get || !param->set);
4029
4030 param_item = kzalloc(sizeof(*param_item), GFP_KERNEL);
4031 if (!param_item)
4032 return -ENOMEM;
4033 param_item->param = param;
4034
39e6160e 4035 list_add_tail(&param_item->list, param_list);
c1e5786d 4036 devlink_param_notify(devlink, port_index, param_item, cmd);
eabaef18
MS
4037 return 0;
4038}
4039
4040static void devlink_param_unregister_one(struct devlink *devlink,
c1e5786d 4041 unsigned int port_index,
39e6160e 4042 struct list_head *param_list,
c1e5786d
VV
4043 const struct devlink_param *param,
4044 enum devlink_command cmd)
eabaef18
MS
4045{
4046 struct devlink_param_item *param_item;
4047
39e6160e 4048 param_item = devlink_param_find_by_name(param_list, param->name);
eabaef18 4049 WARN_ON(!param_item);
c1e5786d 4050 devlink_param_notify(devlink, port_index, param_item, cmd);
eabaef18
MS
4051 list_del(&param_item->list);
4052 kfree(param_item);
4053}
4054
f4601dee
VV
4055static int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg,
4056 struct netlink_callback *cb)
4057{
4058 struct devlink_param_item *param_item;
4059 struct devlink_port *devlink_port;
4060 struct devlink *devlink;
4061 int start = cb->args[0];
4062 int idx = 0;
c62c2cfb 4063 int err = 0;
f4601dee
VV
4064
4065 mutex_lock(&devlink_mutex);
4066 list_for_each_entry(devlink, &devlink_list, list) {
4067 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
4068 continue;
4069 mutex_lock(&devlink->lock);
4070 list_for_each_entry(devlink_port, &devlink->port_list, list) {
4071 list_for_each_entry(param_item,
4072 &devlink_port->param_list, list) {
4073 if (idx < start) {
4074 idx++;
4075 continue;
4076 }
4077 err = devlink_nl_param_fill(msg,
4078 devlink_port->devlink,
4079 devlink_port->index, param_item,
4080 DEVLINK_CMD_PORT_PARAM_GET,
4081 NETLINK_CB(cb->skb).portid,
4082 cb->nlh->nlmsg_seq,
4083 NLM_F_MULTI);
82274d07
JK
4084 if (err == -EOPNOTSUPP) {
4085 err = 0;
4086 } else if (err) {
f4601dee
VV
4087 mutex_unlock(&devlink->lock);
4088 goto out;
4089 }
4090 idx++;
4091 }
4092 }
4093 mutex_unlock(&devlink->lock);
4094 }
4095out:
4096 mutex_unlock(&devlink_mutex);
4097
c62c2cfb
JP
4098 if (err != -EMSGSIZE)
4099 return err;
4100
f4601dee
VV
4101 cb->args[0] = idx;
4102 return msg->len;
4103}
4104
4105static int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb,
4106 struct genl_info *info)
4107{
4108 struct devlink_port *devlink_port = info->user_ptr[0];
4109 struct devlink_param_item *param_item;
4110 struct sk_buff *msg;
4111 int err;
4112
4113 param_item = devlink_param_get_from_info(&devlink_port->param_list,
4114 info);
4115 if (!param_item)
4116 return -EINVAL;
4117
4118 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4119 if (!msg)
4120 return -ENOMEM;
4121
4122 err = devlink_nl_param_fill(msg, devlink_port->devlink,
4123 devlink_port->index, param_item,
4124 DEVLINK_CMD_PORT_PARAM_GET,
4125 info->snd_portid, info->snd_seq, 0);
4126 if (err) {
4127 nlmsg_free(msg);
4128 return err;
4129 }
4130
4131 return genlmsg_reply(msg, info);
4132}
4133
9c54873b
VV
4134static int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb,
4135 struct genl_info *info)
4136{
4137 struct devlink_port *devlink_port = info->user_ptr[0];
4138
4139 return __devlink_nl_cmd_param_set_doit(devlink_port->devlink,
c1e5786d
VV
4140 devlink_port->index,
4141 &devlink_port->param_list, info,
4142 DEVLINK_CMD_PORT_PARAM_NEW);
9c54873b
VV
4143}
4144
a006d467
AV
4145static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg,
4146 struct devlink *devlink,
4147 struct devlink_snapshot *snapshot)
4148{
4149 struct nlattr *snap_attr;
4150 int err;
4151
ae0be8de 4152 snap_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_SNAPSHOT);
a006d467
AV
4153 if (!snap_attr)
4154 return -EINVAL;
4155
4156 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id);
4157 if (err)
4158 goto nla_put_failure;
4159
4160 nla_nest_end(msg, snap_attr);
4161 return 0;
4162
4163nla_put_failure:
4164 nla_nest_cancel(msg, snap_attr);
4165 return err;
4166}
4167
4168static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg,
4169 struct devlink *devlink,
4170 struct devlink_region *region)
4171{
4172 struct devlink_snapshot *snapshot;
4173 struct nlattr *snapshots_attr;
4174 int err;
4175
ae0be8de
MK
4176 snapshots_attr = nla_nest_start_noflag(msg,
4177 DEVLINK_ATTR_REGION_SNAPSHOTS);
a006d467
AV
4178 if (!snapshots_attr)
4179 return -EINVAL;
4180
4181 list_for_each_entry(snapshot, &region->snapshot_list, list) {
4182 err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot);
4183 if (err)
4184 goto nla_put_failure;
4185 }
4186
4187 nla_nest_end(msg, snapshots_attr);
4188 return 0;
4189
4190nla_put_failure:
4191 nla_nest_cancel(msg, snapshots_attr);
4192 return err;
4193}
4194
d8db7ea5
AV
4195static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink,
4196 enum devlink_command cmd, u32 portid,
4197 u32 seq, int flags,
4198 struct devlink_region *region)
4199{
4200 void *hdr;
4201 int err;
4202
4203 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
4204 if (!hdr)
4205 return -EMSGSIZE;
4206
4207 err = devlink_nl_put_handle(msg, devlink);
4208 if (err)
4209 goto nla_put_failure;
4210
544e7c33
AL
4211 if (region->port)
4212 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
4213 region->port->index))
4214 goto nla_put_failure;
4215
e8937681 4216 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->ops->name);
d8db7ea5
AV
4217 if (err)
4218 goto nla_put_failure;
4219
4220 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
4221 region->size,
4222 DEVLINK_ATTR_PAD);
4223 if (err)
4224 goto nla_put_failure;
4225
a006d467
AV
4226 err = devlink_nl_region_snapshots_id_put(msg, devlink, region);
4227 if (err)
4228 goto nla_put_failure;
4229
d8db7ea5
AV
4230 genlmsg_end(msg, hdr);
4231 return 0;
4232
4233nla_put_failure:
4234 genlmsg_cancel(msg, hdr);
4235 return err;
4236}
4237
dd86fec7
JK
4238static struct sk_buff *
4239devlink_nl_region_notify_build(struct devlink_region *region,
4240 struct devlink_snapshot *snapshot,
4241 enum devlink_command cmd, u32 portid, u32 seq)
866319bb
AV
4242{
4243 struct devlink *devlink = region->devlink;
4244 struct sk_buff *msg;
4245 void *hdr;
4246 int err;
4247
866319bb
AV
4248
4249 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4250 if (!msg)
dd86fec7 4251 return ERR_PTR(-ENOMEM);
866319bb 4252
dd86fec7
JK
4253 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, 0, cmd);
4254 if (!hdr) {
4255 err = -EMSGSIZE;
866319bb 4256 goto out_free_msg;
dd86fec7 4257 }
866319bb
AV
4258
4259 err = devlink_nl_put_handle(msg, devlink);
4260 if (err)
4261 goto out_cancel_msg;
4262
544e7c33
AL
4263 if (region->port)
4264 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
4265 region->port->index))
4266 goto out_cancel_msg;
4267
866319bb 4268 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME,
e8937681 4269 region->ops->name);
866319bb
AV
4270 if (err)
4271 goto out_cancel_msg;
4272
4273 if (snapshot) {
4274 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID,
4275 snapshot->id);
4276 if (err)
4277 goto out_cancel_msg;
4278 } else {
4279 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
4280 region->size, DEVLINK_ATTR_PAD);
4281 if (err)
4282 goto out_cancel_msg;
4283 }
4284 genlmsg_end(msg, hdr);
4285
dd86fec7 4286 return msg;
866319bb
AV
4287
4288out_cancel_msg:
4289 genlmsg_cancel(msg, hdr);
4290out_free_msg:
4291 nlmsg_free(msg);
dd86fec7
JK
4292 return ERR_PTR(err);
4293}
4294
4295static void devlink_nl_region_notify(struct devlink_region *region,
4296 struct devlink_snapshot *snapshot,
4297 enum devlink_command cmd)
4298{
4299 struct devlink *devlink = region->devlink;
4300 struct sk_buff *msg;
4301
4302 WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL);
4303
4304 msg = devlink_nl_region_notify_build(region, snapshot, cmd, 0, 0);
4305 if (IS_ERR(msg))
4306 return;
4307
4308 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
4309 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
866319bb
AV
4310}
4311
12102436
JK
4312/**
4313 * __devlink_snapshot_id_increment - Increment number of snapshots using an id
4314 * @devlink: devlink instance
4315 * @id: the snapshot id
4316 *
4317 * Track when a new snapshot begins using an id. Load the count for the
4318 * given id from the snapshot xarray, increment it, and store it back.
4319 *
4320 * Called when a new snapshot is created with the given id.
4321 *
4322 * The id *must* have been previously allocated by
4323 * devlink_region_snapshot_id_get().
4324 *
4325 * Returns 0 on success, or an error on failure.
4326 */
4327static int __devlink_snapshot_id_increment(struct devlink *devlink, u32 id)
4328{
4329 unsigned long count;
4330 void *p;
4331
4332 lockdep_assert_held(&devlink->lock);
4333
4334 p = xa_load(&devlink->snapshot_ids, id);
4335 if (WARN_ON(!p))
4336 return -EINVAL;
4337
4338 if (WARN_ON(!xa_is_value(p)))
4339 return -EINVAL;
4340
4341 count = xa_to_value(p);
4342 count++;
4343
4344 return xa_err(xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
4345 GFP_KERNEL));
4346}
4347
4348/**
4349 * __devlink_snapshot_id_decrement - Decrease number of snapshots using an id
4350 * @devlink: devlink instance
4351 * @id: the snapshot id
4352 *
4353 * Track when a snapshot is deleted and stops using an id. Load the count
4354 * for the given id from the snapshot xarray, decrement it, and store it
4355 * back.
4356 *
4357 * If the count reaches zero, erase this id from the xarray, freeing it
4358 * up for future re-use by devlink_region_snapshot_id_get().
4359 *
4360 * Called when a snapshot using the given id is deleted, and when the
4361 * initial allocator of the id is finished using it.
4362 */
4363static void __devlink_snapshot_id_decrement(struct devlink *devlink, u32 id)
4364{
4365 unsigned long count;
4366 void *p;
4367
4368 lockdep_assert_held(&devlink->lock);
4369
4370 p = xa_load(&devlink->snapshot_ids, id);
4371 if (WARN_ON(!p))
4372 return;
4373
4374 if (WARN_ON(!xa_is_value(p)))
4375 return;
4376
4377 count = xa_to_value(p);
4378
4379 if (count > 1) {
4380 count--;
4381 xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
4382 GFP_KERNEL);
4383 } else {
4384 /* If this was the last user, we can erase this id */
4385 xa_erase(&devlink->snapshot_ids, id);
4386 }
4387}
4388
b9a17abf
JK
4389/**
4390 * __devlink_snapshot_id_insert - Insert a specific snapshot ID
4391 * @devlink: devlink instance
4392 * @id: the snapshot id
4393 *
4394 * Mark the given snapshot id as used by inserting a zero value into the
4395 * snapshot xarray.
4396 *
4397 * This must be called while holding the devlink instance lock. Unlike
4398 * devlink_snapshot_id_get, the initial reference count is zero, not one.
4399 * It is expected that the id will immediately be used before
4400 * releasing the devlink instance lock.
4401 *
4402 * Returns zero on success, or an error code if the snapshot id could not
4403 * be inserted.
4404 */
4405static int __devlink_snapshot_id_insert(struct devlink *devlink, u32 id)
4406{
4407 lockdep_assert_held(&devlink->lock);
4408
bd71ea60 4409 if (xa_load(&devlink->snapshot_ids, id))
b9a17abf
JK
4410 return -EEXIST;
4411
4412 return xa_err(xa_store(&devlink->snapshot_ids, id, xa_mk_value(0),
4413 GFP_KERNEL));
4414}
4415
7000108f
JK
4416/**
4417 * __devlink_region_snapshot_id_get - get snapshot ID
4418 * @devlink: devlink instance
7ef19d3b 4419 * @id: storage to return snapshot id
7000108f 4420 *
7ef19d3b
JK
4421 * Allocates a new snapshot id. Returns zero on success, or a negative
4422 * error on failure. Must be called while holding the devlink instance
4423 * lock.
12102436
JK
4424 *
4425 * Snapshot IDs are tracked using an xarray which stores the number of
4426 * users of the snapshot id.
4427 *
4428 * Note that the caller of this function counts as a 'user', in order to
4429 * avoid race conditions. The caller must release its hold on the
4430 * snapshot by using devlink_region_snapshot_id_put.
7000108f 4431 */
7ef19d3b 4432static int __devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
7000108f
JK
4433{
4434 lockdep_assert_held(&devlink->lock);
7ef19d3b 4435
12102436
JK
4436 return xa_alloc(&devlink->snapshot_ids, id, xa_mk_value(1),
4437 xa_limit_32b, GFP_KERNEL);
7000108f
JK
4438}
4439
cf80faee
JK
4440/**
4441 * __devlink_region_snapshot_create - create a new snapshot
4442 * This will add a new snapshot of a region. The snapshot
4443 * will be stored on the region struct and can be accessed
4444 * from devlink. This is useful for future analyses of snapshots.
4445 * Multiple snapshots can be created on a region.
4446 * The @snapshot_id should be obtained using the getter function.
4447 *
4448 * Must be called only while holding the devlink instance lock.
4449 *
4450 * @region: devlink region of the snapshot
4451 * @data: snapshot data
4452 * @snapshot_id: snapshot id to be created
4453 */
4454static int
4455__devlink_region_snapshot_create(struct devlink_region *region,
4456 u8 *data, u32 snapshot_id)
4457{
4458 struct devlink *devlink = region->devlink;
4459 struct devlink_snapshot *snapshot;
12102436 4460 int err;
cf80faee
JK
4461
4462 lockdep_assert_held(&devlink->lock);
4463
4464 /* check if region can hold one more snapshot */
4465 if (region->cur_snapshots == region->max_snapshots)
47a39f61 4466 return -ENOSPC;
cf80faee
JK
4467
4468 if (devlink_region_snapshot_get_by_id(region, snapshot_id))
4469 return -EEXIST;
4470
4471 snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL);
4472 if (!snapshot)
4473 return -ENOMEM;
4474
12102436
JK
4475 err = __devlink_snapshot_id_increment(devlink, snapshot_id);
4476 if (err)
4477 goto err_snapshot_id_increment;
4478
cf80faee
JK
4479 snapshot->id = snapshot_id;
4480 snapshot->region = region;
4481 snapshot->data = data;
4482
4483 list_add_tail(&snapshot->list, &region->snapshot_list);
4484
4485 region->cur_snapshots++;
4486
4487 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW);
4488 return 0;
12102436
JK
4489
4490err_snapshot_id_increment:
4491 kfree(snapshot);
4492 return err;
cf80faee
JK
4493}
4494
92b49822
JP
4495static void devlink_region_snapshot_del(struct devlink_region *region,
4496 struct devlink_snapshot *snapshot)
4497{
12102436
JK
4498 struct devlink *devlink = region->devlink;
4499
4500 lockdep_assert_held(&devlink->lock);
4501
92b49822
JP
4502 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL);
4503 region->cur_snapshots--;
4504 list_del(&snapshot->list);
a0a09f6b 4505 region->ops->destructor(snapshot->data);
12102436 4506 __devlink_snapshot_id_decrement(devlink, snapshot->id);
92b49822
JP
4507 kfree(snapshot);
4508}
4509
d8db7ea5
AV
4510static int devlink_nl_cmd_region_get_doit(struct sk_buff *skb,
4511 struct genl_info *info)
4512{
4513 struct devlink *devlink = info->user_ptr[0];
544e7c33 4514 struct devlink_port *port = NULL;
d8db7ea5
AV
4515 struct devlink_region *region;
4516 const char *region_name;
4517 struct sk_buff *msg;
544e7c33 4518 unsigned int index;
d8db7ea5
AV
4519 int err;
4520
4521 if (!info->attrs[DEVLINK_ATTR_REGION_NAME])
4522 return -EINVAL;
4523
544e7c33
AL
4524 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
4525 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
4526
4527 port = devlink_port_get_by_index(devlink, index);
4528 if (!port)
4529 return -ENODEV;
4530 }
4531
d8db7ea5 4532 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
544e7c33
AL
4533 if (port)
4534 region = devlink_port_region_get_by_name(port, region_name);
4535 else
4536 region = devlink_region_get_by_name(devlink, region_name);
4537
d8db7ea5
AV
4538 if (!region)
4539 return -EINVAL;
4540
4541 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4542 if (!msg)
4543 return -ENOMEM;
4544
4545 err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET,
4546 info->snd_portid, info->snd_seq, 0,
4547 region);
4548 if (err) {
4549 nlmsg_free(msg);
4550 return err;
4551 }
4552
4553 return genlmsg_reply(msg, info);
4554}
4555
544e7c33
AL
4556static int devlink_nl_cmd_region_get_port_dumpit(struct sk_buff *msg,
4557 struct netlink_callback *cb,
4558 struct devlink_port *port,
4559 int *idx,
4560 int start)
4561{
4562 struct devlink_region *region;
4563 int err = 0;
4564
4565 list_for_each_entry(region, &port->region_list, list) {
4566 if (*idx < start) {
4567 (*idx)++;
4568 continue;
4569 }
4570 err = devlink_nl_region_fill(msg, port->devlink,
4571 DEVLINK_CMD_REGION_GET,
4572 NETLINK_CB(cb->skb).portid,
4573 cb->nlh->nlmsg_seq,
4574 NLM_F_MULTI, region);
4575 if (err)
4576 goto out;
4577 (*idx)++;
4578 }
4579
4580out:
4581 return err;
4582}
4583
4584static int devlink_nl_cmd_region_get_devlink_dumpit(struct sk_buff *msg,
4585 struct netlink_callback *cb,
4586 struct devlink *devlink,
4587 int *idx,
4588 int start)
4589{
4590 struct devlink_region *region;
4591 struct devlink_port *port;
4592 int err = 0;
4593
4594 mutex_lock(&devlink->lock);
4595 list_for_each_entry(region, &devlink->region_list, list) {
4596 if (*idx < start) {
4597 (*idx)++;
4598 continue;
4599 }
4600 err = devlink_nl_region_fill(msg, devlink,
4601 DEVLINK_CMD_REGION_GET,
4602 NETLINK_CB(cb->skb).portid,
4603 cb->nlh->nlmsg_seq,
4604 NLM_F_MULTI, region);
4605 if (err)
4606 goto out;
4607 (*idx)++;
4608 }
4609
4610 list_for_each_entry(port, &devlink->port_list, list) {
4611 err = devlink_nl_cmd_region_get_port_dumpit(msg, cb, port, idx,
4612 start);
4613 if (err)
4614 goto out;
4615 }
4616
4617out:
4618 mutex_unlock(&devlink->lock);
4619 return err;
4620}
4621
d8db7ea5
AV
4622static int devlink_nl_cmd_region_get_dumpit(struct sk_buff *msg,
4623 struct netlink_callback *cb)
4624{
d8db7ea5
AV
4625 struct devlink *devlink;
4626 int start = cb->args[0];
4627 int idx = 0;
4628 int err;
4629
4630 mutex_lock(&devlink_mutex);
4631 list_for_each_entry(devlink, &devlink_list, list) {
4632 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
4633 continue;
544e7c33
AL
4634 err = devlink_nl_cmd_region_get_devlink_dumpit(msg, cb, devlink,
4635 &idx, start);
4636 if (err)
4637 goto out;
d8db7ea5
AV
4638 }
4639out:
4640 mutex_unlock(&devlink_mutex);
4641 cb->args[0] = idx;
4642 return msg->len;
4643}
4644
866319bb
AV
4645static int devlink_nl_cmd_region_del(struct sk_buff *skb,
4646 struct genl_info *info)
4647{
4648 struct devlink *devlink = info->user_ptr[0];
4649 struct devlink_snapshot *snapshot;
544e7c33 4650 struct devlink_port *port = NULL;
866319bb
AV
4651 struct devlink_region *region;
4652 const char *region_name;
544e7c33 4653 unsigned int index;
866319bb
AV
4654 u32 snapshot_id;
4655
4656 if (!info->attrs[DEVLINK_ATTR_REGION_NAME] ||
4657 !info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID])
4658 return -EINVAL;
4659
4660 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
4661 snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
4662
544e7c33
AL
4663 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
4664 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
4665
4666 port = devlink_port_get_by_index(devlink, index);
4667 if (!port)
4668 return -ENODEV;
4669 }
4670
4671 if (port)
4672 region = devlink_port_region_get_by_name(port, region_name);
4673 else
4674 region = devlink_region_get_by_name(devlink, region_name);
4675
866319bb
AV
4676 if (!region)
4677 return -EINVAL;
4678
4679 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
4680 if (!snapshot)
4681 return -EINVAL;
4682
92b49822 4683 devlink_region_snapshot_del(region, snapshot);
866319bb
AV
4684 return 0;
4685}
4686
b9a17abf
JK
4687static int
4688devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info)
4689{
4690 struct devlink *devlink = info->user_ptr[0];
043b3e22 4691 struct devlink_snapshot *snapshot;
544e7c33 4692 struct devlink_port *port = NULL;
043b3e22 4693 struct nlattr *snapshot_id_attr;
b9a17abf
JK
4694 struct devlink_region *region;
4695 const char *region_name;
544e7c33 4696 unsigned int index;
b9a17abf
JK
4697 u32 snapshot_id;
4698 u8 *data;
4699 int err;
4700
4701 if (!info->attrs[DEVLINK_ATTR_REGION_NAME]) {
4702 NL_SET_ERR_MSG_MOD(info->extack, "No region name provided");
4703 return -EINVAL;
4704 }
4705
b9a17abf 4706 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
544e7c33
AL
4707
4708 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
4709 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
4710
4711 port = devlink_port_get_by_index(devlink, index);
4712 if (!port)
4713 return -ENODEV;
4714 }
4715
4716 if (port)
4717 region = devlink_port_region_get_by_name(port, region_name);
4718 else
4719 region = devlink_region_get_by_name(devlink, region_name);
4720
b9a17abf
JK
4721 if (!region) {
4722 NL_SET_ERR_MSG_MOD(info->extack, "The requested region does not exist");
4723 return -EINVAL;
4724 }
4725
4726 if (!region->ops->snapshot) {
4727 NL_SET_ERR_MSG_MOD(info->extack, "The requested region does not support taking an immediate snapshot");
4728 return -EOPNOTSUPP;
4729 }
4730
4731 if (region->cur_snapshots == region->max_snapshots) {
4732 NL_SET_ERR_MSG_MOD(info->extack, "The region has reached the maximum number of stored snapshots");
4733 return -ENOSPC;
4734 }
4735
043b3e22
JK
4736 snapshot_id_attr = info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID];
4737 if (snapshot_id_attr) {
4738 snapshot_id = nla_get_u32(snapshot_id_attr);
b9a17abf 4739
043b3e22
JK
4740 if (devlink_region_snapshot_get_by_id(region, snapshot_id)) {
4741 NL_SET_ERR_MSG_MOD(info->extack, "The requested snapshot id is already in use");
4742 return -EEXIST;
4743 }
b9a17abf 4744
043b3e22
JK
4745 err = __devlink_snapshot_id_insert(devlink, snapshot_id);
4746 if (err)
4747 return err;
4748 } else {
4749 err = __devlink_region_snapshot_id_get(devlink, &snapshot_id);
4750 if (err) {
4751 NL_SET_ERR_MSG_MOD(info->extack, "Failed to allocate a new snapshot id");
4752 return err;
4753 }
4754 }
b9a17abf 4755
544e7c33
AL
4756 if (port)
4757 err = region->port_ops->snapshot(port, region->port_ops,
4758 info->extack, &data);
4759 else
4760 err = region->ops->snapshot(devlink, region->ops,
4761 info->extack, &data);
b9a17abf
JK
4762 if (err)
4763 goto err_snapshot_capture;
4764
4765 err = __devlink_region_snapshot_create(region, data, snapshot_id);
4766 if (err)
4767 goto err_snapshot_create;
4768
043b3e22
JK
4769 if (!snapshot_id_attr) {
4770 struct sk_buff *msg;
4771
4772 snapshot = devlink_region_snapshot_get_by_id(region,
4773 snapshot_id);
4774 if (WARN_ON(!snapshot))
4775 return -EINVAL;
4776
4777 msg = devlink_nl_region_notify_build(region, snapshot,
4778 DEVLINK_CMD_REGION_NEW,
4779 info->snd_portid,
4780 info->snd_seq);
4781 err = PTR_ERR_OR_ZERO(msg);
4782 if (err)
4783 goto err_notify;
4784
4785 err = genlmsg_reply(msg, info);
4786 if (err)
4787 goto err_notify;
4788 }
4789
b9a17abf
JK
4790 return 0;
4791
4792err_snapshot_create:
4793 region->ops->destructor(data);
4794err_snapshot_capture:
4795 __devlink_snapshot_id_decrement(devlink, snapshot_id);
4796 return err;
043b3e22
JK
4797
4798err_notify:
4799 devlink_region_snapshot_del(region, snapshot);
4800 return err;
b9a17abf
JK
4801}
4802
4e54795a
AV
4803static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg,
4804 struct devlink *devlink,
4805 u8 *chunk, u32 chunk_size,
4806 u64 addr)
4807{
4808 struct nlattr *chunk_attr;
4809 int err;
4810
ae0be8de 4811 chunk_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_CHUNK);
4e54795a
AV
4812 if (!chunk_attr)
4813 return -EINVAL;
4814
4815 err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk);
4816 if (err)
4817 goto nla_put_failure;
4818
4819 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr,
4820 DEVLINK_ATTR_PAD);
4821 if (err)
4822 goto nla_put_failure;
4823
4824 nla_nest_end(msg, chunk_attr);
4825 return 0;
4826
4827nla_put_failure:
4828 nla_nest_cancel(msg, chunk_attr);
4829 return err;
4830}
4831
4832#define DEVLINK_REGION_READ_CHUNK_SIZE 256
4833
4834static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb,
4835 struct devlink *devlink,
4836 struct devlink_region *region,
4837 struct nlattr **attrs,
4838 u64 start_offset,
4839 u64 end_offset,
4e54795a
AV
4840 u64 *new_offset)
4841{
4842 struct devlink_snapshot *snapshot;
4843 u64 curr_offset = start_offset;
4844 u32 snapshot_id;
4845 int err = 0;
4846
4847 *new_offset = start_offset;
4848
4849 snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
4850 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
4851 if (!snapshot)
4852 return -EINVAL;
4853
4e54795a
AV
4854 while (curr_offset < end_offset) {
4855 u32 data_size;
4856 u8 *data;
4857
4858 if (end_offset - curr_offset < DEVLINK_REGION_READ_CHUNK_SIZE)
4859 data_size = end_offset - curr_offset;
4860 else
4861 data_size = DEVLINK_REGION_READ_CHUNK_SIZE;
4862
4863 data = &snapshot->data[curr_offset];
4864 err = devlink_nl_cmd_region_read_chunk_fill(skb, devlink,
4865 data, data_size,
4866 curr_offset);
4867 if (err)
4868 break;
4869
4870 curr_offset += data_size;
4871 }
4872 *new_offset = curr_offset;
4873
4874 return err;
4875}
4876
4877static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
4878 struct netlink_callback *cb)
4879{
ee85da53 4880 const struct genl_dumpit_info *info = genl_dumpit_info(cb);
5a46b062 4881 u64 ret_offset, start_offset, end_offset = U64_MAX;
ee85da53 4882 struct nlattr **attrs = info->attrs;
544e7c33 4883 struct devlink_port *port = NULL;
4e54795a
AV
4884 struct devlink_region *region;
4885 struct nlattr *chunks_attr;
4886 const char *region_name;
4887 struct devlink *devlink;
544e7c33 4888 unsigned int index;
4e54795a
AV
4889 void *hdr;
4890 int err;
4891
4892 start_offset = *((u64 *)&cb->args[0]);
4893
dac7c08f 4894 mutex_lock(&devlink_mutex);
4e54795a 4895 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
fdd41ec2
PP
4896 if (IS_ERR(devlink)) {
4897 err = PTR_ERR(devlink);
dac7c08f 4898 goto out_dev;
fdd41ec2 4899 }
4e54795a 4900
4e54795a
AV
4901 mutex_lock(&devlink->lock);
4902
4903 if (!attrs[DEVLINK_ATTR_REGION_NAME] ||
fdd41ec2
PP
4904 !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) {
4905 err = -EINVAL;
4e54795a 4906 goto out_unlock;
fdd41ec2 4907 }
4e54795a 4908
544e7c33
AL
4909 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
4910 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
4911
4912 port = devlink_port_get_by_index(devlink, index);
4913 if (!port)
4914 return -ENODEV;
4915 }
4916
4e54795a 4917 region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]);
544e7c33
AL
4918
4919 if (port)
4920 region = devlink_port_region_get_by_name(port, region_name);
4921 else
4922 region = devlink_region_get_by_name(devlink, region_name);
4923
fdd41ec2
PP
4924 if (!region) {
4925 err = -EINVAL;
4e54795a 4926 goto out_unlock;
fdd41ec2 4927 }
4e54795a 4928
5a46b062
JK
4929 if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] &&
4930 attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) {
4931 if (!start_offset)
4932 start_offset =
4933 nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
4934
4935 end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
4936 end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]);
4937 }
4938
4939 if (end_offset > region->size)
4940 end_offset = region->size;
4941
d5b90e99 4942 /* return 0 if there is no further data to read */
5a46b062 4943 if (start_offset == end_offset) {
d5b90e99
JK
4944 err = 0;
4945 goto out_unlock;
4946 }
4947
4e54795a
AV
4948 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
4949 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
4950 DEVLINK_CMD_REGION_READ);
fdd41ec2
PP
4951 if (!hdr) {
4952 err = -EMSGSIZE;
4e54795a 4953 goto out_unlock;
fdd41ec2 4954 }
4e54795a
AV
4955
4956 err = devlink_nl_put_handle(skb, devlink);
4957 if (err)
4958 goto nla_put_failure;
4959
544e7c33
AL
4960 if (region->port)
4961 if (nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX,
4962 region->port->index))
4963 goto nla_put_failure;
4964
4e54795a
AV
4965 err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
4966 if (err)
4967 goto nla_put_failure;
4968
ae0be8de 4969 chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS);
fdd41ec2
PP
4970 if (!chunks_attr) {
4971 err = -EMSGSIZE;
4e54795a 4972 goto nla_put_failure;
fdd41ec2 4973 }
4e54795a 4974
4e54795a
AV
4975 err = devlink_nl_region_read_snapshot_fill(skb, devlink,
4976 region, attrs,
4977 start_offset,
5a46b062 4978 end_offset, &ret_offset);
4e54795a
AV
4979
4980 if (err && err != -EMSGSIZE)
4981 goto nla_put_failure;
4982
4983 /* Check if there was any progress done to prevent infinite loop */
fdd41ec2
PP
4984 if (ret_offset == start_offset) {
4985 err = -EINVAL;
4e54795a 4986 goto nla_put_failure;
fdd41ec2 4987 }
4e54795a
AV
4988
4989 *((u64 *)&cb->args[0]) = ret_offset;
4990
4991 nla_nest_end(skb, chunks_attr);
4992 genlmsg_end(skb, hdr);
4993 mutex_unlock(&devlink->lock);
4994 mutex_unlock(&devlink_mutex);
4995
4996 return skb->len;
4997
4998nla_put_failure:
4999 genlmsg_cancel(skb, hdr);
5000out_unlock:
5001 mutex_unlock(&devlink->lock);
dac7c08f 5002out_dev:
4e54795a 5003 mutex_unlock(&devlink_mutex);
fdd41ec2 5004 return err;
4e54795a
AV
5005}
5006
f9cf2288
JK
5007struct devlink_info_req {
5008 struct sk_buff *msg;
5009};
5010
5011int devlink_info_driver_name_put(struct devlink_info_req *req, const char *name)
5012{
5013 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRIVER_NAME, name);
5014}
5015EXPORT_SYMBOL_GPL(devlink_info_driver_name_put);
5016
5017int devlink_info_serial_number_put(struct devlink_info_req *req, const char *sn)
5018{
5019 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_SERIAL_NUMBER, sn);
5020}
5021EXPORT_SYMBOL_GPL(devlink_info_serial_number_put);
5022
b5872cd0
VV
5023int devlink_info_board_serial_number_put(struct devlink_info_req *req,
5024 const char *bsn)
5025{
5026 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_BOARD_SERIAL_NUMBER,
5027 bsn);
5028}
5029EXPORT_SYMBOL_GPL(devlink_info_board_serial_number_put);
5030
fc6fae7d
JK
5031static int devlink_info_version_put(struct devlink_info_req *req, int attr,
5032 const char *version_name,
5033 const char *version_value)
5034{
5035 struct nlattr *nest;
5036 int err;
5037
ae0be8de 5038 nest = nla_nest_start_noflag(req->msg, attr);
fc6fae7d
JK
5039 if (!nest)
5040 return -EMSGSIZE;
5041
5042 err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_NAME,
5043 version_name);
5044 if (err)
5045 goto nla_put_failure;
5046
5047 err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_VALUE,
5048 version_value);
5049 if (err)
5050 goto nla_put_failure;
5051
5052 nla_nest_end(req->msg, nest);
5053
5054 return 0;
5055
5056nla_put_failure:
5057 nla_nest_cancel(req->msg, nest);
5058 return err;
5059}
5060
5061int devlink_info_version_fixed_put(struct devlink_info_req *req,
5062 const char *version_name,
5063 const char *version_value)
5064{
5065 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_FIXED,
5066 version_name, version_value);
5067}
5068EXPORT_SYMBOL_GPL(devlink_info_version_fixed_put);
5069
5070int devlink_info_version_stored_put(struct devlink_info_req *req,
5071 const char *version_name,
5072 const char *version_value)
5073{
5074 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_STORED,
5075 version_name, version_value);
5076}
5077EXPORT_SYMBOL_GPL(devlink_info_version_stored_put);
5078
5079int devlink_info_version_running_put(struct devlink_info_req *req,
5080 const char *version_name,
5081 const char *version_value)
5082{
5083 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_RUNNING,
5084 version_name, version_value);
5085}
5086EXPORT_SYMBOL_GPL(devlink_info_version_running_put);
5087
f9cf2288
JK
5088static int
5089devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
5090 enum devlink_command cmd, u32 portid,
5091 u32 seq, int flags, struct netlink_ext_ack *extack)
5092{
5093 struct devlink_info_req req;
5094 void *hdr;
5095 int err;
5096
5097 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
5098 if (!hdr)
5099 return -EMSGSIZE;
5100
5101 err = -EMSGSIZE;
5102 if (devlink_nl_put_handle(msg, devlink))
5103 goto err_cancel_msg;
5104
5105 req.msg = msg;
5106 err = devlink->ops->info_get(devlink, &req, extack);
5107 if (err)
5108 goto err_cancel_msg;
5109
5110 genlmsg_end(msg, hdr);
5111 return 0;
5112
5113err_cancel_msg:
5114 genlmsg_cancel(msg, hdr);
5115 return err;
5116}
5117
5118static int devlink_nl_cmd_info_get_doit(struct sk_buff *skb,
5119 struct genl_info *info)
5120{
5121 struct devlink *devlink = info->user_ptr[0];
5122 struct sk_buff *msg;
5123 int err;
5124
be6fe1d8 5125 if (!devlink->ops->info_get)
f9cf2288
JK
5126 return -EOPNOTSUPP;
5127
5128 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5129 if (!msg)
5130 return -ENOMEM;
5131
5132 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
5133 info->snd_portid, info->snd_seq, 0,
5134 info->extack);
5135 if (err) {
5136 nlmsg_free(msg);
5137 return err;
5138 }
5139
5140 return genlmsg_reply(msg, info);
5141}
5142
5143static int devlink_nl_cmd_info_get_dumpit(struct sk_buff *msg,
5144 struct netlink_callback *cb)
5145{
5146 struct devlink *devlink;
5147 int start = cb->args[0];
5148 int idx = 0;
c62c2cfb 5149 int err = 0;
f9cf2288
JK
5150
5151 mutex_lock(&devlink_mutex);
5152 list_for_each_entry(devlink, &devlink_list, list) {
5153 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
5154 continue;
5155 if (idx < start) {
5156 idx++;
5157 continue;
5158 }
5159
c493b09b
JP
5160 if (!devlink->ops->info_get) {
5161 idx++;
5162 continue;
5163 }
5164
f9cf2288
JK
5165 mutex_lock(&devlink->lock);
5166 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
5167 NETLINK_CB(cb->skb).portid,
5168 cb->nlh->nlmsg_seq, NLM_F_MULTI,
5169 cb->extack);
5170 mutex_unlock(&devlink->lock);
82274d07
JK
5171 if (err == -EOPNOTSUPP)
5172 err = 0;
5173 else if (err)
f9cf2288
JK
5174 break;
5175 idx++;
5176 }
5177 mutex_unlock(&devlink_mutex);
5178
c62c2cfb
JP
5179 if (err != -EMSGSIZE)
5180 return err;
5181
f9cf2288
JK
5182 cb->args[0] = idx;
5183 return msg->len;
5184}
5185
1db64e87
EBE
5186struct devlink_fmsg_item {
5187 struct list_head list;
5188 int attrtype;
5189 u8 nla_type;
5190 u16 len;
d2afb41a 5191 int value[];
1db64e87
EBE
5192};
5193
5194struct devlink_fmsg {
5195 struct list_head item_list;
573ed90a
AL
5196 bool putting_binary; /* This flag forces enclosing of binary data
5197 * in an array brackets. It forces using
5198 * of designated API:
5199 * devlink_fmsg_binary_pair_nest_start()
5200 * devlink_fmsg_binary_pair_nest_end()
5201 */
1db64e87
EBE
5202};
5203
5204static struct devlink_fmsg *devlink_fmsg_alloc(void)
5205{
5206 struct devlink_fmsg *fmsg;
5207
5208 fmsg = kzalloc(sizeof(*fmsg), GFP_KERNEL);
5209 if (!fmsg)
5210 return NULL;
5211
5212 INIT_LIST_HEAD(&fmsg->item_list);
5213
5214 return fmsg;
5215}
5216
5217static void devlink_fmsg_free(struct devlink_fmsg *fmsg)
5218{
5219 struct devlink_fmsg_item *item, *tmp;
5220
5221 list_for_each_entry_safe(item, tmp, &fmsg->item_list, list) {
5222 list_del(&item->list);
5223 kfree(item);
5224 }
5225 kfree(fmsg);
5226}
5227
5228static int devlink_fmsg_nest_common(struct devlink_fmsg *fmsg,
5229 int attrtype)
5230{
5231 struct devlink_fmsg_item *item;
5232
5233 item = kzalloc(sizeof(*item), GFP_KERNEL);
5234 if (!item)
5235 return -ENOMEM;
5236
5237 item->attrtype = attrtype;
5238 list_add_tail(&item->list, &fmsg->item_list);
5239
5240 return 0;
5241}
5242
5243int devlink_fmsg_obj_nest_start(struct devlink_fmsg *fmsg)
5244{
573ed90a
AL
5245 if (fmsg->putting_binary)
5246 return -EINVAL;
5247
1db64e87
EBE
5248 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_OBJ_NEST_START);
5249}
5250EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_start);
5251
5252static int devlink_fmsg_nest_end(struct devlink_fmsg *fmsg)
5253{
573ed90a
AL
5254 if (fmsg->putting_binary)
5255 return -EINVAL;
5256
1db64e87
EBE
5257 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_NEST_END);
5258}
5259
5260int devlink_fmsg_obj_nest_end(struct devlink_fmsg *fmsg)
5261{
573ed90a
AL
5262 if (fmsg->putting_binary)
5263 return -EINVAL;
5264
1db64e87
EBE
5265 return devlink_fmsg_nest_end(fmsg);
5266}
5267EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_end);
5268
5269#define DEVLINK_FMSG_MAX_SIZE (GENLMSG_DEFAULT_SIZE - GENL_HDRLEN - NLA_HDRLEN)
5270
5271static int devlink_fmsg_put_name(struct devlink_fmsg *fmsg, const char *name)
5272{
5273 struct devlink_fmsg_item *item;
5274
573ed90a
AL
5275 if (fmsg->putting_binary)
5276 return -EINVAL;
5277
1db64e87
EBE
5278 if (strlen(name) + 1 > DEVLINK_FMSG_MAX_SIZE)
5279 return -EMSGSIZE;
5280
5281 item = kzalloc(sizeof(*item) + strlen(name) + 1, GFP_KERNEL);
5282 if (!item)
5283 return -ENOMEM;
5284
5285 item->nla_type = NLA_NUL_STRING;
5286 item->len = strlen(name) + 1;
5287 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_NAME;
5288 memcpy(&item->value, name, item->len);
5289 list_add_tail(&item->list, &fmsg->item_list);
5290
5291 return 0;
5292}
5293
5294int devlink_fmsg_pair_nest_start(struct devlink_fmsg *fmsg, const char *name)
5295{
5296 int err;
5297
573ed90a
AL
5298 if (fmsg->putting_binary)
5299 return -EINVAL;
5300
1db64e87
EBE
5301 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_PAIR_NEST_START);
5302 if (err)
5303 return err;
5304
5305 err = devlink_fmsg_put_name(fmsg, name);
5306 if (err)
5307 return err;
5308
5309 return 0;
5310}
5311EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_start);
5312
5313int devlink_fmsg_pair_nest_end(struct devlink_fmsg *fmsg)
5314{
573ed90a
AL
5315 if (fmsg->putting_binary)
5316 return -EINVAL;
5317
1db64e87
EBE
5318 return devlink_fmsg_nest_end(fmsg);
5319}
5320EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_end);
5321
5322int devlink_fmsg_arr_pair_nest_start(struct devlink_fmsg *fmsg,
5323 const char *name)
5324{
5325 int err;
5326
573ed90a
AL
5327 if (fmsg->putting_binary)
5328 return -EINVAL;
5329
1db64e87
EBE
5330 err = devlink_fmsg_pair_nest_start(fmsg, name);
5331 if (err)
5332 return err;
5333
5334 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_ARR_NEST_START);
5335 if (err)
5336 return err;
5337
5338 return 0;
5339}
5340EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_start);
5341
5342int devlink_fmsg_arr_pair_nest_end(struct devlink_fmsg *fmsg)
5343{
5344 int err;
5345
573ed90a
AL
5346 if (fmsg->putting_binary)
5347 return -EINVAL;
5348
1db64e87
EBE
5349 err = devlink_fmsg_nest_end(fmsg);
5350 if (err)
5351 return err;
5352
5353 err = devlink_fmsg_nest_end(fmsg);
5354 if (err)
5355 return err;
5356
5357 return 0;
5358}
5359EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_end);
5360
573ed90a
AL
5361int devlink_fmsg_binary_pair_nest_start(struct devlink_fmsg *fmsg,
5362 const char *name)
5363{
5364 int err;
5365
5366 err = devlink_fmsg_arr_pair_nest_start(fmsg, name);
5367 if (err)
5368 return err;
5369
5370 fmsg->putting_binary = true;
5371 return err;
5372}
5373EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_nest_start);
5374
5375int devlink_fmsg_binary_pair_nest_end(struct devlink_fmsg *fmsg)
5376{
5377 if (!fmsg->putting_binary)
5378 return -EINVAL;
5379
5380 fmsg->putting_binary = false;
5381 return devlink_fmsg_arr_pair_nest_end(fmsg);
5382}
5383EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_nest_end);
5384
1db64e87
EBE
5385static int devlink_fmsg_put_value(struct devlink_fmsg *fmsg,
5386 const void *value, u16 value_len,
5387 u8 value_nla_type)
5388{
5389 struct devlink_fmsg_item *item;
5390
5391 if (value_len > DEVLINK_FMSG_MAX_SIZE)
5392 return -EMSGSIZE;
5393
5394 item = kzalloc(sizeof(*item) + value_len, GFP_KERNEL);
5395 if (!item)
5396 return -ENOMEM;
5397
5398 item->nla_type = value_nla_type;
5399 item->len = value_len;
5400 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
5401 memcpy(&item->value, value, item->len);
5402 list_add_tail(&item->list, &fmsg->item_list);
5403
5404 return 0;
5405}
5406
5407int devlink_fmsg_bool_put(struct devlink_fmsg *fmsg, bool value)
5408{
573ed90a
AL
5409 if (fmsg->putting_binary)
5410 return -EINVAL;
5411
1db64e87
EBE
5412 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_FLAG);
5413}
5414EXPORT_SYMBOL_GPL(devlink_fmsg_bool_put);
5415
5416int devlink_fmsg_u8_put(struct devlink_fmsg *fmsg, u8 value)
5417{
573ed90a
AL
5418 if (fmsg->putting_binary)
5419 return -EINVAL;
5420
1db64e87
EBE
5421 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U8);
5422}
5423EXPORT_SYMBOL_GPL(devlink_fmsg_u8_put);
5424
5425int devlink_fmsg_u32_put(struct devlink_fmsg *fmsg, u32 value)
5426{
573ed90a
AL
5427 if (fmsg->putting_binary)
5428 return -EINVAL;
5429
1db64e87
EBE
5430 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U32);
5431}
5432EXPORT_SYMBOL_GPL(devlink_fmsg_u32_put);
5433
5434int devlink_fmsg_u64_put(struct devlink_fmsg *fmsg, u64 value)
5435{
573ed90a
AL
5436 if (fmsg->putting_binary)
5437 return -EINVAL;
5438
1db64e87
EBE
5439 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U64);
5440}
5441EXPORT_SYMBOL_GPL(devlink_fmsg_u64_put);
5442
5443int devlink_fmsg_string_put(struct devlink_fmsg *fmsg, const char *value)
5444{
573ed90a
AL
5445 if (fmsg->putting_binary)
5446 return -EINVAL;
5447
1db64e87
EBE
5448 return devlink_fmsg_put_value(fmsg, value, strlen(value) + 1,
5449 NLA_NUL_STRING);
5450}
5451EXPORT_SYMBOL_GPL(devlink_fmsg_string_put);
5452
573ed90a
AL
5453int devlink_fmsg_binary_put(struct devlink_fmsg *fmsg, const void *value,
5454 u16 value_len)
1db64e87 5455{
573ed90a
AL
5456 if (!fmsg->putting_binary)
5457 return -EINVAL;
5458
1db64e87
EBE
5459 return devlink_fmsg_put_value(fmsg, value, value_len, NLA_BINARY);
5460}
573ed90a 5461EXPORT_SYMBOL_GPL(devlink_fmsg_binary_put);
1db64e87
EBE
5462
5463int devlink_fmsg_bool_pair_put(struct devlink_fmsg *fmsg, const char *name,
5464 bool value)
5465{
5466 int err;
5467
5468 err = devlink_fmsg_pair_nest_start(fmsg, name);
5469 if (err)
5470 return err;
5471
5472 err = devlink_fmsg_bool_put(fmsg, value);
5473 if (err)
5474 return err;
5475
5476 err = devlink_fmsg_pair_nest_end(fmsg);
5477 if (err)
5478 return err;
5479
5480 return 0;
5481}
5482EXPORT_SYMBOL_GPL(devlink_fmsg_bool_pair_put);
5483
5484int devlink_fmsg_u8_pair_put(struct devlink_fmsg *fmsg, const char *name,
5485 u8 value)
5486{
5487 int err;
5488
5489 err = devlink_fmsg_pair_nest_start(fmsg, name);
5490 if (err)
5491 return err;
5492
5493 err = devlink_fmsg_u8_put(fmsg, value);
5494 if (err)
5495 return err;
5496
5497 err = devlink_fmsg_pair_nest_end(fmsg);
5498 if (err)
5499 return err;
5500
5501 return 0;
5502}
5503EXPORT_SYMBOL_GPL(devlink_fmsg_u8_pair_put);
5504
5505int devlink_fmsg_u32_pair_put(struct devlink_fmsg *fmsg, const char *name,
5506 u32 value)
5507{
5508 int err;
5509
5510 err = devlink_fmsg_pair_nest_start(fmsg, name);
5511 if (err)
5512 return err;
5513
5514 err = devlink_fmsg_u32_put(fmsg, value);
5515 if (err)
5516 return err;
5517
5518 err = devlink_fmsg_pair_nest_end(fmsg);
5519 if (err)
5520 return err;
5521
5522 return 0;
5523}
5524EXPORT_SYMBOL_GPL(devlink_fmsg_u32_pair_put);
5525
5526int devlink_fmsg_u64_pair_put(struct devlink_fmsg *fmsg, const char *name,
5527 u64 value)
5528{
5529 int err;
5530
5531 err = devlink_fmsg_pair_nest_start(fmsg, name);
5532 if (err)
5533 return err;
5534
5535 err = devlink_fmsg_u64_put(fmsg, value);
5536 if (err)
5537 return err;
5538
5539 err = devlink_fmsg_pair_nest_end(fmsg);
5540 if (err)
5541 return err;
5542
5543 return 0;
5544}
5545EXPORT_SYMBOL_GPL(devlink_fmsg_u64_pair_put);
5546
5547int devlink_fmsg_string_pair_put(struct devlink_fmsg *fmsg, const char *name,
5548 const char *value)
5549{
5550 int err;
5551
5552 err = devlink_fmsg_pair_nest_start(fmsg, name);
5553 if (err)
5554 return err;
5555
5556 err = devlink_fmsg_string_put(fmsg, value);
5557 if (err)
5558 return err;
5559
5560 err = devlink_fmsg_pair_nest_end(fmsg);
5561 if (err)
5562 return err;
5563
5564 return 0;
5565}
5566EXPORT_SYMBOL_GPL(devlink_fmsg_string_pair_put);
5567
5568int devlink_fmsg_binary_pair_put(struct devlink_fmsg *fmsg, const char *name,
e2cde864 5569 const void *value, u32 value_len)
1db64e87 5570{
e2cde864 5571 u32 data_size;
573ed90a 5572 int end_err;
e2cde864 5573 u32 offset;
1db64e87
EBE
5574 int err;
5575
573ed90a 5576 err = devlink_fmsg_binary_pair_nest_start(fmsg, name);
1db64e87
EBE
5577 if (err)
5578 return err;
5579
e2cde864
AL
5580 for (offset = 0; offset < value_len; offset += data_size) {
5581 data_size = value_len - offset;
5582 if (data_size > DEVLINK_FMSG_MAX_SIZE)
5583 data_size = DEVLINK_FMSG_MAX_SIZE;
5584 err = devlink_fmsg_binary_put(fmsg, value + offset, data_size);
5585 if (err)
573ed90a
AL
5586 break;
5587 /* Exit from loop with a break (instead of
5588 * return) to make sure putting_binary is turned off in
5589 * devlink_fmsg_binary_pair_nest_end
5590 */
e2cde864 5591 }
1db64e87 5592
573ed90a
AL
5593 end_err = devlink_fmsg_binary_pair_nest_end(fmsg);
5594 if (end_err)
5595 err = end_err;
1db64e87 5596
573ed90a 5597 return err;
1db64e87
EBE
5598}
5599EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_put);
5600
5601static int
5602devlink_fmsg_item_fill_type(struct devlink_fmsg_item *msg, struct sk_buff *skb)
5603{
5604 switch (msg->nla_type) {
5605 case NLA_FLAG:
5606 case NLA_U8:
5607 case NLA_U32:
5608 case NLA_U64:
5609 case NLA_NUL_STRING:
5610 case NLA_BINARY:
5611 return nla_put_u8(skb, DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE,
5612 msg->nla_type);
5613 default:
5614 return -EINVAL;
5615 }
5616}
5617
5618static int
5619devlink_fmsg_item_fill_data(struct devlink_fmsg_item *msg, struct sk_buff *skb)
5620{
5621 int attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
5622 u8 tmp;
5623
5624 switch (msg->nla_type) {
5625 case NLA_FLAG:
5626 /* Always provide flag data, regardless of its value */
5627 tmp = *(bool *) msg->value;
5628
5629 return nla_put_u8(skb, attrtype, tmp);
5630 case NLA_U8:
5631 return nla_put_u8(skb, attrtype, *(u8 *) msg->value);
5632 case NLA_U32:
5633 return nla_put_u32(skb, attrtype, *(u32 *) msg->value);
5634 case NLA_U64:
5635 return nla_put_u64_64bit(skb, attrtype, *(u64 *) msg->value,
5636 DEVLINK_ATTR_PAD);
5637 case NLA_NUL_STRING:
5638 return nla_put_string(skb, attrtype, (char *) &msg->value);
5639 case NLA_BINARY:
5640 return nla_put(skb, attrtype, msg->len, (void *) &msg->value);
5641 default:
5642 return -EINVAL;
5643 }
5644}
5645
5646static int
5647devlink_fmsg_prepare_skb(struct devlink_fmsg *fmsg, struct sk_buff *skb,
5648 int *start)
5649{
5650 struct devlink_fmsg_item *item;
5651 struct nlattr *fmsg_nlattr;
5652 int i = 0;
5653 int err;
5654
ae0be8de 5655 fmsg_nlattr = nla_nest_start_noflag(skb, DEVLINK_ATTR_FMSG);
1db64e87
EBE
5656 if (!fmsg_nlattr)
5657 return -EMSGSIZE;
5658
5659 list_for_each_entry(item, &fmsg->item_list, list) {
5660 if (i < *start) {
5661 i++;
5662 continue;
5663 }
5664
5665 switch (item->attrtype) {
5666 case DEVLINK_ATTR_FMSG_OBJ_NEST_START:
5667 case DEVLINK_ATTR_FMSG_PAIR_NEST_START:
5668 case DEVLINK_ATTR_FMSG_ARR_NEST_START:
5669 case DEVLINK_ATTR_FMSG_NEST_END:
5670 err = nla_put_flag(skb, item->attrtype);
5671 break;
5672 case DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA:
5673 err = devlink_fmsg_item_fill_type(item, skb);
5674 if (err)
5675 break;
5676 err = devlink_fmsg_item_fill_data(item, skb);
5677 break;
5678 case DEVLINK_ATTR_FMSG_OBJ_NAME:
5679 err = nla_put_string(skb, item->attrtype,
5680 (char *) &item->value);
5681 break;
5682 default:
5683 err = -EINVAL;
5684 break;
5685 }
5686 if (!err)
5687 *start = ++i;
5688 else
5689 break;
5690 }
5691
5692 nla_nest_end(skb, fmsg_nlattr);
5693 return err;
5694}
5695
5696static int devlink_fmsg_snd(struct devlink_fmsg *fmsg,
5697 struct genl_info *info,
5698 enum devlink_command cmd, int flags)
5699{
5700 struct nlmsghdr *nlh;
5701 struct sk_buff *skb;
5702 bool last = false;
5703 int index = 0;
5704 void *hdr;
5705 int err;
5706
5707 while (!last) {
5708 int tmp_index = index;
5709
5710 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
5711 if (!skb)
5712 return -ENOMEM;
5713
5714 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
5715 &devlink_nl_family, flags | NLM_F_MULTI, cmd);
5716 if (!hdr) {
5717 err = -EMSGSIZE;
5718 goto nla_put_failure;
5719 }
5720
5721 err = devlink_fmsg_prepare_skb(fmsg, skb, &index);
5722 if (!err)
5723 last = true;
5724 else if (err != -EMSGSIZE || tmp_index == index)
5725 goto nla_put_failure;
5726
5727 genlmsg_end(skb, hdr);
5728 err = genlmsg_reply(skb, info);
5729 if (err)
5730 return err;
5731 }
5732
5733 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
5734 if (!skb)
5735 return -ENOMEM;
5736 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
5737 NLMSG_DONE, 0, flags | NLM_F_MULTI);
5738 if (!nlh) {
5739 err = -EMSGSIZE;
5740 goto nla_put_failure;
5741 }
1db64e87 5742
fde55ea7 5743 return genlmsg_reply(skb, info);
1db64e87
EBE
5744
5745nla_put_failure:
5746 nlmsg_free(skb);
5747 return err;
5748}
5749
e44ef4e4
AL
5750static int devlink_fmsg_dumpit(struct devlink_fmsg *fmsg, struct sk_buff *skb,
5751 struct netlink_callback *cb,
5752 enum devlink_command cmd)
5753{
5754 int index = cb->args[0];
5755 int tmp_index = index;
5756 void *hdr;
5757 int err;
5758
5759 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
5760 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, cmd);
5761 if (!hdr) {
5762 err = -EMSGSIZE;
5763 goto nla_put_failure;
5764 }
5765
5766 err = devlink_fmsg_prepare_skb(fmsg, skb, &index);
5767 if ((err && err != -EMSGSIZE) || tmp_index == index)
5768 goto nla_put_failure;
5769
5770 cb->args[0] = index;
5771 genlmsg_end(skb, hdr);
5772 return skb->len;
5773
5774nla_put_failure:
5775 genlmsg_cancel(skb, hdr);
5776 return err;
5777}
5778
a0bdcc59
EBE
5779struct devlink_health_reporter {
5780 struct list_head list;
5781 void *priv;
5782 const struct devlink_health_reporter_ops *ops;
5783 struct devlink *devlink;
f4f54166 5784 struct devlink_port *devlink_port;
c8e1da0b
EBE
5785 struct devlink_fmsg *dump_fmsg;
5786 struct mutex dump_lock; /* lock parallel read/write from dump buffers */
a0bdcc59
EBE
5787 u64 graceful_period;
5788 bool auto_recover;
48bb52c8 5789 bool auto_dump;
a0bdcc59 5790 u8 health_state;
c8e1da0b 5791 u64 dump_ts;
d279505b 5792 u64 dump_real_ts;
c8e1da0b
EBE
5793 u64 error_count;
5794 u64 recovery_count;
5795 u64 last_recovery_ts;
b587bdaf 5796 refcount_t refcount;
c8e1da0b
EBE
5797};
5798
a0bdcc59
EBE
5799void *
5800devlink_health_reporter_priv(struct devlink_health_reporter *reporter)
5801{
5802 return reporter->priv;
5803}
5804EXPORT_SYMBOL_GPL(devlink_health_reporter_priv);
5805
5806static struct devlink_health_reporter *
bd821005
VT
5807__devlink_health_reporter_find_by_name(struct list_head *reporter_list,
5808 struct mutex *list_lock,
5809 const char *reporter_name)
a0bdcc59
EBE
5810{
5811 struct devlink_health_reporter *reporter;
5812
bd821005
VT
5813 lockdep_assert_held(list_lock);
5814 list_for_each_entry(reporter, reporter_list, list)
a0bdcc59
EBE
5815 if (!strcmp(reporter->ops->name, reporter_name))
5816 return reporter;
5817 return NULL;
5818}
5819
bd821005
VT
5820static struct devlink_health_reporter *
5821devlink_health_reporter_find_by_name(struct devlink *devlink,
5822 const char *reporter_name)
5823{
5824 return __devlink_health_reporter_find_by_name(&devlink->reporter_list,
5825 &devlink->reporters_lock,
5826 reporter_name);
5827}
5828
f4f54166
VT
5829static struct devlink_health_reporter *
5830devlink_port_health_reporter_find_by_name(struct devlink_port *devlink_port,
5831 const char *reporter_name)
5832{
5833 return __devlink_health_reporter_find_by_name(&devlink_port->reporter_list,
5834 &devlink_port->reporters_lock,
5835 reporter_name);
5836}
5837
c57544b3
VT
5838static struct devlink_health_reporter *
5839__devlink_health_reporter_create(struct devlink *devlink,
5840 const struct devlink_health_reporter_ops *ops,
5841 u64 graceful_period, void *priv)
5842{
5843 struct devlink_health_reporter *reporter;
5844
5845 if (WARN_ON(graceful_period && !ops->recover))
5846 return ERR_PTR(-EINVAL);
5847
5848 reporter = kzalloc(sizeof(*reporter), GFP_KERNEL);
5849 if (!reporter)
5850 return ERR_PTR(-ENOMEM);
5851
5852 reporter->priv = priv;
5853 reporter->ops = ops;
5854 reporter->devlink = devlink;
5855 reporter->graceful_period = graceful_period;
5856 reporter->auto_recover = !!ops->recover;
5857 reporter->auto_dump = !!ops->dump;
5858 mutex_init(&reporter->dump_lock);
5859 refcount_set(&reporter->refcount, 1);
5860 return reporter;
5861}
5862
15c724b9
VT
5863/**
5864 * devlink_port_health_reporter_create - create devlink health reporter for
5865 * specified port instance
5866 *
5867 * @port: devlink_port which should contain the new reporter
5868 * @ops: ops
5869 * @graceful_period: to avoid recovery loops, in msecs
5870 * @priv: priv
5871 */
5872struct devlink_health_reporter *
5873devlink_port_health_reporter_create(struct devlink_port *port,
5874 const struct devlink_health_reporter_ops *ops,
5875 u64 graceful_period, void *priv)
5876{
5877 struct devlink_health_reporter *reporter;
5878
5879 mutex_lock(&port->reporters_lock);
5880 if (__devlink_health_reporter_find_by_name(&port->reporter_list,
5881 &port->reporters_lock, ops->name)) {
5882 reporter = ERR_PTR(-EEXIST);
5883 goto unlock;
5884 }
5885
5886 reporter = __devlink_health_reporter_create(port->devlink, ops,
5887 graceful_period, priv);
5888 if (IS_ERR(reporter))
5889 goto unlock;
5890
5891 reporter->devlink_port = port;
5892 list_add_tail(&reporter->list, &port->reporter_list);
5893unlock:
5894 mutex_unlock(&port->reporters_lock);
5895 return reporter;
5896}
5897EXPORT_SYMBOL_GPL(devlink_port_health_reporter_create);
5898
a0bdcc59
EBE
5899/**
5900 * devlink_health_reporter_create - create devlink health reporter
5901 *
5902 * @devlink: devlink
5903 * @ops: ops
5904 * @graceful_period: to avoid recovery loops, in msecs
a0bdcc59
EBE
5905 * @priv: priv
5906 */
5907struct devlink_health_reporter *
5908devlink_health_reporter_create(struct devlink *devlink,
5909 const struct devlink_health_reporter_ops *ops,
ba7d16c7 5910 u64 graceful_period, void *priv)
a0bdcc59
EBE
5911{
5912 struct devlink_health_reporter *reporter;
5913
b587bdaf 5914 mutex_lock(&devlink->reporters_lock);
a0bdcc59
EBE
5915 if (devlink_health_reporter_find_by_name(devlink, ops->name)) {
5916 reporter = ERR_PTR(-EEXIST);
5917 goto unlock;
5918 }
5919
c57544b3
VT
5920 reporter = __devlink_health_reporter_create(devlink, ops,
5921 graceful_period, priv);
5922 if (IS_ERR(reporter))
a0bdcc59 5923 goto unlock;
a0bdcc59 5924
a0bdcc59
EBE
5925 list_add_tail(&reporter->list, &devlink->reporter_list);
5926unlock:
b587bdaf 5927 mutex_unlock(&devlink->reporters_lock);
a0bdcc59
EBE
5928 return reporter;
5929}
5930EXPORT_SYMBOL_GPL(devlink_health_reporter_create);
5931
3c5584bf
VT
5932static void
5933devlink_health_reporter_free(struct devlink_health_reporter *reporter)
5934{
5935 mutex_destroy(&reporter->dump_lock);
5936 if (reporter->dump_fmsg)
5937 devlink_fmsg_free(reporter->dump_fmsg);
5938 kfree(reporter);
5939}
5940
5941static void
5942devlink_health_reporter_put(struct devlink_health_reporter *reporter)
5943{
5944 if (refcount_dec_and_test(&reporter->refcount))
5945 devlink_health_reporter_free(reporter);
5946}
5947
5948static void
5949__devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
5950{
5951 list_del(&reporter->list);
5952 devlink_health_reporter_put(reporter);
5953}
5954
a0bdcc59
EBE
5955/**
5956 * devlink_health_reporter_destroy - destroy devlink health reporter
5957 *
5958 * @reporter: devlink health reporter to destroy
5959 */
5960void
5961devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
5962{
5d037b4d
IS
5963 struct mutex *lock = &reporter->devlink->reporters_lock;
5964
5965 mutex_lock(lock);
3c5584bf 5966 __devlink_health_reporter_destroy(reporter);
5d037b4d 5967 mutex_unlock(lock);
a0bdcc59
EBE
5968}
5969EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
5970
15c724b9
VT
5971/**
5972 * devlink_port_health_reporter_destroy - destroy devlink port health reporter
5973 *
5974 * @reporter: devlink health reporter to destroy
5975 */
5976void
5977devlink_port_health_reporter_destroy(struct devlink_health_reporter *reporter)
5978{
5d037b4d
IS
5979 struct mutex *lock = &reporter->devlink_port->reporters_lock;
5980
5981 mutex_lock(lock);
15c724b9 5982 __devlink_health_reporter_destroy(reporter);
5d037b4d 5983 mutex_unlock(lock);
15c724b9
VT
5984}
5985EXPORT_SYMBOL_GPL(devlink_port_health_reporter_destroy);
5986
6ec8b6cd
MS
5987static int
5988devlink_nl_health_reporter_fill(struct sk_buff *msg,
5989 struct devlink *devlink,
5990 struct devlink_health_reporter *reporter,
5991 enum devlink_command cmd, u32 portid,
5992 u32 seq, int flags)
5993{
5994 struct nlattr *reporter_attr;
5995 void *hdr;
5996
5997 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
5998 if (!hdr)
5999 return -EMSGSIZE;
6000
6001 if (devlink_nl_put_handle(msg, devlink))
6002 goto genlmsg_cancel;
6003
f4f54166
VT
6004 if (reporter->devlink_port) {
6005 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, reporter->devlink_port->index))
6006 goto genlmsg_cancel;
6007 }
6ec8b6cd
MS
6008 reporter_attr = nla_nest_start_noflag(msg,
6009 DEVLINK_ATTR_HEALTH_REPORTER);
6010 if (!reporter_attr)
6011 goto genlmsg_cancel;
6012 if (nla_put_string(msg, DEVLINK_ATTR_HEALTH_REPORTER_NAME,
6013 reporter->ops->name))
6014 goto reporter_nest_cancel;
6015 if (nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_STATE,
6016 reporter->health_state))
6017 goto reporter_nest_cancel;
6018 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_ERR_COUNT,
6019 reporter->error_count, DEVLINK_ATTR_PAD))
6020 goto reporter_nest_cancel;
6021 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_RECOVER_COUNT,
6022 reporter->recovery_count, DEVLINK_ATTR_PAD))
6023 goto reporter_nest_cancel;
6024 if (reporter->ops->recover &&
6025 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD,
6026 reporter->graceful_period,
6027 DEVLINK_ATTR_PAD))
6028 goto reporter_nest_cancel;
6029 if (reporter->ops->recover &&
6030 nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER,
6031 reporter->auto_recover))
6032 goto reporter_nest_cancel;
6033 if (reporter->dump_fmsg &&
6034 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS,
6035 jiffies_to_msecs(reporter->dump_ts),
6036 DEVLINK_ATTR_PAD))
6037 goto reporter_nest_cancel;
6038 if (reporter->dump_fmsg &&
6039 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS_NS,
6040 reporter->dump_real_ts, DEVLINK_ATTR_PAD))
6041 goto reporter_nest_cancel;
48bb52c8
EBE
6042 if (reporter->ops->dump &&
6043 nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP,
6044 reporter->auto_dump))
6045 goto reporter_nest_cancel;
6ec8b6cd
MS
6046
6047 nla_nest_end(msg, reporter_attr);
6048 genlmsg_end(msg, hdr);
6049 return 0;
6050
6051reporter_nest_cancel:
6052 nla_nest_end(msg, reporter_attr);
6053genlmsg_cancel:
6054 genlmsg_cancel(msg, hdr);
6055 return -EMSGSIZE;
6056}
6057
6058static void devlink_recover_notify(struct devlink_health_reporter *reporter,
6059 enum devlink_command cmd)
6060{
6061 struct sk_buff *msg;
6062 int err;
6063
6064 WARN_ON(cmd != DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
6065
6066 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
6067 if (!msg)
6068 return;
6069
6070 err = devlink_nl_health_reporter_fill(msg, reporter->devlink,
6071 reporter, cmd, 0, 0, 0);
6072 if (err) {
6073 nlmsg_free(msg);
6074 return;
6075 }
6076
6077 genlmsg_multicast_netns(&devlink_nl_family,
6078 devlink_net(reporter->devlink),
6079 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
6080}
6081
6181e5cb
VG
6082void
6083devlink_health_reporter_recovery_done(struct devlink_health_reporter *reporter)
6084{
6085 reporter->recovery_count++;
6086 reporter->last_recovery_ts = jiffies;
6087}
6088EXPORT_SYMBOL_GPL(devlink_health_reporter_recovery_done);
6089
c8e1da0b
EBE
6090static int
6091devlink_health_reporter_recover(struct devlink_health_reporter *reporter,
e7a98105 6092 void *priv_ctx, struct netlink_ext_ack *extack)
c8e1da0b
EBE
6093{
6094 int err;
6095
40281820
JP
6096 if (reporter->health_state == DEVLINK_HEALTH_REPORTER_STATE_HEALTHY)
6097 return 0;
6098
c8e1da0b
EBE
6099 if (!reporter->ops->recover)
6100 return -EOPNOTSUPP;
6101
e7a98105 6102 err = reporter->ops->recover(reporter, priv_ctx, extack);
c8e1da0b
EBE
6103 if (err)
6104 return err;
6105
6181e5cb 6106 devlink_health_reporter_recovery_done(reporter);
c8e1da0b 6107 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY;
6ec8b6cd 6108 devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
c8e1da0b
EBE
6109
6110 return 0;
6111}
6112
6113static void
6114devlink_health_dump_clear(struct devlink_health_reporter *reporter)
6115{
6116 if (!reporter->dump_fmsg)
6117 return;
6118 devlink_fmsg_free(reporter->dump_fmsg);
6119 reporter->dump_fmsg = NULL;
6120}
6121
6122static int devlink_health_do_dump(struct devlink_health_reporter *reporter,
e7a98105
JP
6123 void *priv_ctx,
6124 struct netlink_ext_ack *extack)
c8e1da0b
EBE
6125{
6126 int err;
6127
6128 if (!reporter->ops->dump)
6129 return 0;
6130
6131 if (reporter->dump_fmsg)
6132 return 0;
6133
6134 reporter->dump_fmsg = devlink_fmsg_alloc();
6135 if (!reporter->dump_fmsg) {
6136 err = -ENOMEM;
6137 return err;
6138 }
6139
6140 err = devlink_fmsg_obj_nest_start(reporter->dump_fmsg);
6141 if (err)
6142 goto dump_err;
6143
6144 err = reporter->ops->dump(reporter, reporter->dump_fmsg,
e7a98105 6145 priv_ctx, extack);
c8e1da0b
EBE
6146 if (err)
6147 goto dump_err;
6148
6149 err = devlink_fmsg_obj_nest_end(reporter->dump_fmsg);
6150 if (err)
6151 goto dump_err;
6152
6153 reporter->dump_ts = jiffies;
d279505b 6154 reporter->dump_real_ts = ktime_get_real_ns();
c8e1da0b
EBE
6155
6156 return 0;
6157
6158dump_err:
6159 devlink_health_dump_clear(reporter);
6160 return err;
6161}
6162
6163int devlink_health_report(struct devlink_health_reporter *reporter,
6164 const char *msg, void *priv_ctx)
6165{
a0a21adb 6166 enum devlink_health_reporter_state prev_health_state;
c8e1da0b 6167 struct devlink *devlink = reporter->devlink;
bea0c5c9 6168 unsigned long recover_ts_threshold;
c8e1da0b
EBE
6169
6170 /* write a log message of the current error */
6171 WARN_ON(!msg);
6172 trace_devlink_health_report(devlink, reporter->ops->name, msg);
6173 reporter->error_count++;
a0a21adb
EBE
6174 prev_health_state = reporter->health_state;
6175 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
6ec8b6cd 6176 devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
c8e1da0b
EBE
6177
6178 /* abort if the previous error wasn't recovered */
bea0c5c9
AL
6179 recover_ts_threshold = reporter->last_recovery_ts +
6180 msecs_to_jiffies(reporter->graceful_period);
c8e1da0b 6181 if (reporter->auto_recover &&
a0a21adb 6182 (prev_health_state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY ||
bea0c5c9
AL
6183 (reporter->last_recovery_ts && reporter->recovery_count &&
6184 time_is_after_jiffies(recover_ts_threshold)))) {
c8e1da0b
EBE
6185 trace_devlink_health_recover_aborted(devlink,
6186 reporter->ops->name,
6187 reporter->health_state,
6188 jiffies -
6189 reporter->last_recovery_ts);
6190 return -ECANCELED;
6191 }
6192
6193 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
6194
48bb52c8
EBE
6195 if (reporter->auto_dump) {
6196 mutex_lock(&reporter->dump_lock);
6197 /* store current dump of current error, for later analysis */
6198 devlink_health_do_dump(reporter, priv_ctx, NULL);
6199 mutex_unlock(&reporter->dump_lock);
6200 }
c8e1da0b
EBE
6201
6202 if (reporter->auto_recover)
e7a98105
JP
6203 return devlink_health_reporter_recover(reporter,
6204 priv_ctx, NULL);
c8e1da0b
EBE
6205
6206 return 0;
6207}
6208EXPORT_SYMBOL_GPL(devlink_health_report);
6209
7afe335a 6210static struct devlink_health_reporter *
e44ef4e4
AL
6211devlink_health_reporter_get_from_attrs(struct devlink *devlink,
6212 struct nlattr **attrs)
7afe335a 6213{
b587bdaf 6214 struct devlink_health_reporter *reporter;
f4f54166 6215 struct devlink_port *devlink_port;
7afe335a
EBE
6216 char *reporter_name;
6217
e44ef4e4 6218 if (!attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME])
7afe335a
EBE
6219 return NULL;
6220
e44ef4e4 6221 reporter_name = nla_data(attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]);
f4f54166
VT
6222 devlink_port = devlink_port_get_from_attrs(devlink, attrs);
6223 if (IS_ERR(devlink_port)) {
6224 mutex_lock(&devlink->reporters_lock);
6225 reporter = devlink_health_reporter_find_by_name(devlink, reporter_name);
6226 if (reporter)
6227 refcount_inc(&reporter->refcount);
6228 mutex_unlock(&devlink->reporters_lock);
6229 } else {
6230 mutex_lock(&devlink_port->reporters_lock);
6231 reporter = devlink_port_health_reporter_find_by_name(devlink_port, reporter_name);
6232 if (reporter)
6233 refcount_inc(&reporter->refcount);
6234 mutex_unlock(&devlink_port->reporters_lock);
6235 }
6236
b587bdaf
MS
6237 return reporter;
6238}
6239
e44ef4e4
AL
6240static struct devlink_health_reporter *
6241devlink_health_reporter_get_from_info(struct devlink *devlink,
6242 struct genl_info *info)
6243{
6244 return devlink_health_reporter_get_from_attrs(devlink, info->attrs);
6245}
6246
6247static struct devlink_health_reporter *
6248devlink_health_reporter_get_from_cb(struct netlink_callback *cb)
6249{
ee85da53 6250 const struct genl_dumpit_info *info = genl_dumpit_info(cb);
e44ef4e4 6251 struct devlink_health_reporter *reporter;
ee85da53 6252 struct nlattr **attrs = info->attrs;
e44ef4e4 6253 struct devlink *devlink;
e44ef4e4
AL
6254
6255 mutex_lock(&devlink_mutex);
6256 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
6257 if (IS_ERR(devlink))
6258 goto unlock;
6259
6260 reporter = devlink_health_reporter_get_from_attrs(devlink, attrs);
6261 mutex_unlock(&devlink_mutex);
e44ef4e4
AL
6262 return reporter;
6263unlock:
6264 mutex_unlock(&devlink_mutex);
e44ef4e4
AL
6265 return NULL;
6266}
6267
97ff3bd3
VG
6268void
6269devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
6270 enum devlink_health_reporter_state state)
6271{
6272 if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY &&
6273 state != DEVLINK_HEALTH_REPORTER_STATE_ERROR))
6274 return;
6275
6276 if (reporter->health_state == state)
6277 return;
6278
6279 reporter->health_state = state;
6280 trace_devlink_health_reporter_state_update(reporter->devlink,
6281 reporter->ops->name, state);
6282 devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
6283}
6284EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update);
6285
7afe335a
EBE
6286static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb,
6287 struct genl_info *info)
6288{
6289 struct devlink *devlink = info->user_ptr[0];
6290 struct devlink_health_reporter *reporter;
6291 struct sk_buff *msg;
6292 int err;
6293
6294 reporter = devlink_health_reporter_get_from_info(devlink, info);
6295 if (!reporter)
6296 return -EINVAL;
6297
6298 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
b587bdaf
MS
6299 if (!msg) {
6300 err = -ENOMEM;
6301 goto out;
6302 }
7afe335a
EBE
6303
6304 err = devlink_nl_health_reporter_fill(msg, devlink, reporter,
6305 DEVLINK_CMD_HEALTH_REPORTER_GET,
6306 info->snd_portid, info->snd_seq,
6307 0);
6308 if (err) {
6309 nlmsg_free(msg);
b587bdaf 6310 goto out;
7afe335a
EBE
6311 }
6312
b587bdaf
MS
6313 err = genlmsg_reply(msg, info);
6314out:
6315 devlink_health_reporter_put(reporter);
6316 return err;
7afe335a
EBE
6317}
6318
6319static int
6320devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg,
6321 struct netlink_callback *cb)
6322{
6323 struct devlink_health_reporter *reporter;
f4f54166 6324 struct devlink_port *port;
7afe335a
EBE
6325 struct devlink *devlink;
6326 int start = cb->args[0];
6327 int idx = 0;
6328 int err;
6329
6330 mutex_lock(&devlink_mutex);
6331 list_for_each_entry(devlink, &devlink_list, list) {
6332 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
6333 continue;
b587bdaf 6334 mutex_lock(&devlink->reporters_lock);
7afe335a
EBE
6335 list_for_each_entry(reporter, &devlink->reporter_list,
6336 list) {
6337 if (idx < start) {
6338 idx++;
6339 continue;
6340 }
6341 err = devlink_nl_health_reporter_fill(msg, devlink,
6342 reporter,
6343 DEVLINK_CMD_HEALTH_REPORTER_GET,
6344 NETLINK_CB(cb->skb).portid,
6345 cb->nlh->nlmsg_seq,
6346 NLM_F_MULTI);
6347 if (err) {
b587bdaf 6348 mutex_unlock(&devlink->reporters_lock);
7afe335a
EBE
6349 goto out;
6350 }
6351 idx++;
6352 }
b587bdaf 6353 mutex_unlock(&devlink->reporters_lock);
7afe335a 6354 }
f4f54166
VT
6355
6356 list_for_each_entry(devlink, &devlink_list, list) {
6357 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
6358 continue;
5d080b50 6359 mutex_lock(&devlink->lock);
f4f54166
VT
6360 list_for_each_entry(port, &devlink->port_list, list) {
6361 mutex_lock(&port->reporters_lock);
6362 list_for_each_entry(reporter, &port->reporter_list, list) {
6363 if (idx < start) {
6364 idx++;
6365 continue;
6366 }
6367 err = devlink_nl_health_reporter_fill(msg, devlink, reporter,
6368 DEVLINK_CMD_HEALTH_REPORTER_GET,
6369 NETLINK_CB(cb->skb).portid,
6370 cb->nlh->nlmsg_seq,
6371 NLM_F_MULTI);
6372 if (err) {
6373 mutex_unlock(&port->reporters_lock);
5d080b50 6374 mutex_unlock(&devlink->lock);
f4f54166
VT
6375 goto out;
6376 }
6377 idx++;
6378 }
6379 mutex_unlock(&port->reporters_lock);
6380 }
5d080b50 6381 mutex_unlock(&devlink->lock);
f4f54166 6382 }
7afe335a
EBE
6383out:
6384 mutex_unlock(&devlink_mutex);
6385
6386 cb->args[0] = idx;
6387 return msg->len;
6388}
6389
a1e55ec0
EBE
6390static int
6391devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb,
6392 struct genl_info *info)
6393{
6394 struct devlink *devlink = info->user_ptr[0];
6395 struct devlink_health_reporter *reporter;
b587bdaf 6396 int err;
a1e55ec0
EBE
6397
6398 reporter = devlink_health_reporter_get_from_info(devlink, info);
6399 if (!reporter)
6400 return -EINVAL;
6401
6402 if (!reporter->ops->recover &&
6403 (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] ||
b587bdaf
MS
6404 info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])) {
6405 err = -EOPNOTSUPP;
6406 goto out;
6407 }
48bb52c8
EBE
6408 if (!reporter->ops->dump &&
6409 info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP]) {
6410 err = -EOPNOTSUPP;
6411 goto out;
6412 }
a1e55ec0
EBE
6413
6414 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD])
6415 reporter->graceful_period =
6416 nla_get_u64(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]);
6417
6418 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])
6419 reporter->auto_recover =
6420 nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]);
6421
48bb52c8
EBE
6422 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP])
6423 reporter->auto_dump =
6424 nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP]);
6425
b587bdaf 6426 devlink_health_reporter_put(reporter);
a1e55ec0 6427 return 0;
b587bdaf
MS
6428out:
6429 devlink_health_reporter_put(reporter);
6430 return err;
a1e55ec0
EBE
6431}
6432
20a0943a
EBE
6433static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb,
6434 struct genl_info *info)
6435{
6436 struct devlink *devlink = info->user_ptr[0];
6437 struct devlink_health_reporter *reporter;
b587bdaf 6438 int err;
20a0943a
EBE
6439
6440 reporter = devlink_health_reporter_get_from_info(devlink, info);
6441 if (!reporter)
6442 return -EINVAL;
6443
e7a98105 6444 err = devlink_health_reporter_recover(reporter, NULL, info->extack);
b587bdaf
MS
6445
6446 devlink_health_reporter_put(reporter);
6447 return err;
20a0943a
EBE
6448}
6449
fca42a27
EBE
6450static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb,
6451 struct genl_info *info)
6452{
6453 struct devlink *devlink = info->user_ptr[0];
6454 struct devlink_health_reporter *reporter;
6455 struct devlink_fmsg *fmsg;
6456 int err;
6457
6458 reporter = devlink_health_reporter_get_from_info(devlink, info);
6459 if (!reporter)
6460 return -EINVAL;
6461
b587bdaf
MS
6462 if (!reporter->ops->diagnose) {
6463 devlink_health_reporter_put(reporter);
fca42a27 6464 return -EOPNOTSUPP;
b587bdaf 6465 }
fca42a27
EBE
6466
6467 fmsg = devlink_fmsg_alloc();
b587bdaf
MS
6468 if (!fmsg) {
6469 devlink_health_reporter_put(reporter);
fca42a27 6470 return -ENOMEM;
b587bdaf 6471 }
fca42a27
EBE
6472
6473 err = devlink_fmsg_obj_nest_start(fmsg);
6474 if (err)
6475 goto out;
6476
e7a98105 6477 err = reporter->ops->diagnose(reporter, fmsg, info->extack);
fca42a27
EBE
6478 if (err)
6479 goto out;
6480
6481 err = devlink_fmsg_obj_nest_end(fmsg);
6482 if (err)
6483 goto out;
6484
6485 err = devlink_fmsg_snd(fmsg, info,
6486 DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 0);
6487
6488out:
6489 devlink_fmsg_free(fmsg);
b587bdaf 6490 devlink_health_reporter_put(reporter);
fca42a27
EBE
6491 return err;
6492}
6493
e44ef4e4
AL
6494static int
6495devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb,
6496 struct netlink_callback *cb)
35455e23 6497{
35455e23 6498 struct devlink_health_reporter *reporter;
e44ef4e4 6499 u64 start = cb->args[0];
35455e23
EBE
6500 int err;
6501
e44ef4e4 6502 reporter = devlink_health_reporter_get_from_cb(cb);
35455e23
EBE
6503 if (!reporter)
6504 return -EINVAL;
6505
b587bdaf 6506 if (!reporter->ops->dump) {
e44ef4e4
AL
6507 err = -EOPNOTSUPP;
6508 goto out;
b587bdaf 6509 }
35455e23 6510 mutex_lock(&reporter->dump_lock);
e44ef4e4 6511 if (!start) {
e7a98105 6512 err = devlink_health_do_dump(reporter, NULL, cb->extack);
e44ef4e4
AL
6513 if (err)
6514 goto unlock;
6515 cb->args[1] = reporter->dump_ts;
6516 }
6517 if (!reporter->dump_fmsg || cb->args[1] != reporter->dump_ts) {
6518 NL_SET_ERR_MSG_MOD(cb->extack, "Dump trampled, please retry");
6519 err = -EAGAIN;
6520 goto unlock;
6521 }
35455e23 6522
e44ef4e4
AL
6523 err = devlink_fmsg_dumpit(reporter->dump_fmsg, skb, cb,
6524 DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET);
6525unlock:
35455e23 6526 mutex_unlock(&reporter->dump_lock);
e44ef4e4 6527out:
b587bdaf 6528 devlink_health_reporter_put(reporter);
35455e23
EBE
6529 return err;
6530}
6531
6532static int
6533devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb,
6534 struct genl_info *info)
6535{
6536 struct devlink *devlink = info->user_ptr[0];
6537 struct devlink_health_reporter *reporter;
6538
6539 reporter = devlink_health_reporter_get_from_info(devlink, info);
6540 if (!reporter)
6541 return -EINVAL;
6542
b587bdaf
MS
6543 if (!reporter->ops->dump) {
6544 devlink_health_reporter_put(reporter);
35455e23 6545 return -EOPNOTSUPP;
b587bdaf 6546 }
35455e23
EBE
6547
6548 mutex_lock(&reporter->dump_lock);
6549 devlink_health_dump_clear(reporter);
6550 mutex_unlock(&reporter->dump_lock);
b587bdaf 6551 devlink_health_reporter_put(reporter);
35455e23
EBE
6552 return 0;
6553}
6554
e2ce94dc
JP
6555static int devlink_nl_cmd_health_reporter_test_doit(struct sk_buff *skb,
6556 struct genl_info *info)
6557{
6558 struct devlink *devlink = info->user_ptr[0];
6559 struct devlink_health_reporter *reporter;
6560 int err;
6561
6562 reporter = devlink_health_reporter_get_from_info(devlink, info);
6563 if (!reporter)
6564 return -EINVAL;
6565
6566 if (!reporter->ops->test) {
6567 devlink_health_reporter_put(reporter);
6568 return -EOPNOTSUPP;
6569 }
6570
6571 err = reporter->ops->test(reporter, info->extack);
6572
6573 devlink_health_reporter_put(reporter);
6574 return err;
6575}
6576
0f420b6c
IS
6577struct devlink_stats {
6578 u64 rx_bytes;
6579 u64 rx_packets;
6580 struct u64_stats_sync syncp;
6581};
6582
1e8c6619
IS
6583/**
6584 * struct devlink_trap_policer_item - Packet trap policer attributes.
6585 * @policer: Immutable packet trap policer attributes.
6586 * @rate: Rate in packets / sec.
6587 * @burst: Burst size in packets.
6588 * @list: trap_policer_list member.
6589 *
6590 * Describes packet trap policer attributes. Created by devlink during trap
6591 * policer registration.
6592 */
6593struct devlink_trap_policer_item {
6594 const struct devlink_trap_policer *policer;
6595 u64 rate;
6596 u64 burst;
6597 struct list_head list;
6598};
6599
0f420b6c
IS
6600/**
6601 * struct devlink_trap_group_item - Packet trap group attributes.
6602 * @group: Immutable packet trap group attributes.
f9f54392 6603 * @policer_item: Associated policer item. Can be NULL.
0f420b6c
IS
6604 * @list: trap_group_list member.
6605 * @stats: Trap group statistics.
6606 *
6607 * Describes packet trap group attributes. Created by devlink during trap
a09b37fc 6608 * group registration.
0f420b6c
IS
6609 */
6610struct devlink_trap_group_item {
6611 const struct devlink_trap_group *group;
f9f54392 6612 struct devlink_trap_policer_item *policer_item;
0f420b6c
IS
6613 struct list_head list;
6614 struct devlink_stats __percpu *stats;
6615};
6616
6617/**
6618 * struct devlink_trap_item - Packet trap attributes.
6619 * @trap: Immutable packet trap attributes.
6620 * @group_item: Associated group item.
6621 * @list: trap_list member.
6622 * @action: Trap action.
6623 * @stats: Trap statistics.
6624 * @priv: Driver private information.
6625 *
6626 * Describes both mutable and immutable packet trap attributes. Created by
6627 * devlink during trap registration and used for all trap related operations.
6628 */
6629struct devlink_trap_item {
6630 const struct devlink_trap *trap;
6631 struct devlink_trap_group_item *group_item;
6632 struct list_head list;
6633 enum devlink_trap_action action;
6634 struct devlink_stats __percpu *stats;
6635 void *priv;
6636};
6637
1e8c6619
IS
6638static struct devlink_trap_policer_item *
6639devlink_trap_policer_item_lookup(struct devlink *devlink, u32 id)
6640{
6641 struct devlink_trap_policer_item *policer_item;
6642
6643 list_for_each_entry(policer_item, &devlink->trap_policer_list, list) {
6644 if (policer_item->policer->id == id)
6645 return policer_item;
6646 }
6647
6648 return NULL;
6649}
6650
0f420b6c
IS
6651static struct devlink_trap_item *
6652devlink_trap_item_lookup(struct devlink *devlink, const char *name)
6653{
6654 struct devlink_trap_item *trap_item;
6655
6656 list_for_each_entry(trap_item, &devlink->trap_list, list) {
6657 if (!strcmp(trap_item->trap->name, name))
6658 return trap_item;
6659 }
6660
6661 return NULL;
6662}
6663
6664static struct devlink_trap_item *
6665devlink_trap_item_get_from_info(struct devlink *devlink,
6666 struct genl_info *info)
6667{
6668 struct nlattr *attr;
6669
6670 if (!info->attrs[DEVLINK_ATTR_TRAP_NAME])
6671 return NULL;
6672 attr = info->attrs[DEVLINK_ATTR_TRAP_NAME];
6673
6674 return devlink_trap_item_lookup(devlink, nla_data(attr));
6675}
6676
6677static int
6678devlink_trap_action_get_from_info(struct genl_info *info,
6679 enum devlink_trap_action *p_trap_action)
6680{
6681 u8 val;
6682
6683 val = nla_get_u8(info->attrs[DEVLINK_ATTR_TRAP_ACTION]);
6684 switch (val) {
df561f66
GS
6685 case DEVLINK_TRAP_ACTION_DROP:
6686 case DEVLINK_TRAP_ACTION_TRAP:
9eefeabe 6687 case DEVLINK_TRAP_ACTION_MIRROR:
0f420b6c
IS
6688 *p_trap_action = val;
6689 break;
6690 default:
6691 return -EINVAL;
6692 }
6693
6694 return 0;
6695}
6696
6697static int devlink_trap_metadata_put(struct sk_buff *msg,
6698 const struct devlink_trap *trap)
6699{
6700 struct nlattr *attr;
6701
6702 attr = nla_nest_start(msg, DEVLINK_ATTR_TRAP_METADATA);
6703 if (!attr)
6704 return -EMSGSIZE;
6705
6706 if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT) &&
6707 nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_IN_PORT))
6708 goto nla_put_failure;
85b0589e
JP
6709 if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE) &&
6710 nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_FA_COOKIE))
6711 goto nla_put_failure;
0f420b6c
IS
6712
6713 nla_nest_end(msg, attr);
6714
6715 return 0;
6716
6717nla_put_failure:
6718 nla_nest_cancel(msg, attr);
6719 return -EMSGSIZE;
6720}
6721
6722static void devlink_trap_stats_read(struct devlink_stats __percpu *trap_stats,
6723 struct devlink_stats *stats)
6724{
6725 int i;
6726
6727 memset(stats, 0, sizeof(*stats));
6728 for_each_possible_cpu(i) {
6729 struct devlink_stats *cpu_stats;
6730 u64 rx_packets, rx_bytes;
6731 unsigned int start;
6732
6733 cpu_stats = per_cpu_ptr(trap_stats, i);
6734 do {
6735 start = u64_stats_fetch_begin_irq(&cpu_stats->syncp);
6736 rx_packets = cpu_stats->rx_packets;
6737 rx_bytes = cpu_stats->rx_bytes;
6738 } while (u64_stats_fetch_retry_irq(&cpu_stats->syncp, start));
6739
6740 stats->rx_packets += rx_packets;
6741 stats->rx_bytes += rx_bytes;
6742 }
6743}
6744
6745static int devlink_trap_stats_put(struct sk_buff *msg,
6746 struct devlink_stats __percpu *trap_stats)
6747{
6748 struct devlink_stats stats;
6749 struct nlattr *attr;
6750
6751 devlink_trap_stats_read(trap_stats, &stats);
6752
6753 attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
6754 if (!attr)
6755 return -EMSGSIZE;
6756
6757 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS,
6758 stats.rx_packets, DEVLINK_ATTR_PAD))
6759 goto nla_put_failure;
6760
6761 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES,
6762 stats.rx_bytes, DEVLINK_ATTR_PAD))
6763 goto nla_put_failure;
6764
6765 nla_nest_end(msg, attr);
6766
6767 return 0;
6768
6769nla_put_failure:
6770 nla_nest_cancel(msg, attr);
6771 return -EMSGSIZE;
6772}
6773
6774static int devlink_nl_trap_fill(struct sk_buff *msg, struct devlink *devlink,
6775 const struct devlink_trap_item *trap_item,
6776 enum devlink_command cmd, u32 portid, u32 seq,
6777 int flags)
6778{
6779 struct devlink_trap_group_item *group_item = trap_item->group_item;
6780 void *hdr;
6781 int err;
6782
6783 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
6784 if (!hdr)
6785 return -EMSGSIZE;
6786
6787 if (devlink_nl_put_handle(msg, devlink))
6788 goto nla_put_failure;
6789
6790 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
6791 group_item->group->name))
6792 goto nla_put_failure;
6793
6794 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_NAME, trap_item->trap->name))
6795 goto nla_put_failure;
6796
6797 if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_TYPE, trap_item->trap->type))
6798 goto nla_put_failure;
6799
6800 if (trap_item->trap->generic &&
6801 nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
6802 goto nla_put_failure;
6803
6804 if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_ACTION, trap_item->action))
6805 goto nla_put_failure;
6806
6807 err = devlink_trap_metadata_put(msg, trap_item->trap);
6808 if (err)
6809 goto nla_put_failure;
6810
6811 err = devlink_trap_stats_put(msg, trap_item->stats);
6812 if (err)
6813 goto nla_put_failure;
6814
6815 genlmsg_end(msg, hdr);
6816
6817 return 0;
6818
6819nla_put_failure:
6820 genlmsg_cancel(msg, hdr);
6821 return -EMSGSIZE;
6822}
6823
6824static int devlink_nl_cmd_trap_get_doit(struct sk_buff *skb,
6825 struct genl_info *info)
6826{
6827 struct netlink_ext_ack *extack = info->extack;
6828 struct devlink *devlink = info->user_ptr[0];
6829 struct devlink_trap_item *trap_item;
6830 struct sk_buff *msg;
6831 int err;
6832
6833 if (list_empty(&devlink->trap_list))
6834 return -EOPNOTSUPP;
6835
6836 trap_item = devlink_trap_item_get_from_info(devlink, info);
6837 if (!trap_item) {
6838 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap");
6839 return -ENOENT;
6840 }
6841
6842 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
6843 if (!msg)
6844 return -ENOMEM;
6845
6846 err = devlink_nl_trap_fill(msg, devlink, trap_item,
6847 DEVLINK_CMD_TRAP_NEW, info->snd_portid,
6848 info->snd_seq, 0);
6849 if (err)
6850 goto err_trap_fill;
6851
6852 return genlmsg_reply(msg, info);
6853
6854err_trap_fill:
6855 nlmsg_free(msg);
6856 return err;
6857}
6858
6859static int devlink_nl_cmd_trap_get_dumpit(struct sk_buff *msg,
6860 struct netlink_callback *cb)
6861{
6862 struct devlink_trap_item *trap_item;
6863 struct devlink *devlink;
6864 int start = cb->args[0];
6865 int idx = 0;
6866 int err;
6867
6868 mutex_lock(&devlink_mutex);
6869 list_for_each_entry(devlink, &devlink_list, list) {
6870 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
6871 continue;
6872 mutex_lock(&devlink->lock);
6873 list_for_each_entry(trap_item, &devlink->trap_list, list) {
6874 if (idx < start) {
6875 idx++;
6876 continue;
6877 }
6878 err = devlink_nl_trap_fill(msg, devlink, trap_item,
6879 DEVLINK_CMD_TRAP_NEW,
6880 NETLINK_CB(cb->skb).portid,
6881 cb->nlh->nlmsg_seq,
6882 NLM_F_MULTI);
6883 if (err) {
6884 mutex_unlock(&devlink->lock);
6885 goto out;
6886 }
6887 idx++;
6888 }
6889 mutex_unlock(&devlink->lock);
6890 }
6891out:
6892 mutex_unlock(&devlink_mutex);
6893
6894 cb->args[0] = idx;
6895 return msg->len;
6896}
6897
6898static int __devlink_trap_action_set(struct devlink *devlink,
6899 struct devlink_trap_item *trap_item,
6900 enum devlink_trap_action trap_action,
6901 struct netlink_ext_ack *extack)
6902{
6903 int err;
6904
6905 if (trap_item->action != trap_action &&
6906 trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP) {
6907 NL_SET_ERR_MSG_MOD(extack, "Cannot change action of non-drop traps. Skipping");
6908 return 0;
6909 }
6910
6911 err = devlink->ops->trap_action_set(devlink, trap_item->trap,
c88e11e0 6912 trap_action, extack);
0f420b6c
IS
6913 if (err)
6914 return err;
6915
6916 trap_item->action = trap_action;
6917
6918 return 0;
6919}
6920
6921static int devlink_trap_action_set(struct devlink *devlink,
6922 struct devlink_trap_item *trap_item,
6923 struct genl_info *info)
6924{
6925 enum devlink_trap_action trap_action;
6926 int err;
6927
6928 if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
6929 return 0;
6930
6931 err = devlink_trap_action_get_from_info(info, &trap_action);
6932 if (err) {
6933 NL_SET_ERR_MSG_MOD(info->extack, "Invalid trap action");
6934 return -EINVAL;
6935 }
6936
6937 return __devlink_trap_action_set(devlink, trap_item, trap_action,
6938 info->extack);
6939}
6940
6941static int devlink_nl_cmd_trap_set_doit(struct sk_buff *skb,
6942 struct genl_info *info)
6943{
6944 struct netlink_ext_ack *extack = info->extack;
6945 struct devlink *devlink = info->user_ptr[0];
6946 struct devlink_trap_item *trap_item;
6947 int err;
6948
6949 if (list_empty(&devlink->trap_list))
6950 return -EOPNOTSUPP;
6951
6952 trap_item = devlink_trap_item_get_from_info(devlink, info);
6953 if (!trap_item) {
6954 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap");
6955 return -ENOENT;
6956 }
6957
6958 err = devlink_trap_action_set(devlink, trap_item, info);
6959 if (err)
6960 return err;
6961
6962 return 0;
6963}
6964
6965static struct devlink_trap_group_item *
6966devlink_trap_group_item_lookup(struct devlink *devlink, const char *name)
6967{
6968 struct devlink_trap_group_item *group_item;
6969
6970 list_for_each_entry(group_item, &devlink->trap_group_list, list) {
6971 if (!strcmp(group_item->group->name, name))
6972 return group_item;
6973 }
6974
6975 return NULL;
6976}
6977
107f1678
IS
6978static struct devlink_trap_group_item *
6979devlink_trap_group_item_lookup_by_id(struct devlink *devlink, u16 id)
6980{
6981 struct devlink_trap_group_item *group_item;
6982
6983 list_for_each_entry(group_item, &devlink->trap_group_list, list) {
6984 if (group_item->group->id == id)
6985 return group_item;
6986 }
6987
6988 return NULL;
6989}
6990
0f420b6c
IS
6991static struct devlink_trap_group_item *
6992devlink_trap_group_item_get_from_info(struct devlink *devlink,
6993 struct genl_info *info)
6994{
6995 char *name;
6996
6997 if (!info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME])
6998 return NULL;
6999 name = nla_data(info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME]);
7000
7001 return devlink_trap_group_item_lookup(devlink, name);
7002}
7003
7004static int
7005devlink_nl_trap_group_fill(struct sk_buff *msg, struct devlink *devlink,
7006 const struct devlink_trap_group_item *group_item,
7007 enum devlink_command cmd, u32 portid, u32 seq,
7008 int flags)
7009{
7010 void *hdr;
7011 int err;
7012
7013 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
7014 if (!hdr)
7015 return -EMSGSIZE;
7016
7017 if (devlink_nl_put_handle(msg, devlink))
7018 goto nla_put_failure;
7019
7020 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
7021 group_item->group->name))
7022 goto nla_put_failure;
7023
7024 if (group_item->group->generic &&
7025 nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
7026 goto nla_put_failure;
7027
f9f54392
IS
7028 if (group_item->policer_item &&
7029 nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID,
7030 group_item->policer_item->policer->id))
7031 goto nla_put_failure;
7032
0f420b6c
IS
7033 err = devlink_trap_stats_put(msg, group_item->stats);
7034 if (err)
7035 goto nla_put_failure;
7036
7037 genlmsg_end(msg, hdr);
7038
7039 return 0;
7040
7041nla_put_failure:
7042 genlmsg_cancel(msg, hdr);
7043 return -EMSGSIZE;
7044}
7045
7046static int devlink_nl_cmd_trap_group_get_doit(struct sk_buff *skb,
7047 struct genl_info *info)
7048{
7049 struct netlink_ext_ack *extack = info->extack;
7050 struct devlink *devlink = info->user_ptr[0];
7051 struct devlink_trap_group_item *group_item;
7052 struct sk_buff *msg;
7053 int err;
7054
7055 if (list_empty(&devlink->trap_group_list))
7056 return -EOPNOTSUPP;
7057
7058 group_item = devlink_trap_group_item_get_from_info(devlink, info);
7059 if (!group_item) {
7060 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap group");
7061 return -ENOENT;
7062 }
7063
7064 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7065 if (!msg)
7066 return -ENOMEM;
7067
7068 err = devlink_nl_trap_group_fill(msg, devlink, group_item,
7069 DEVLINK_CMD_TRAP_GROUP_NEW,
7070 info->snd_portid, info->snd_seq, 0);
7071 if (err)
7072 goto err_trap_group_fill;
7073
7074 return genlmsg_reply(msg, info);
7075
7076err_trap_group_fill:
7077 nlmsg_free(msg);
7078 return err;
7079}
7080
7081static int devlink_nl_cmd_trap_group_get_dumpit(struct sk_buff *msg,
7082 struct netlink_callback *cb)
7083{
7084 enum devlink_command cmd = DEVLINK_CMD_TRAP_GROUP_NEW;
7085 struct devlink_trap_group_item *group_item;
7086 u32 portid = NETLINK_CB(cb->skb).portid;
7087 struct devlink *devlink;
7088 int start = cb->args[0];
7089 int idx = 0;
7090 int err;
7091
7092 mutex_lock(&devlink_mutex);
7093 list_for_each_entry(devlink, &devlink_list, list) {
7094 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
7095 continue;
7096 mutex_lock(&devlink->lock);
7097 list_for_each_entry(group_item, &devlink->trap_group_list,
7098 list) {
7099 if (idx < start) {
7100 idx++;
7101 continue;
7102 }
7103 err = devlink_nl_trap_group_fill(msg, devlink,
7104 group_item, cmd,
7105 portid,
7106 cb->nlh->nlmsg_seq,
7107 NLM_F_MULTI);
7108 if (err) {
7109 mutex_unlock(&devlink->lock);
7110 goto out;
7111 }
7112 idx++;
7113 }
7114 mutex_unlock(&devlink->lock);
7115 }
7116out:
7117 mutex_unlock(&devlink_mutex);
7118
7119 cb->args[0] = idx;
7120 return msg->len;
7121}
7122
7123static int
7124__devlink_trap_group_action_set(struct devlink *devlink,
7125 struct devlink_trap_group_item *group_item,
7126 enum devlink_trap_action trap_action,
7127 struct netlink_ext_ack *extack)
7128{
7129 const char *group_name = group_item->group->name;
7130 struct devlink_trap_item *trap_item;
7131 int err;
7132
c50bf2be
IC
7133 if (devlink->ops->trap_group_action_set) {
7134 err = devlink->ops->trap_group_action_set(devlink, group_item->group,
7135 trap_action, extack);
7136 if (err)
7137 return err;
7138
7139 list_for_each_entry(trap_item, &devlink->trap_list, list) {
7140 if (strcmp(trap_item->group_item->group->name, group_name))
7141 continue;
7142 if (trap_item->action != trap_action &&
7143 trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP)
7144 continue;
7145 trap_item->action = trap_action;
7146 }
7147
7148 return 0;
7149 }
7150
0f420b6c 7151 list_for_each_entry(trap_item, &devlink->trap_list, list) {
107f1678 7152 if (strcmp(trap_item->group_item->group->name, group_name))
0f420b6c
IS
7153 continue;
7154 err = __devlink_trap_action_set(devlink, trap_item,
7155 trap_action, extack);
7156 if (err)
7157 return err;
7158 }
7159
7160 return 0;
7161}
7162
7163static int
7164devlink_trap_group_action_set(struct devlink *devlink,
7165 struct devlink_trap_group_item *group_item,
c064875a 7166 struct genl_info *info, bool *p_modified)
0f420b6c
IS
7167{
7168 enum devlink_trap_action trap_action;
7169 int err;
7170
7171 if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
7172 return 0;
7173
7174 err = devlink_trap_action_get_from_info(info, &trap_action);
7175 if (err) {
7176 NL_SET_ERR_MSG_MOD(info->extack, "Invalid trap action");
7177 return -EINVAL;
7178 }
7179
7180 err = __devlink_trap_group_action_set(devlink, group_item, trap_action,
7181 info->extack);
7182 if (err)
7183 return err;
7184
c064875a
IS
7185 *p_modified = true;
7186
7187 return 0;
7188}
7189
7190static int devlink_trap_group_set(struct devlink *devlink,
7191 struct devlink_trap_group_item *group_item,
7192 struct genl_info *info)
7193{
7194 struct devlink_trap_policer_item *policer_item;
7195 struct netlink_ext_ack *extack = info->extack;
7196 const struct devlink_trap_policer *policer;
7197 struct nlattr **attrs = info->attrs;
7198 int err;
7199
7200 if (!attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
7201 return 0;
7202
7203 if (!devlink->ops->trap_group_set)
7204 return -EOPNOTSUPP;
7205
7206 policer_item = group_item->policer_item;
7207 if (attrs[DEVLINK_ATTR_TRAP_POLICER_ID]) {
7208 u32 policer_id;
7209
7210 policer_id = nla_get_u32(attrs[DEVLINK_ATTR_TRAP_POLICER_ID]);
7211 policer_item = devlink_trap_policer_item_lookup(devlink,
7212 policer_id);
7213 if (policer_id && !policer_item) {
7214 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");
7215 return -ENOENT;
7216 }
7217 }
7218 policer = policer_item ? policer_item->policer : NULL;
7219
c88e11e0
IS
7220 err = devlink->ops->trap_group_set(devlink, group_item->group, policer,
7221 extack);
c064875a
IS
7222 if (err)
7223 return err;
7224
7225 group_item->policer_item = policer_item;
7226
0f420b6c
IS
7227 return 0;
7228}
7229
7230static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb,
7231 struct genl_info *info)
7232{
7233 struct netlink_ext_ack *extack = info->extack;
7234 struct devlink *devlink = info->user_ptr[0];
7235 struct devlink_trap_group_item *group_item;
c064875a 7236 bool modified = false;
0f420b6c
IS
7237 int err;
7238
7239 if (list_empty(&devlink->trap_group_list))
7240 return -EOPNOTSUPP;
7241
7242 group_item = devlink_trap_group_item_get_from_info(devlink, info);
7243 if (!group_item) {
7244 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap group");
7245 return -ENOENT;
7246 }
7247
c064875a
IS
7248 err = devlink_trap_group_action_set(devlink, group_item, info,
7249 &modified);
0f420b6c
IS
7250 if (err)
7251 return err;
7252
c064875a
IS
7253 err = devlink_trap_group_set(devlink, group_item, info);
7254 if (err)
7255 goto err_trap_group_set;
7256
0f420b6c 7257 return 0;
c064875a
IS
7258
7259err_trap_group_set:
7260 if (modified)
7261 NL_SET_ERR_MSG_MOD(extack, "Trap group set failed, but some changes were committed already");
7262 return err;
0f420b6c
IS
7263}
7264
1e8c6619
IS
7265static struct devlink_trap_policer_item *
7266devlink_trap_policer_item_get_from_info(struct devlink *devlink,
7267 struct genl_info *info)
7268{
7269 u32 id;
7270
7271 if (!info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
7272 return NULL;
7273 id = nla_get_u32(info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID]);
7274
7275 return devlink_trap_policer_item_lookup(devlink, id);
7276}
7277
7278static int
7279devlink_trap_policer_stats_put(struct sk_buff *msg, struct devlink *devlink,
7280 const struct devlink_trap_policer *policer)
7281{
7282 struct nlattr *attr;
7283 u64 drops;
7284 int err;
7285
7286 if (!devlink->ops->trap_policer_counter_get)
7287 return 0;
7288
7289 err = devlink->ops->trap_policer_counter_get(devlink, policer, &drops);
7290 if (err)
7291 return err;
7292
7293 attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
7294 if (!attr)
7295 return -EMSGSIZE;
7296
7297 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops,
7298 DEVLINK_ATTR_PAD))
7299 goto nla_put_failure;
7300
7301 nla_nest_end(msg, attr);
7302
7303 return 0;
7304
7305nla_put_failure:
7306 nla_nest_cancel(msg, attr);
7307 return -EMSGSIZE;
7308}
7309
7310static int
7311devlink_nl_trap_policer_fill(struct sk_buff *msg, struct devlink *devlink,
7312 const struct devlink_trap_policer_item *policer_item,
7313 enum devlink_command cmd, u32 portid, u32 seq,
7314 int flags)
7315{
7316 void *hdr;
7317 int err;
7318
7319 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
7320 if (!hdr)
7321 return -EMSGSIZE;
7322
7323 if (devlink_nl_put_handle(msg, devlink))
7324 goto nla_put_failure;
7325
7326 if (nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID,
7327 policer_item->policer->id))
7328 goto nla_put_failure;
7329
7330 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_RATE,
7331 policer_item->rate, DEVLINK_ATTR_PAD))
7332 goto nla_put_failure;
7333
7334 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_BURST,
7335 policer_item->burst, DEVLINK_ATTR_PAD))
7336 goto nla_put_failure;
7337
7338 err = devlink_trap_policer_stats_put(msg, devlink,
7339 policer_item->policer);
7340 if (err)
7341 goto nla_put_failure;
7342
7343 genlmsg_end(msg, hdr);
7344
7345 return 0;
7346
7347nla_put_failure:
7348 genlmsg_cancel(msg, hdr);
7349 return -EMSGSIZE;
7350}
7351
7352static int devlink_nl_cmd_trap_policer_get_doit(struct sk_buff *skb,
7353 struct genl_info *info)
7354{
7355 struct devlink_trap_policer_item *policer_item;
7356 struct netlink_ext_ack *extack = info->extack;
7357 struct devlink *devlink = info->user_ptr[0];
7358 struct sk_buff *msg;
7359 int err;
7360
7361 if (list_empty(&devlink->trap_policer_list))
7362 return -EOPNOTSUPP;
7363
7364 policer_item = devlink_trap_policer_item_get_from_info(devlink, info);
7365 if (!policer_item) {
7366 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");
7367 return -ENOENT;
7368 }
7369
7370 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7371 if (!msg)
7372 return -ENOMEM;
7373
7374 err = devlink_nl_trap_policer_fill(msg, devlink, policer_item,
7375 DEVLINK_CMD_TRAP_POLICER_NEW,
7376 info->snd_portid, info->snd_seq, 0);
7377 if (err)
7378 goto err_trap_policer_fill;
7379
7380 return genlmsg_reply(msg, info);
7381
7382err_trap_policer_fill:
7383 nlmsg_free(msg);
7384 return err;
7385}
7386
7387static int devlink_nl_cmd_trap_policer_get_dumpit(struct sk_buff *msg,
7388 struct netlink_callback *cb)
7389{
7390 enum devlink_command cmd = DEVLINK_CMD_TRAP_POLICER_NEW;
7391 struct devlink_trap_policer_item *policer_item;
7392 u32 portid = NETLINK_CB(cb->skb).portid;
7393 struct devlink *devlink;
7394 int start = cb->args[0];
7395 int idx = 0;
7396 int err;
7397
7398 mutex_lock(&devlink_mutex);
7399 list_for_each_entry(devlink, &devlink_list, list) {
7400 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
7401 continue;
7402 mutex_lock(&devlink->lock);
7403 list_for_each_entry(policer_item, &devlink->trap_policer_list,
7404 list) {
7405 if (idx < start) {
7406 idx++;
7407 continue;
7408 }
7409 err = devlink_nl_trap_policer_fill(msg, devlink,
7410 policer_item, cmd,
7411 portid,
7412 cb->nlh->nlmsg_seq,
7413 NLM_F_MULTI);
7414 if (err) {
7415 mutex_unlock(&devlink->lock);
7416 goto out;
7417 }
7418 idx++;
7419 }
7420 mutex_unlock(&devlink->lock);
7421 }
7422out:
7423 mutex_unlock(&devlink_mutex);
7424
7425 cb->args[0] = idx;
7426 return msg->len;
7427}
7428
7429static int
7430devlink_trap_policer_set(struct devlink *devlink,
7431 struct devlink_trap_policer_item *policer_item,
7432 struct genl_info *info)
7433{
7434 struct netlink_ext_ack *extack = info->extack;
7435 struct nlattr **attrs = info->attrs;
7436 u64 rate, burst;
7437 int err;
7438
7439 rate = policer_item->rate;
7440 burst = policer_item->burst;
7441
7442 if (attrs[DEVLINK_ATTR_TRAP_POLICER_RATE])
7443 rate = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_RATE]);
7444
7445 if (attrs[DEVLINK_ATTR_TRAP_POLICER_BURST])
7446 burst = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_BURST]);
7447
7448 if (rate < policer_item->policer->min_rate) {
7449 NL_SET_ERR_MSG_MOD(extack, "Policer rate lower than limit");
7450 return -EINVAL;
7451 }
7452
7453 if (rate > policer_item->policer->max_rate) {
7454 NL_SET_ERR_MSG_MOD(extack, "Policer rate higher than limit");
7455 return -EINVAL;
7456 }
7457
7458 if (burst < policer_item->policer->min_burst) {
7459 NL_SET_ERR_MSG_MOD(extack, "Policer burst size lower than limit");
7460 return -EINVAL;
7461 }
7462
7463 if (burst > policer_item->policer->max_burst) {
7464 NL_SET_ERR_MSG_MOD(extack, "Policer burst size higher than limit");
7465 return -EINVAL;
7466 }
7467
7468 err = devlink->ops->trap_policer_set(devlink, policer_item->policer,
7469 rate, burst, info->extack);
7470 if (err)
7471 return err;
7472
7473 policer_item->rate = rate;
7474 policer_item->burst = burst;
7475
7476 return 0;
7477}
7478
7479static int devlink_nl_cmd_trap_policer_set_doit(struct sk_buff *skb,
7480 struct genl_info *info)
7481{
7482 struct devlink_trap_policer_item *policer_item;
7483 struct netlink_ext_ack *extack = info->extack;
7484 struct devlink *devlink = info->user_ptr[0];
7485
7486 if (list_empty(&devlink->trap_policer_list))
7487 return -EOPNOTSUPP;
7488
7489 if (!devlink->ops->trap_policer_set)
7490 return -EOPNOTSUPP;
7491
7492 policer_item = devlink_trap_policer_item_get_from_info(devlink, info);
7493 if (!policer_item) {
7494 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");
7495 return -ENOENT;
7496 }
7497
7498 return devlink_trap_policer_set(devlink, policer_item, info);
7499}
7500
bfcd3a46 7501static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
1e8c6619
IS
7502 [DEVLINK_ATTR_UNSPEC] = { .strict_start_type =
7503 DEVLINK_ATTR_TRAP_POLICER_ID },
bfcd3a46
JP
7504 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
7505 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
7506 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 },
c49a9440
PP
7507 [DEVLINK_ATTR_PORT_TYPE] = NLA_POLICY_RANGE(NLA_U16, DEVLINK_PORT_TYPE_AUTO,
7508 DEVLINK_PORT_TYPE_IB),
bfcd3a46 7509 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 },
bf797471
JP
7510 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 },
7511 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 },
7512 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 },
7513 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 },
7514 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 },
7515 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 },
7516 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 },
ba356c90
PP
7517 [DEVLINK_ATTR_ESWITCH_MODE] = NLA_POLICY_RANGE(NLA_U16, DEVLINK_ESWITCH_MODE_LEGACY,
7518 DEVLINK_ESWITCH_MODE_SWITCHDEV),
59bfde01 7519 [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 },
f43e9b06 7520 [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 },
1555d204
AS
7521 [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING },
7522 [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 },
d9f9b9a4
AS
7523 [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64},
7524 [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64},
e3b7ca18
MS
7525 [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING },
7526 [DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 },
7527 [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 },
d8db7ea5 7528 [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING },
866319bb 7529 [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 },
ff3b63b8
JK
7530 [DEVLINK_ATTR_REGION_CHUNK_ADDR] = { .type = NLA_U64 },
7531 [DEVLINK_ATTR_REGION_CHUNK_LEN] = { .type = NLA_U64 },
7afe335a 7532 [DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING },
a1e55ec0
EBE
7533 [DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] = { .type = NLA_U64 },
7534 [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER] = { .type = NLA_U8 },
76726ccb
JK
7535 [DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME] = { .type = NLA_NUL_STRING },
7536 [DEVLINK_ATTR_FLASH_UPDATE_COMPONENT] = { .type = NLA_NUL_STRING },
5d5b4128
JK
7537 [DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK] =
7538 NLA_POLICY_BITFIELD32(DEVLINK_SUPPORTED_FLASH_OVERWRITE_SECTIONS),
0f420b6c
IS
7539 [DEVLINK_ATTR_TRAP_NAME] = { .type = NLA_NUL_STRING },
7540 [DEVLINK_ATTR_TRAP_ACTION] = { .type = NLA_U8 },
7541 [DEVLINK_ATTR_TRAP_GROUP_NAME] = { .type = NLA_NUL_STRING },
070c63f2
JP
7542 [DEVLINK_ATTR_NETNS_PID] = { .type = NLA_U32 },
7543 [DEVLINK_ATTR_NETNS_FD] = { .type = NLA_U32 },
7544 [DEVLINK_ATTR_NETNS_ID] = { .type = NLA_U32 },
48bb52c8 7545 [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP] = { .type = NLA_U8 },
1e8c6619
IS
7546 [DEVLINK_ATTR_TRAP_POLICER_ID] = { .type = NLA_U32 },
7547 [DEVLINK_ATTR_TRAP_POLICER_RATE] = { .type = NLA_U64 },
7548 [DEVLINK_ATTR_TRAP_POLICER_BURST] = { .type = NLA_U64 },
a1e8ae90 7549 [DEVLINK_ATTR_PORT_FUNCTION] = { .type = NLA_NESTED },
ccdf0721
MS
7550 [DEVLINK_ATTR_RELOAD_ACTION] = NLA_POLICY_RANGE(NLA_U8, DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
7551 DEVLINK_RELOAD_ACTION_MAX),
dc64cc7c 7552 [DEVLINK_ATTR_RELOAD_LIMITS] = NLA_POLICY_BITFIELD32(DEVLINK_RELOAD_LIMITS_VALID_MASK),
bfcd3a46
JP
7553};
7554
66a9b928 7555static const struct genl_small_ops devlink_nl_ops[] = {
bfcd3a46
JP
7556 {
7557 .cmd = DEVLINK_CMD_GET,
ef6243ac 7558 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bfcd3a46
JP
7559 .doit = devlink_nl_cmd_get_doit,
7560 .dumpit = devlink_nl_cmd_get_dumpit,
bfcd3a46
JP
7561 /* can be retrieved by unprivileged users */
7562 },
7563 {
7564 .cmd = DEVLINK_CMD_PORT_GET,
ef6243ac 7565 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bfcd3a46
JP
7566 .doit = devlink_nl_cmd_port_get_doit,
7567 .dumpit = devlink_nl_cmd_port_get_dumpit,
bfcd3a46
JP
7568 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
7569 /* can be retrieved by unprivileged users */
7570 },
7571 {
7572 .cmd = DEVLINK_CMD_PORT_SET,
ef6243ac 7573 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bfcd3a46 7574 .doit = devlink_nl_cmd_port_set_doit,
bfcd3a46
JP
7575 .flags = GENL_ADMIN_PERM,
7576 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
7577 },
7578 {
7579 .cmd = DEVLINK_CMD_PORT_SPLIT,
ef6243ac 7580 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bfcd3a46 7581 .doit = devlink_nl_cmd_port_split_doit,
bfcd3a46 7582 .flags = GENL_ADMIN_PERM,
637989b5 7583 .internal_flags = DEVLINK_NL_FLAG_NO_LOCK,
bfcd3a46
JP
7584 },
7585 {
7586 .cmd = DEVLINK_CMD_PORT_UNSPLIT,
ef6243ac 7587 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bfcd3a46 7588 .doit = devlink_nl_cmd_port_unsplit_doit,
bfcd3a46 7589 .flags = GENL_ADMIN_PERM,
637989b5 7590 .internal_flags = DEVLINK_NL_FLAG_NO_LOCK,
bfcd3a46 7591 },
bf797471
JP
7592 {
7593 .cmd = DEVLINK_CMD_SB_GET,
ef6243ac 7594 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bf797471
JP
7595 .doit = devlink_nl_cmd_sb_get_doit,
7596 .dumpit = devlink_nl_cmd_sb_get_dumpit,
bf797471
JP
7597 /* can be retrieved by unprivileged users */
7598 },
7599 {
7600 .cmd = DEVLINK_CMD_SB_POOL_GET,
ef6243ac 7601 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bf797471
JP
7602 .doit = devlink_nl_cmd_sb_pool_get_doit,
7603 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit,
bf797471
JP
7604 /* can be retrieved by unprivileged users */
7605 },
7606 {
7607 .cmd = DEVLINK_CMD_SB_POOL_SET,
ef6243ac 7608 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bf797471 7609 .doit = devlink_nl_cmd_sb_pool_set_doit,
bf797471 7610 .flags = GENL_ADMIN_PERM,
bf797471
JP
7611 },
7612 {
7613 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET,
ef6243ac 7614 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bf797471
JP
7615 .doit = devlink_nl_cmd_sb_port_pool_get_doit,
7616 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit,
637989b5 7617 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
bf797471
JP
7618 /* can be retrieved by unprivileged users */
7619 },
7620 {
7621 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET,
ef6243ac 7622 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bf797471 7623 .doit = devlink_nl_cmd_sb_port_pool_set_doit,
bf797471 7624 .flags = GENL_ADMIN_PERM,
637989b5 7625 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
bf797471
JP
7626 },
7627 {
7628 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET,
ef6243ac 7629 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bf797471
JP
7630 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit,
7631 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit,
637989b5 7632 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
bf797471
JP
7633 /* can be retrieved by unprivileged users */
7634 },
7635 {
7636 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET,
ef6243ac 7637 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bf797471 7638 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit,
bf797471 7639 .flags = GENL_ADMIN_PERM,
637989b5 7640 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
bf797471 7641 },
df38dafd
JP
7642 {
7643 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT,
ef6243ac 7644 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
df38dafd 7645 .doit = devlink_nl_cmd_sb_occ_snapshot_doit,
df38dafd 7646 .flags = GENL_ADMIN_PERM,
df38dafd
JP
7647 },
7648 {
7649 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR,
ef6243ac 7650 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
df38dafd 7651 .doit = devlink_nl_cmd_sb_occ_max_clear_doit,
df38dafd 7652 .flags = GENL_ADMIN_PERM,
df38dafd 7653 },
08f4b591 7654 {
adf200f3 7655 .cmd = DEVLINK_CMD_ESWITCH_GET,
ef6243ac 7656 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
adf200f3 7657 .doit = devlink_nl_cmd_eswitch_get_doit,
08f4b591 7658 .flags = GENL_ADMIN_PERM,
637989b5 7659 .internal_flags = DEVLINK_NL_FLAG_NO_LOCK,
08f4b591
OG
7660 },
7661 {
adf200f3 7662 .cmd = DEVLINK_CMD_ESWITCH_SET,
ef6243ac 7663 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
adf200f3 7664 .doit = devlink_nl_cmd_eswitch_set_doit,
08f4b591 7665 .flags = GENL_ADMIN_PERM,
637989b5 7666 .internal_flags = DEVLINK_NL_FLAG_NO_LOCK,
08f4b591 7667 },
1555d204
AS
7668 {
7669 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET,
ef6243ac 7670 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1555d204 7671 .doit = devlink_nl_cmd_dpipe_table_get,
67ae686b 7672 /* can be retrieved by unprivileged users */
1555d204
AS
7673 },
7674 {
7675 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET,
ef6243ac 7676 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1555d204 7677 .doit = devlink_nl_cmd_dpipe_entries_get,
67ae686b 7678 /* can be retrieved by unprivileged users */
1555d204
AS
7679 },
7680 {
7681 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET,
ef6243ac 7682 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1555d204 7683 .doit = devlink_nl_cmd_dpipe_headers_get,
67ae686b 7684 /* can be retrieved by unprivileged users */
1555d204
AS
7685 },
7686 {
7687 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET,
ef6243ac 7688 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1555d204 7689 .doit = devlink_nl_cmd_dpipe_table_counters_set,
1555d204 7690 .flags = GENL_ADMIN_PERM,
1555d204 7691 },
d9f9b9a4
AS
7692 {
7693 .cmd = DEVLINK_CMD_RESOURCE_SET,
ef6243ac 7694 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
d9f9b9a4 7695 .doit = devlink_nl_cmd_resource_set,
d9f9b9a4 7696 .flags = GENL_ADMIN_PERM,
d9f9b9a4
AS
7697 },
7698 {
7699 .cmd = DEVLINK_CMD_RESOURCE_DUMP,
ef6243ac 7700 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
d9f9b9a4 7701 .doit = devlink_nl_cmd_resource_dump,
67ae686b 7702 /* can be retrieved by unprivileged users */
d9f9b9a4 7703 },
2d8dc5bb
AS
7704 {
7705 .cmd = DEVLINK_CMD_RELOAD,
ef6243ac 7706 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2d8dc5bb 7707 .doit = devlink_nl_cmd_reload,
2d8dc5bb 7708 .flags = GENL_ADMIN_PERM,
637989b5 7709 .internal_flags = DEVLINK_NL_FLAG_NO_LOCK,
2d8dc5bb 7710 },
45f05def
MS
7711 {
7712 .cmd = DEVLINK_CMD_PARAM_GET,
ef6243ac 7713 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
45f05def
MS
7714 .doit = devlink_nl_cmd_param_get_doit,
7715 .dumpit = devlink_nl_cmd_param_get_dumpit,
45f05def
MS
7716 /* can be retrieved by unprivileged users */
7717 },
e3b7ca18
MS
7718 {
7719 .cmd = DEVLINK_CMD_PARAM_SET,
ef6243ac 7720 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
e3b7ca18 7721 .doit = devlink_nl_cmd_param_set_doit,
e3b7ca18 7722 .flags = GENL_ADMIN_PERM,
e3b7ca18 7723 },
f4601dee
VV
7724 {
7725 .cmd = DEVLINK_CMD_PORT_PARAM_GET,
ef6243ac 7726 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f4601dee
VV
7727 .doit = devlink_nl_cmd_port_param_get_doit,
7728 .dumpit = devlink_nl_cmd_port_param_get_dumpit,
f4601dee
VV
7729 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
7730 /* can be retrieved by unprivileged users */
7731 },
9c54873b
VV
7732 {
7733 .cmd = DEVLINK_CMD_PORT_PARAM_SET,
ef6243ac 7734 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9c54873b 7735 .doit = devlink_nl_cmd_port_param_set_doit,
9c54873b
VV
7736 .flags = GENL_ADMIN_PERM,
7737 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
7738 },
d8db7ea5
AV
7739 {
7740 .cmd = DEVLINK_CMD_REGION_GET,
ef6243ac 7741 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
d8db7ea5
AV
7742 .doit = devlink_nl_cmd_region_get_doit,
7743 .dumpit = devlink_nl_cmd_region_get_dumpit,
d8db7ea5 7744 .flags = GENL_ADMIN_PERM,
d8db7ea5 7745 },
b9a17abf
JK
7746 {
7747 .cmd = DEVLINK_CMD_REGION_NEW,
7748 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
7749 .doit = devlink_nl_cmd_region_new,
7750 .flags = GENL_ADMIN_PERM,
b9a17abf 7751 },
866319bb
AV
7752 {
7753 .cmd = DEVLINK_CMD_REGION_DEL,
ef6243ac 7754 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
866319bb 7755 .doit = devlink_nl_cmd_region_del,
866319bb 7756 .flags = GENL_ADMIN_PERM,
866319bb 7757 },
4e54795a
AV
7758 {
7759 .cmd = DEVLINK_CMD_REGION_READ,
ee85da53
JP
7760 .validate = GENL_DONT_VALIDATE_STRICT |
7761 GENL_DONT_VALIDATE_DUMP_STRICT,
4e54795a 7762 .dumpit = devlink_nl_cmd_region_read_dumpit,
4e54795a 7763 .flags = GENL_ADMIN_PERM,
4e54795a 7764 },
f9cf2288
JK
7765 {
7766 .cmd = DEVLINK_CMD_INFO_GET,
ef6243ac 7767 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f9cf2288
JK
7768 .doit = devlink_nl_cmd_info_get_doit,
7769 .dumpit = devlink_nl_cmd_info_get_dumpit,
f9cf2288
JK
7770 /* can be retrieved by unprivileged users */
7771 },
7afe335a
EBE
7772 {
7773 .cmd = DEVLINK_CMD_HEALTH_REPORTER_GET,
ef6243ac 7774 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
7afe335a
EBE
7775 .doit = devlink_nl_cmd_health_reporter_get_doit,
7776 .dumpit = devlink_nl_cmd_health_reporter_get_dumpit,
f4f54166 7777 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT |
b587bdaf 7778 DEVLINK_NL_FLAG_NO_LOCK,
7afe335a
EBE
7779 /* can be retrieved by unprivileged users */
7780 },
a1e55ec0
EBE
7781 {
7782 .cmd = DEVLINK_CMD_HEALTH_REPORTER_SET,
ef6243ac 7783 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a1e55ec0 7784 .doit = devlink_nl_cmd_health_reporter_set_doit,
a1e55ec0 7785 .flags = GENL_ADMIN_PERM,
f4f54166 7786 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT |
b587bdaf 7787 DEVLINK_NL_FLAG_NO_LOCK,
a1e55ec0 7788 },
20a0943a
EBE
7789 {
7790 .cmd = DEVLINK_CMD_HEALTH_REPORTER_RECOVER,
ef6243ac 7791 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20a0943a 7792 .doit = devlink_nl_cmd_health_reporter_recover_doit,
20a0943a 7793 .flags = GENL_ADMIN_PERM,
f4f54166 7794 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT |
b587bdaf 7795 DEVLINK_NL_FLAG_NO_LOCK,
20a0943a 7796 },
fca42a27
EBE
7797 {
7798 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE,
ef6243ac 7799 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
fca42a27 7800 .doit = devlink_nl_cmd_health_reporter_diagnose_doit,
fca42a27 7801 .flags = GENL_ADMIN_PERM,
f4f54166 7802 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT |
b587bdaf 7803 DEVLINK_NL_FLAG_NO_LOCK,
fca42a27 7804 },
35455e23
EBE
7805 {
7806 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET,
82a843de
JP
7807 .validate = GENL_DONT_VALIDATE_STRICT |
7808 GENL_DONT_VALIDATE_DUMP_STRICT,
e44ef4e4 7809 .dumpit = devlink_nl_cmd_health_reporter_dump_get_dumpit,
35455e23 7810 .flags = GENL_ADMIN_PERM,
f4f54166 7811 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT |
35455e23
EBE
7812 DEVLINK_NL_FLAG_NO_LOCK,
7813 },
7814 {
7815 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR,
ef6243ac 7816 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
35455e23 7817 .doit = devlink_nl_cmd_health_reporter_dump_clear_doit,
35455e23 7818 .flags = GENL_ADMIN_PERM,
f4f54166 7819 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT |
35455e23
EBE
7820 DEVLINK_NL_FLAG_NO_LOCK,
7821 },
e2ce94dc
JP
7822 {
7823 .cmd = DEVLINK_CMD_HEALTH_REPORTER_TEST,
7824 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
7825 .doit = devlink_nl_cmd_health_reporter_test_doit,
7826 .flags = GENL_ADMIN_PERM,
7827 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT |
7828 DEVLINK_NL_FLAG_NO_LOCK,
7829 },
76726ccb
JK
7830 {
7831 .cmd = DEVLINK_CMD_FLASH_UPDATE,
ef6243ac 7832 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
76726ccb 7833 .doit = devlink_nl_cmd_flash_update,
76726ccb 7834 .flags = GENL_ADMIN_PERM,
76726ccb 7835 },
0f420b6c
IS
7836 {
7837 .cmd = DEVLINK_CMD_TRAP_GET,
7838 .doit = devlink_nl_cmd_trap_get_doit,
7839 .dumpit = devlink_nl_cmd_trap_get_dumpit,
0f420b6c
IS
7840 /* can be retrieved by unprivileged users */
7841 },
7842 {
7843 .cmd = DEVLINK_CMD_TRAP_SET,
7844 .doit = devlink_nl_cmd_trap_set_doit,
7845 .flags = GENL_ADMIN_PERM,
0f420b6c
IS
7846 },
7847 {
7848 .cmd = DEVLINK_CMD_TRAP_GROUP_GET,
7849 .doit = devlink_nl_cmd_trap_group_get_doit,
7850 .dumpit = devlink_nl_cmd_trap_group_get_dumpit,
0f420b6c
IS
7851 /* can be retrieved by unprivileged users */
7852 },
7853 {
7854 .cmd = DEVLINK_CMD_TRAP_GROUP_SET,
7855 .doit = devlink_nl_cmd_trap_group_set_doit,
7856 .flags = GENL_ADMIN_PERM,
0f420b6c 7857 },
1e8c6619
IS
7858 {
7859 .cmd = DEVLINK_CMD_TRAP_POLICER_GET,
7860 .doit = devlink_nl_cmd_trap_policer_get_doit,
7861 .dumpit = devlink_nl_cmd_trap_policer_get_dumpit,
1e8c6619
IS
7862 /* can be retrieved by unprivileged users */
7863 },
7864 {
7865 .cmd = DEVLINK_CMD_TRAP_POLICER_SET,
7866 .doit = devlink_nl_cmd_trap_policer_set_doit,
7867 .flags = GENL_ADMIN_PERM,
1e8c6619 7868 },
bfcd3a46
JP
7869};
7870
56989f6d 7871static struct genl_family devlink_nl_family __ro_after_init = {
489111e5
JB
7872 .name = DEVLINK_GENL_NAME,
7873 .version = DEVLINK_GENL_VERSION,
7874 .maxattr = DEVLINK_ATTR_MAX,
3b0f31f2 7875 .policy = devlink_nl_policy,
489111e5
JB
7876 .netnsok = true,
7877 .pre_doit = devlink_nl_pre_doit,
7878 .post_doit = devlink_nl_post_doit,
7879 .module = THIS_MODULE,
66a9b928
JK
7880 .small_ops = devlink_nl_ops,
7881 .n_small_ops = ARRAY_SIZE(devlink_nl_ops),
489111e5
JB
7882 .mcgrps = devlink_nl_mcgrps,
7883 .n_mcgrps = ARRAY_SIZE(devlink_nl_mcgrps),
7884};
7885
ccdf0721
MS
7886static bool devlink_reload_actions_valid(const struct devlink_ops *ops)
7887{
dc64cc7c
MS
7888 const struct devlink_reload_combination *comb;
7889 int i;
7890
ccdf0721
MS
7891 if (!devlink_reload_supported(ops)) {
7892 if (WARN_ON(ops->reload_actions))
7893 return false;
7894 return true;
7895 }
7896
7897 if (WARN_ON(!ops->reload_actions ||
7898 ops->reload_actions & BIT(DEVLINK_RELOAD_ACTION_UNSPEC) ||
7899 ops->reload_actions >= BIT(__DEVLINK_RELOAD_ACTION_MAX)))
7900 return false;
dc64cc7c
MS
7901
7902 if (WARN_ON(ops->reload_limits & BIT(DEVLINK_RELOAD_LIMIT_UNSPEC) ||
7903 ops->reload_limits >= BIT(__DEVLINK_RELOAD_LIMIT_MAX)))
7904 return false;
7905
7906 for (i = 0; i < ARRAY_SIZE(devlink_reload_invalid_combinations); i++) {
7907 comb = &devlink_reload_invalid_combinations[i];
7908 if (ops->reload_actions == BIT(comb->action) &&
7909 ops->reload_limits == BIT(comb->limit))
7910 return false;
7911 }
ccdf0721
MS
7912 return true;
7913}
7914
bfcd3a46
JP
7915/**
7916 * devlink_alloc - Allocate new devlink instance resources
7917 *
7918 * @ops: ops
7919 * @priv_size: size of user private data
7920 *
7921 * Allocate new devlink instance resources, including devlink index
7922 * and name.
7923 */
7924struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
7925{
7926 struct devlink *devlink;
7927
be6fe1d8
JK
7928 if (WARN_ON(!ops))
7929 return NULL;
7930
ccdf0721
MS
7931 if (!devlink_reload_actions_valid(ops))
7932 return NULL;
7933
bfcd3a46
JP
7934 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL);
7935 if (!devlink)
7936 return NULL;
7937 devlink->ops = ops;
12102436 7938 xa_init_flags(&devlink->snapshot_ids, XA_FLAGS_ALLOC);
8273fd84 7939 __devlink_net_set(devlink, &init_net);
bfcd3a46 7940 INIT_LIST_HEAD(&devlink->port_list);
bf797471 7941 INIT_LIST_HEAD(&devlink->sb_list);
1555d204 7942 INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list);
d9f9b9a4 7943 INIT_LIST_HEAD(&devlink->resource_list);
eabaef18 7944 INIT_LIST_HEAD(&devlink->param_list);
b16ebe92 7945 INIT_LIST_HEAD(&devlink->region_list);
a0bdcc59 7946 INIT_LIST_HEAD(&devlink->reporter_list);
0f420b6c
IS
7947 INIT_LIST_HEAD(&devlink->trap_list);
7948 INIT_LIST_HEAD(&devlink->trap_group_list);
1e8c6619 7949 INIT_LIST_HEAD(&devlink->trap_policer_list);
2406e7e5 7950 mutex_init(&devlink->lock);
b587bdaf 7951 mutex_init(&devlink->reporters_lock);
bfcd3a46
JP
7952 return devlink;
7953}
7954EXPORT_SYMBOL_GPL(devlink_alloc);
7955
7956/**
7957 * devlink_register - Register devlink instance
7958 *
7959 * @devlink: devlink
eeaadd82 7960 * @dev: parent device
bfcd3a46
JP
7961 */
7962int devlink_register(struct devlink *devlink, struct device *dev)
7963{
bfcd3a46 7964 devlink->dev = dev;
8273fd84 7965 devlink->registered = true;
6553e561 7966 mutex_lock(&devlink_mutex);
bfcd3a46
JP
7967 list_add_tail(&devlink->list, &devlink_list);
7968 devlink_notify(devlink, DEVLINK_CMD_NEW);
7969 mutex_unlock(&devlink_mutex);
7970 return 0;
7971}
7972EXPORT_SYMBOL_GPL(devlink_register);
7973
7974/**
7975 * devlink_unregister - Unregister devlink instance
7976 *
7977 * @devlink: devlink
7978 */
7979void devlink_unregister(struct devlink *devlink)
7980{
7981 mutex_lock(&devlink_mutex);
69d56e0e 7982 WARN_ON(devlink_reload_supported(devlink->ops) &&
a0c76345 7983 devlink->reload_enabled);
bfcd3a46
JP
7984 devlink_notify(devlink, DEVLINK_CMD_DEL);
7985 list_del(&devlink->list);
7986 mutex_unlock(&devlink_mutex);
7987}
7988EXPORT_SYMBOL_GPL(devlink_unregister);
7989
a0c76345
JP
7990/**
7991 * devlink_reload_enable - Enable reload of devlink instance
7992 *
7993 * @devlink: devlink
7994 *
7995 * Should be called at end of device initialization
7996 * process when reload operation is supported.
7997 */
7998void devlink_reload_enable(struct devlink *devlink)
7999{
8000 mutex_lock(&devlink_mutex);
8001 devlink->reload_enabled = true;
8002 mutex_unlock(&devlink_mutex);
8003}
8004EXPORT_SYMBOL_GPL(devlink_reload_enable);
8005
8006/**
8007 * devlink_reload_disable - Disable reload of devlink instance
8008 *
8009 * @devlink: devlink
8010 *
8011 * Should be called at the beginning of device cleanup
8012 * process when reload operation is supported.
8013 */
8014void devlink_reload_disable(struct devlink *devlink)
8015{
8016 mutex_lock(&devlink_mutex);
8017 /* Mutex is taken which ensures that no reload operation is in
8018 * progress while setting up forbidded flag.
8019 */
8020 devlink->reload_enabled = false;
8021 mutex_unlock(&devlink_mutex);
8022}
8023EXPORT_SYMBOL_GPL(devlink_reload_disable);
8024
bfcd3a46
JP
8025/**
8026 * devlink_free - Free devlink instance resources
8027 *
8028 * @devlink: devlink
8029 */
8030void devlink_free(struct devlink *devlink)
8031{
b587bdaf 8032 mutex_destroy(&devlink->reporters_lock);
375cf8c6 8033 mutex_destroy(&devlink->lock);
1e8c6619 8034 WARN_ON(!list_empty(&devlink->trap_policer_list));
0f420b6c
IS
8035 WARN_ON(!list_empty(&devlink->trap_group_list));
8036 WARN_ON(!list_empty(&devlink->trap_list));
b904aada
PP
8037 WARN_ON(!list_empty(&devlink->reporter_list));
8038 WARN_ON(!list_empty(&devlink->region_list));
8039 WARN_ON(!list_empty(&devlink->param_list));
8040 WARN_ON(!list_empty(&devlink->resource_list));
8041 WARN_ON(!list_empty(&devlink->dpipe_table_list));
8042 WARN_ON(!list_empty(&devlink->sb_list));
8043 WARN_ON(!list_empty(&devlink->port_list));
8044
12102436
JK
8045 xa_destroy(&devlink->snapshot_ids);
8046
bfcd3a46
JP
8047 kfree(devlink);
8048}
8049EXPORT_SYMBOL_GPL(devlink_free);
8050
136bf27f
JP
8051static void devlink_port_type_warn(struct work_struct *work)
8052{
8053 WARN(true, "Type was not set for devlink port.");
8054}
8055
8056static bool devlink_port_type_should_warn(struct devlink_port *devlink_port)
8057{
8058 /* Ignore CPU and DSA flavours. */
8059 return devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_CPU &&
cf116634
AL
8060 devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_DSA &&
8061 devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_UNUSED;
136bf27f
JP
8062}
8063
4c582234 8064#define DEVLINK_PORT_TYPE_WARN_TIMEOUT (HZ * 3600)
136bf27f
JP
8065
8066static void devlink_port_type_warn_schedule(struct devlink_port *devlink_port)
8067{
8068 if (!devlink_port_type_should_warn(devlink_port))
8069 return;
8070 /* Schedule a work to WARN in case driver does not set port
8071 * type within timeout.
8072 */
8073 schedule_delayed_work(&devlink_port->type_warn_dw,
8074 DEVLINK_PORT_TYPE_WARN_TIMEOUT);
8075}
8076
8077static void devlink_port_type_warn_cancel(struct devlink_port *devlink_port)
8078{
8079 if (!devlink_port_type_should_warn(devlink_port))
8080 return;
8081 cancel_delayed_work_sync(&devlink_port->type_warn_dw);
8082}
8083
bfcd3a46
JP
8084/**
8085 * devlink_port_register - Register devlink port
8086 *
8087 * @devlink: devlink
8088 * @devlink_port: devlink port
eeaadd82 8089 * @port_index: driver-specific numerical identifier of the port
bfcd3a46
JP
8090 *
8091 * Register devlink port with provided port index. User can use
8092 * any indexing, even hw-related one. devlink_port structure
8093 * is convenient to be embedded inside user driver private structure.
8094 * Note that the caller should take care of zeroing the devlink_port
8095 * structure.
8096 */
8097int devlink_port_register(struct devlink *devlink,
8098 struct devlink_port *devlink_port,
8099 unsigned int port_index)
8100{
2406e7e5 8101 mutex_lock(&devlink->lock);
bfcd3a46 8102 if (devlink_port_index_exists(devlink, port_index)) {
2406e7e5 8103 mutex_unlock(&devlink->lock);
bfcd3a46
JP
8104 return -EEXIST;
8105 }
8106 devlink_port->devlink = devlink;
8107 devlink_port->index = port_index;
bfcd3a46 8108 devlink_port->registered = true;
b8f97554 8109 spin_lock_init(&devlink_port->type_lock);
79604c5d
PP
8110 INIT_LIST_HEAD(&devlink_port->reporter_list);
8111 mutex_init(&devlink_port->reporters_lock);
bfcd3a46 8112 list_add_tail(&devlink_port->list, &devlink->port_list);
39e6160e 8113 INIT_LIST_HEAD(&devlink_port->param_list);
544e7c33 8114 INIT_LIST_HEAD(&devlink_port->region_list);
2406e7e5 8115 mutex_unlock(&devlink->lock);
136bf27f
JP
8116 INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn);
8117 devlink_port_type_warn_schedule(devlink_port);
bfcd3a46
JP
8118 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
8119 return 0;
8120}
8121EXPORT_SYMBOL_GPL(devlink_port_register);
8122
8123/**
8124 * devlink_port_unregister - Unregister devlink port
8125 *
8126 * @devlink_port: devlink port
8127 */
8128void devlink_port_unregister(struct devlink_port *devlink_port)
8129{
2406e7e5
AS
8130 struct devlink *devlink = devlink_port->devlink;
8131
136bf27f 8132 devlink_port_type_warn_cancel(devlink_port);
bfcd3a46 8133 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
2406e7e5 8134 mutex_lock(&devlink->lock);
bfcd3a46 8135 list_del(&devlink_port->list);
2406e7e5 8136 mutex_unlock(&devlink->lock);
79604c5d 8137 WARN_ON(!list_empty(&devlink_port->reporter_list));
544e7c33 8138 WARN_ON(!list_empty(&devlink_port->region_list));
79604c5d 8139 mutex_destroy(&devlink_port->reporters_lock);
bfcd3a46
JP
8140}
8141EXPORT_SYMBOL_GPL(devlink_port_unregister);
8142
8143static void __devlink_port_type_set(struct devlink_port *devlink_port,
8144 enum devlink_port_type type,
8145 void *type_dev)
8146{
2b239e70
JP
8147 if (WARN_ON(!devlink_port->registered))
8148 return;
136bf27f 8149 devlink_port_type_warn_cancel(devlink_port);
0f420b6c 8150 spin_lock_bh(&devlink_port->type_lock);
bfcd3a46
JP
8151 devlink_port->type = type;
8152 devlink_port->type_dev = type_dev;
0f420b6c 8153 spin_unlock_bh(&devlink_port->type_lock);
bfcd3a46
JP
8154 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
8155}
8156
3ea87ca7
JK
8157static void devlink_port_type_netdev_checks(struct devlink_port *devlink_port,
8158 struct net_device *netdev)
bfcd3a46 8159{
119c0b57
JP
8160 const struct net_device_ops *ops = netdev->netdev_ops;
8161
746364f2
JP
8162 /* If driver registers devlink port, it should set devlink port
8163 * attributes accordingly so the compat functions are called
8164 * and the original ops are not used.
8165 */
119c0b57 8166 if (ops->ndo_get_phys_port_name) {
746364f2
JP
8167 /* Some drivers use the same set of ndos for netdevs
8168 * that have devlink_port registered and also for
8169 * those who don't. Make sure that ndo_get_phys_port_name
8170 * returns -EOPNOTSUPP here in case it is defined.
8171 * Warn if not.
8172 */
746364f2
JP
8173 char name[IFNAMSIZ];
8174 int err;
8175
8176 err = ops->ndo_get_phys_port_name(netdev, name, sizeof(name));
8177 WARN_ON(err != -EOPNOTSUPP);
8178 }
119c0b57
JP
8179 if (ops->ndo_get_port_parent_id) {
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_port_parent_id
8183 * returns -EOPNOTSUPP here in case it is defined.
8184 * Warn if not.
8185 */
8186 struct netdev_phys_item_id ppid;
8187 int err;
8188
8189 err = ops->ndo_get_port_parent_id(netdev, &ppid);
8190 WARN_ON(err != -EOPNOTSUPP);
8191 }
3ea87ca7
JK
8192}
8193
8194/**
8195 * devlink_port_type_eth_set - Set port type to Ethernet
8196 *
8197 * @devlink_port: devlink port
8198 * @netdev: related netdevice
8199 */
8200void devlink_port_type_eth_set(struct devlink_port *devlink_port,
8201 struct net_device *netdev)
8202{
8203 if (netdev)
8204 devlink_port_type_netdev_checks(devlink_port, netdev);
8205 else
8206 dev_warn(devlink_port->devlink->dev,
8207 "devlink port type for port %d set to Ethernet without a software interface reference, device type not supported by the kernel?\n",
8208 devlink_port->index);
8209
773b1f38 8210 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, netdev);
bfcd3a46
JP
8211}
8212EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
8213
8214/**
8215 * devlink_port_type_ib_set - Set port type to InfiniBand
8216 *
8217 * @devlink_port: devlink port
8218 * @ibdev: related IB device
8219 */
8220void devlink_port_type_ib_set(struct devlink_port *devlink_port,
8221 struct ib_device *ibdev)
8222{
773b1f38 8223 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_IB, ibdev);
bfcd3a46
JP
8224}
8225EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
8226
8227/**
8228 * devlink_port_type_clear - Clear port type
8229 *
8230 * @devlink_port: devlink port
8231 */
8232void devlink_port_type_clear(struct devlink_port *devlink_port)
8233{
773b1f38 8234 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL);
136bf27f 8235 devlink_port_type_warn_schedule(devlink_port);
bfcd3a46
JP
8236}
8237EXPORT_SYMBOL_GPL(devlink_port_type_clear);
8238
378ef01b 8239static int __devlink_port_attrs_set(struct devlink_port *devlink_port,
71ad8d55 8240 enum devlink_port_flavour flavour)
378ef01b
PP
8241{
8242 struct devlink_port_attrs *attrs = &devlink_port->attrs;
8243
8244 if (WARN_ON(devlink_port->registered))
8245 return -EEXIST;
10a429ba 8246 devlink_port->attrs_set = true;
378ef01b 8247 attrs->flavour = flavour;
71ad8d55 8248 if (attrs->switch_id.id_len) {
46737a19 8249 devlink_port->switch_port = true;
71ad8d55
DR
8250 if (WARN_ON(attrs->switch_id.id_len > MAX_PHYS_ITEM_ID_LEN))
8251 attrs->switch_id.id_len = MAX_PHYS_ITEM_ID_LEN;
378ef01b 8252 } else {
46737a19 8253 devlink_port->switch_port = false;
378ef01b
PP
8254 }
8255 return 0;
8256}
8257
bfcd3a46 8258/**
b9ffcbaf 8259 * devlink_port_attrs_set - Set port attributes
bfcd3a46
JP
8260 *
8261 * @devlink_port: devlink port
71ad8d55 8262 * @attrs: devlink port attrs
bfcd3a46 8263 */
b9ffcbaf 8264void devlink_port_attrs_set(struct devlink_port *devlink_port,
71ad8d55 8265 struct devlink_port_attrs *attrs)
bfcd3a46 8266{
378ef01b 8267 int ret;
b9ffcbaf 8268
71ad8d55
DR
8269 devlink_port->attrs = *attrs;
8270 ret = __devlink_port_attrs_set(devlink_port, attrs->flavour);
378ef01b 8271 if (ret)
45b86112 8272 return;
a0f49b54 8273 WARN_ON(attrs->splittable && attrs->split);
bfcd3a46 8274}
b9ffcbaf 8275EXPORT_SYMBOL_GPL(devlink_port_attrs_set);
bfcd3a46 8276
98fd2d65
PP
8277/**
8278 * devlink_port_attrs_pci_pf_set - Set PCI PF port attributes
8279 *
8280 * @devlink_port: devlink port
3a2d9588 8281 * @controller: associated controller number for the devlink port instance
98fd2d65 8282 * @pf: associated PF for the devlink port instance
05b595e9 8283 * @external: indicates if the port is for an external controller
98fd2d65 8284 */
3a2d9588
PP
8285void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u32 controller,
8286 u16 pf, bool external)
98fd2d65
PP
8287{
8288 struct devlink_port_attrs *attrs = &devlink_port->attrs;
8289 int ret;
8290
8291 ret = __devlink_port_attrs_set(devlink_port,
71ad8d55 8292 DEVLINK_PORT_FLAVOUR_PCI_PF);
98fd2d65
PP
8293 if (ret)
8294 return;
3a2d9588 8295 attrs->pci_pf.controller = controller;
98fd2d65 8296 attrs->pci_pf.pf = pf;
05b595e9 8297 attrs->pci_pf.external = external;
98fd2d65
PP
8298}
8299EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_pf_set);
8300
e41b6bf3
PP
8301/**
8302 * devlink_port_attrs_pci_vf_set - Set PCI VF port attributes
8303 *
8304 * @devlink_port: devlink port
3a2d9588 8305 * @controller: associated controller number for the devlink port instance
e41b6bf3
PP
8306 * @pf: associated PF for the devlink port instance
8307 * @vf: associated VF of a PF for the devlink port instance
05b595e9 8308 * @external: indicates if the port is for an external controller
e41b6bf3 8309 */
3a2d9588 8310void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, u32 controller,
05b595e9 8311 u16 pf, u16 vf, bool external)
e41b6bf3
PP
8312{
8313 struct devlink_port_attrs *attrs = &devlink_port->attrs;
8314 int ret;
8315
8316 ret = __devlink_port_attrs_set(devlink_port,
71ad8d55 8317 DEVLINK_PORT_FLAVOUR_PCI_VF);
e41b6bf3
PP
8318 if (ret)
8319 return;
3a2d9588 8320 attrs->pci_vf.controller = controller;
e41b6bf3
PP
8321 attrs->pci_vf.pf = pf;
8322 attrs->pci_vf.vf = vf;
05b595e9 8323 attrs->pci_vf.external = external;
e41b6bf3
PP
8324}
8325EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_vf_set);
8326
af3836df
JP
8327static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port,
8328 char *name, size_t len)
08474c1a
JP
8329{
8330 struct devlink_port_attrs *attrs = &devlink_port->attrs;
8331 int n = 0;
8332
10a429ba 8333 if (!devlink_port->attrs_set)
08474c1a
JP
8334 return -EOPNOTSUPP;
8335
8336 switch (attrs->flavour) {
8337 case DEVLINK_PORT_FLAVOUR_PHYSICAL:
acf1ee44 8338 case DEVLINK_PORT_FLAVOUR_VIRTUAL:
08474c1a 8339 if (!attrs->split)
378ef01b 8340 n = snprintf(name, len, "p%u", attrs->phys.port_number);
08474c1a 8341 else
378ef01b
PP
8342 n = snprintf(name, len, "p%us%u",
8343 attrs->phys.port_number,
8344 attrs->phys.split_subport_number);
08474c1a
JP
8345 break;
8346 case DEVLINK_PORT_FLAVOUR_CPU:
8347 case DEVLINK_PORT_FLAVOUR_DSA:
cf116634 8348 case DEVLINK_PORT_FLAVOUR_UNUSED:
08474c1a
JP
8349 /* As CPU and DSA ports do not have a netdevice associated
8350 * case should not ever happen.
8351 */
8352 WARN_ON(1);
8353 return -EINVAL;
98fd2d65 8354 case DEVLINK_PORT_FLAVOUR_PCI_PF:
66b17082
PP
8355 if (attrs->pci_pf.external) {
8356 n = snprintf(name, len, "c%u", attrs->pci_pf.controller);
8357 if (n >= len)
8358 return -EINVAL;
8359 len -= n;
8360 name += n;
8361 }
98fd2d65
PP
8362 n = snprintf(name, len, "pf%u", attrs->pci_pf.pf);
8363 break;
e41b6bf3 8364 case DEVLINK_PORT_FLAVOUR_PCI_VF:
66b17082
PP
8365 if (attrs->pci_vf.external) {
8366 n = snprintf(name, len, "c%u", attrs->pci_vf.controller);
8367 if (n >= len)
8368 return -EINVAL;
8369 len -= n;
8370 name += n;
8371 }
e41b6bf3
PP
8372 n = snprintf(name, len, "pf%uvf%u",
8373 attrs->pci_vf.pf, attrs->pci_vf.vf);
8374 break;
08474c1a
JP
8375 }
8376
8377 if (n >= len)
8378 return -EINVAL;
8379
8380 return 0;
8381}
af3836df 8382
bf797471
JP
8383int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
8384 u32 size, u16 ingress_pools_count,
8385 u16 egress_pools_count, u16 ingress_tc_count,
8386 u16 egress_tc_count)
8387{
8388 struct devlink_sb *devlink_sb;
8389 int err = 0;
8390
2406e7e5 8391 mutex_lock(&devlink->lock);
bf797471
JP
8392 if (devlink_sb_index_exists(devlink, sb_index)) {
8393 err = -EEXIST;
8394 goto unlock;
8395 }
8396
8397 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL);
8398 if (!devlink_sb) {
8399 err = -ENOMEM;
8400 goto unlock;
8401 }
8402 devlink_sb->index = sb_index;
8403 devlink_sb->size = size;
8404 devlink_sb->ingress_pools_count = ingress_pools_count;
8405 devlink_sb->egress_pools_count = egress_pools_count;
8406 devlink_sb->ingress_tc_count = ingress_tc_count;
8407 devlink_sb->egress_tc_count = egress_tc_count;
8408 list_add_tail(&devlink_sb->list, &devlink->sb_list);
8409unlock:
2406e7e5 8410 mutex_unlock(&devlink->lock);
bf797471
JP
8411 return err;
8412}
8413EXPORT_SYMBOL_GPL(devlink_sb_register);
8414
8415void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index)
8416{
8417 struct devlink_sb *devlink_sb;
8418
2406e7e5 8419 mutex_lock(&devlink->lock);
bf797471
JP
8420 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
8421 WARN_ON(!devlink_sb);
8422 list_del(&devlink_sb->list);
2406e7e5 8423 mutex_unlock(&devlink->lock);
bf797471
JP
8424 kfree(devlink_sb);
8425}
8426EXPORT_SYMBOL_GPL(devlink_sb_unregister);
8427
1555d204
AS
8428/**
8429 * devlink_dpipe_headers_register - register dpipe headers
8430 *
8431 * @devlink: devlink
8432 * @dpipe_headers: dpipe header array
8433 *
8434 * Register the headers supported by hardware.
8435 */
8436int devlink_dpipe_headers_register(struct devlink *devlink,
8437 struct devlink_dpipe_headers *dpipe_headers)
8438{
2406e7e5 8439 mutex_lock(&devlink->lock);
1555d204 8440 devlink->dpipe_headers = dpipe_headers;
2406e7e5 8441 mutex_unlock(&devlink->lock);
1555d204
AS
8442 return 0;
8443}
8444EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register);
8445
8446/**
8447 * devlink_dpipe_headers_unregister - unregister dpipe headers
8448 *
8449 * @devlink: devlink
8450 *
8451 * Unregister the headers supported by hardware.
8452 */
8453void devlink_dpipe_headers_unregister(struct devlink *devlink)
8454{
2406e7e5 8455 mutex_lock(&devlink->lock);
1555d204 8456 devlink->dpipe_headers = NULL;
2406e7e5 8457 mutex_unlock(&devlink->lock);
1555d204
AS
8458}
8459EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister);
8460
8461/**
8462 * devlink_dpipe_table_counter_enabled - check if counter allocation
8463 * required
8464 * @devlink: devlink
8465 * @table_name: tables name
8466 *
8467 * Used by driver to check if counter allocation is required.
8468 * After counter allocation is turned on the table entries
8469 * are updated to include counter statistics.
8470 *
8471 * After that point on the driver must respect the counter
8472 * state so that each entry added to the table is added
8473 * with a counter.
8474 */
8475bool devlink_dpipe_table_counter_enabled(struct devlink *devlink,
8476 const char *table_name)
8477{
8478 struct devlink_dpipe_table *table;
8479 bool enabled;
8480
8481 rcu_read_lock();
8482 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2eb51c75 8483 table_name, devlink);
1555d204
AS
8484 enabled = false;
8485 if (table)
8486 enabled = table->counters_enabled;
8487 rcu_read_unlock();
8488 return enabled;
8489}
8490EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled);
8491
8492/**
8493 * devlink_dpipe_table_register - register dpipe table
8494 *
8495 * @devlink: devlink
8496 * @table_name: table name
8497 * @table_ops: table ops
8498 * @priv: priv
1555d204
AS
8499 * @counter_control_extern: external control for counters
8500 */
8501int devlink_dpipe_table_register(struct devlink *devlink,
8502 const char *table_name,
8503 struct devlink_dpipe_table_ops *table_ops,
ffd3cdcc 8504 void *priv, bool counter_control_extern)
1555d204
AS
8505{
8506 struct devlink_dpipe_table *table;
6132c1d9 8507 int err = 0;
1555d204 8508
ffd3cdcc
AS
8509 if (WARN_ON(!table_ops->size_get))
8510 return -EINVAL;
8511
6132c1d9
MB
8512 mutex_lock(&devlink->lock);
8513
2eb51c75
MB
8514 if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name,
8515 devlink)) {
6132c1d9
MB
8516 err = -EEXIST;
8517 goto unlock;
8518 }
8519
1555d204 8520 table = kzalloc(sizeof(*table), GFP_KERNEL);
6132c1d9
MB
8521 if (!table) {
8522 err = -ENOMEM;
8523 goto unlock;
8524 }
1555d204
AS
8525
8526 table->name = table_name;
8527 table->table_ops = table_ops;
8528 table->priv = priv;
1555d204
AS
8529 table->counter_control_extern = counter_control_extern;
8530
1555d204 8531 list_add_tail_rcu(&table->list, &devlink->dpipe_table_list);
6132c1d9 8532unlock:
2406e7e5 8533 mutex_unlock(&devlink->lock);
6132c1d9 8534 return err;
1555d204
AS
8535}
8536EXPORT_SYMBOL_GPL(devlink_dpipe_table_register);
8537
8538/**
8539 * devlink_dpipe_table_unregister - unregister dpipe table
8540 *
8541 * @devlink: devlink
8542 * @table_name: table name
8543 */
8544void devlink_dpipe_table_unregister(struct devlink *devlink,
8545 const char *table_name)
8546{
8547 struct devlink_dpipe_table *table;
8548
2406e7e5 8549 mutex_lock(&devlink->lock);
1555d204 8550 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2eb51c75 8551 table_name, devlink);
1555d204
AS
8552 if (!table)
8553 goto unlock;
8554 list_del_rcu(&table->list);
2406e7e5 8555 mutex_unlock(&devlink->lock);
1555d204
AS
8556 kfree_rcu(table, rcu);
8557 return;
8558unlock:
2406e7e5 8559 mutex_unlock(&devlink->lock);
1555d204
AS
8560}
8561EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister);
8562
d9f9b9a4
AS
8563/**
8564 * devlink_resource_register - devlink resource register
8565 *
8566 * @devlink: devlink
8567 * @resource_name: resource's name
d9f9b9a4
AS
8568 * @resource_size: resource's size
8569 * @resource_id: resource's id
eeaadd82
JK
8570 * @parent_resource_id: resource's parent id
8571 * @size_params: size parameters
d9f9b9a4
AS
8572 */
8573int devlink_resource_register(struct devlink *devlink,
8574 const char *resource_name,
d9f9b9a4
AS
8575 u64 resource_size,
8576 u64 resource_id,
8577 u64 parent_resource_id,
fc56be47 8578 const struct devlink_resource_size_params *size_params)
d9f9b9a4
AS
8579{
8580 struct devlink_resource *resource;
8581 struct list_head *resource_list;
14530746 8582 bool top_hierarchy;
d9f9b9a4
AS
8583 int err = 0;
8584
14530746
DA
8585 top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP;
8586
d9f9b9a4
AS
8587 mutex_lock(&devlink->lock);
8588 resource = devlink_resource_find(devlink, NULL, resource_id);
8589 if (resource) {
8590 err = -EINVAL;
8591 goto out;
8592 }
8593
8594 resource = kzalloc(sizeof(*resource), GFP_KERNEL);
8595 if (!resource) {
8596 err = -ENOMEM;
8597 goto out;
8598 }
8599
8600 if (top_hierarchy) {
8601 resource_list = &devlink->resource_list;
8602 } else {
8603 struct devlink_resource *parent_resource;
8604
8605 parent_resource = devlink_resource_find(devlink, NULL,
8606 parent_resource_id);
8607 if (parent_resource) {
8608 resource_list = &parent_resource->resource_list;
8609 resource->parent = parent_resource;
8610 } else {
b75703de 8611 kfree(resource);
d9f9b9a4
AS
8612 err = -EINVAL;
8613 goto out;
8614 }
8615 }
8616
8617 resource->name = resource_name;
8618 resource->size = resource_size;
8619 resource->size_new = resource_size;
8620 resource->id = resource_id;
d9f9b9a4 8621 resource->size_valid = true;
77d27096
JP
8622 memcpy(&resource->size_params, size_params,
8623 sizeof(resource->size_params));
d9f9b9a4
AS
8624 INIT_LIST_HEAD(&resource->resource_list);
8625 list_add_tail(&resource->list, resource_list);
8626out:
8627 mutex_unlock(&devlink->lock);
8628 return err;
8629}
8630EXPORT_SYMBOL_GPL(devlink_resource_register);
8631
8632/**
8633 * devlink_resources_unregister - free all resources
8634 *
8635 * @devlink: devlink
8636 * @resource: resource
8637 */
8638void devlink_resources_unregister(struct devlink *devlink,
8639 struct devlink_resource *resource)
8640{
8641 struct devlink_resource *tmp, *child_resource;
8642 struct list_head *resource_list;
8643
8644 if (resource)
8645 resource_list = &resource->resource_list;
8646 else
8647 resource_list = &devlink->resource_list;
8648
8649 if (!resource)
8650 mutex_lock(&devlink->lock);
8651
8652 list_for_each_entry_safe(child_resource, tmp, resource_list, list) {
8653 devlink_resources_unregister(devlink, child_resource);
8654 list_del(&child_resource->list);
8655 kfree(child_resource);
8656 }
8657
8658 if (!resource)
8659 mutex_unlock(&devlink->lock);
8660}
8661EXPORT_SYMBOL_GPL(devlink_resources_unregister);
8662
8663/**
8664 * devlink_resource_size_get - get and update size
8665 *
8666 * @devlink: devlink
8667 * @resource_id: the requested resource id
8668 * @p_resource_size: ptr to update
8669 */
8670int devlink_resource_size_get(struct devlink *devlink,
8671 u64 resource_id,
8672 u64 *p_resource_size)
8673{
8674 struct devlink_resource *resource;
8675 int err = 0;
8676
8677 mutex_lock(&devlink->lock);
8678 resource = devlink_resource_find(devlink, NULL, resource_id);
8679 if (!resource) {
8680 err = -EINVAL;
8681 goto out;
8682 }
8683 *p_resource_size = resource->size_new;
8684 resource->size = resource->size_new;
8685out:
8686 mutex_unlock(&devlink->lock);
8687 return err;
8688}
8689EXPORT_SYMBOL_GPL(devlink_resource_size_get);
8690
56dc7cd0
AS
8691/**
8692 * devlink_dpipe_table_resource_set - set the resource id
8693 *
8694 * @devlink: devlink
8695 * @table_name: table name
8696 * @resource_id: resource id
8697 * @resource_units: number of resource's units consumed per table's entry
8698 */
8699int devlink_dpipe_table_resource_set(struct devlink *devlink,
8700 const char *table_name, u64 resource_id,
8701 u64 resource_units)
8702{
8703 struct devlink_dpipe_table *table;
8704 int err = 0;
8705
8706 mutex_lock(&devlink->lock);
8707 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2eb51c75 8708 table_name, devlink);
56dc7cd0
AS
8709 if (!table) {
8710 err = -EINVAL;
8711 goto out;
8712 }
8713 table->resource_id = resource_id;
8714 table->resource_units = resource_units;
8715 table->resource_valid = true;
8716out:
8717 mutex_unlock(&devlink->lock);
8718 return err;
8719}
8720EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set);
8721
fc56be47
JP
8722/**
8723 * devlink_resource_occ_get_register - register occupancy getter
8724 *
8725 * @devlink: devlink
8726 * @resource_id: resource id
8727 * @occ_get: occupancy getter callback
8728 * @occ_get_priv: occupancy getter callback priv
8729 */
8730void devlink_resource_occ_get_register(struct devlink *devlink,
8731 u64 resource_id,
8732 devlink_resource_occ_get_t *occ_get,
8733 void *occ_get_priv)
8734{
8735 struct devlink_resource *resource;
8736
8737 mutex_lock(&devlink->lock);
8738 resource = devlink_resource_find(devlink, NULL, resource_id);
8739 if (WARN_ON(!resource))
8740 goto out;
8741 WARN_ON(resource->occ_get);
8742
8743 resource->occ_get = occ_get;
8744 resource->occ_get_priv = occ_get_priv;
8745out:
8746 mutex_unlock(&devlink->lock);
8747}
8748EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register);
8749
8750/**
8751 * devlink_resource_occ_get_unregister - unregister occupancy getter
8752 *
8753 * @devlink: devlink
8754 * @resource_id: resource id
8755 */
8756void devlink_resource_occ_get_unregister(struct devlink *devlink,
8757 u64 resource_id)
8758{
8759 struct devlink_resource *resource;
8760
8761 mutex_lock(&devlink->lock);
8762 resource = devlink_resource_find(devlink, NULL, resource_id);
8763 if (WARN_ON(!resource))
8764 goto out;
8765 WARN_ON(!resource->occ_get);
8766
8767 resource->occ_get = NULL;
8768 resource->occ_get_priv = NULL;
8769out:
8770 mutex_unlock(&devlink->lock);
8771}
8772EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister);
8773
39e6160e
VV
8774static int devlink_param_verify(const struct devlink_param *param)
8775{
8776 if (!param || !param->name || !param->supported_cmodes)
8777 return -EINVAL;
8778 if (param->generic)
8779 return devlink_param_generic_verify(param);
8780 else
8781 return devlink_param_driver_verify(param);
8782}
8783
8784static int __devlink_params_register(struct devlink *devlink,
c1e5786d 8785 unsigned int port_index,
39e6160e
VV
8786 struct list_head *param_list,
8787 const struct devlink_param *params,
c1e5786d
VV
8788 size_t params_count,
8789 enum devlink_command reg_cmd,
8790 enum devlink_command unreg_cmd)
eabaef18
MS
8791{
8792 const struct devlink_param *param = params;
8793 int i;
8794 int err;
8795
8796 mutex_lock(&devlink->lock);
8797 for (i = 0; i < params_count; i++, param++) {
39e6160e
VV
8798 err = devlink_param_verify(param);
8799 if (err)
eabaef18 8800 goto rollback;
39e6160e 8801
c1e5786d
VV
8802 err = devlink_param_register_one(devlink, port_index,
8803 param_list, param, reg_cmd);
eabaef18
MS
8804 if (err)
8805 goto rollback;
8806 }
8807
8808 mutex_unlock(&devlink->lock);
8809 return 0;
8810
8811rollback:
8812 if (!i)
8813 goto unlock;
8814 for (param--; i > 0; i--, param--)
c1e5786d
VV
8815 devlink_param_unregister_one(devlink, port_index, param_list,
8816 param, unreg_cmd);
eabaef18
MS
8817unlock:
8818 mutex_unlock(&devlink->lock);
8819 return err;
8820}
39e6160e
VV
8821
8822static void __devlink_params_unregister(struct devlink *devlink,
c1e5786d 8823 unsigned int port_index,
39e6160e
VV
8824 struct list_head *param_list,
8825 const struct devlink_param *params,
c1e5786d
VV
8826 size_t params_count,
8827 enum devlink_command cmd)
39e6160e
VV
8828{
8829 const struct devlink_param *param = params;
8830 int i;
8831
8832 mutex_lock(&devlink->lock);
8833 for (i = 0; i < params_count; i++, param++)
c1e5786d
VV
8834 devlink_param_unregister_one(devlink, 0, param_list, param,
8835 cmd);
39e6160e
VV
8836 mutex_unlock(&devlink->lock);
8837}
8838
8839/**
8840 * devlink_params_register - register configuration parameters
8841 *
8842 * @devlink: devlink
8843 * @params: configuration parameters array
8844 * @params_count: number of parameters provided
8845 *
8846 * Register the configuration parameters supported by the driver.
8847 */
8848int devlink_params_register(struct devlink *devlink,
8849 const struct devlink_param *params,
8850 size_t params_count)
8851{
c1e5786d
VV
8852 return __devlink_params_register(devlink, 0, &devlink->param_list,
8853 params, params_count,
8854 DEVLINK_CMD_PARAM_NEW,
8855 DEVLINK_CMD_PARAM_DEL);
39e6160e 8856}
eabaef18
MS
8857EXPORT_SYMBOL_GPL(devlink_params_register);
8858
8859/**
8860 * devlink_params_unregister - unregister configuration parameters
8861 * @devlink: devlink
8862 * @params: configuration parameters to unregister
8863 * @params_count: number of parameters provided
8864 */
8865void devlink_params_unregister(struct devlink *devlink,
8866 const struct devlink_param *params,
8867 size_t params_count)
8868{
c1e5786d
VV
8869 return __devlink_params_unregister(devlink, 0, &devlink->param_list,
8870 params, params_count,
8871 DEVLINK_CMD_PARAM_DEL);
eabaef18
MS
8872}
8873EXPORT_SYMBOL_GPL(devlink_params_unregister);
8874
7c62cfb8
JP
8875/**
8876 * devlink_params_publish - publish configuration parameters
8877 *
8878 * @devlink: devlink
8879 *
8880 * Publish previously registered configuration parameters.
8881 */
8882void devlink_params_publish(struct devlink *devlink)
8883{
8884 struct devlink_param_item *param_item;
8885
8886 list_for_each_entry(param_item, &devlink->param_list, list) {
8887 if (param_item->published)
8888 continue;
8889 param_item->published = true;
8890 devlink_param_notify(devlink, 0, param_item,
8891 DEVLINK_CMD_PARAM_NEW);
8892 }
8893}
8894EXPORT_SYMBOL_GPL(devlink_params_publish);
8895
8896/**
8897 * devlink_params_unpublish - unpublish configuration parameters
8898 *
8899 * @devlink: devlink
8900 *
8901 * Unpublish previously registered configuration parameters.
8902 */
8903void devlink_params_unpublish(struct devlink *devlink)
8904{
8905 struct devlink_param_item *param_item;
8906
8907 list_for_each_entry(param_item, &devlink->param_list, list) {
8908 if (!param_item->published)
8909 continue;
8910 param_item->published = false;
8911 devlink_param_notify(devlink, 0, param_item,
8912 DEVLINK_CMD_PARAM_DEL);
8913 }
8914}
8915EXPORT_SYMBOL_GPL(devlink_params_unpublish);
8916
39e6160e
VV
8917/**
8918 * devlink_port_params_register - register port configuration parameters
8919 *
8920 * @devlink_port: devlink port
8921 * @params: configuration parameters array
8922 * @params_count: number of parameters provided
8923 *
8924 * Register the configuration parameters supported by the port.
8925 */
8926int devlink_port_params_register(struct devlink_port *devlink_port,
8927 const struct devlink_param *params,
8928 size_t params_count)
8929{
8930 return __devlink_params_register(devlink_port->devlink,
c1e5786d 8931 devlink_port->index,
39e6160e 8932 &devlink_port->param_list, params,
c1e5786d
VV
8933 params_count,
8934 DEVLINK_CMD_PORT_PARAM_NEW,
8935 DEVLINK_CMD_PORT_PARAM_DEL);
39e6160e
VV
8936}
8937EXPORT_SYMBOL_GPL(devlink_port_params_register);
8938
8939/**
8940 * devlink_port_params_unregister - unregister port configuration
8941 * parameters
8942 *
8943 * @devlink_port: devlink port
8944 * @params: configuration parameters array
8945 * @params_count: number of parameters provided
8946 */
8947void devlink_port_params_unregister(struct devlink_port *devlink_port,
8948 const struct devlink_param *params,
8949 size_t params_count)
8950{
8951 return __devlink_params_unregister(devlink_port->devlink,
c1e5786d 8952 devlink_port->index,
39e6160e 8953 &devlink_port->param_list,
c1e5786d
VV
8954 params, params_count,
8955 DEVLINK_CMD_PORT_PARAM_DEL);
39e6160e
VV
8956}
8957EXPORT_SYMBOL_GPL(devlink_port_params_unregister);
8958
ffd19b9a
VV
8959static int
8960__devlink_param_driverinit_value_get(struct list_head *param_list, u32 param_id,
8961 union devlink_param_value *init_val)
ec01aeb1
MS
8962{
8963 struct devlink_param_item *param_item;
8964
ffd19b9a 8965 param_item = devlink_param_find_by_id(param_list, param_id);
ec01aeb1
MS
8966 if (!param_item)
8967 return -EINVAL;
8968
8969 if (!param_item->driverinit_value_valid ||
8970 !devlink_param_cmode_is_supported(param_item->param,
8971 DEVLINK_PARAM_CMODE_DRIVERINIT))
8972 return -EOPNOTSUPP;
8973
1276534c
MS
8974 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
8975 strcpy(init_val->vstr, param_item->driverinit_value.vstr);
8976 else
8977 *init_val = param_item->driverinit_value;
ec01aeb1
MS
8978
8979 return 0;
8980}
ffd19b9a 8981
5473a7bd
VV
8982static int
8983__devlink_param_driverinit_value_set(struct devlink *devlink,
c1e5786d 8984 unsigned int port_index,
5473a7bd
VV
8985 struct list_head *param_list, u32 param_id,
8986 union devlink_param_value init_val,
8987 enum devlink_command cmd)
8988{
8989 struct devlink_param_item *param_item;
8990
8991 param_item = devlink_param_find_by_id(param_list, param_id);
8992 if (!param_item)
8993 return -EINVAL;
8994
8995 if (!devlink_param_cmode_is_supported(param_item->param,
8996 DEVLINK_PARAM_CMODE_DRIVERINIT))
8997 return -EOPNOTSUPP;
8998
8999 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
9000 strcpy(param_item->driverinit_value.vstr, init_val.vstr);
9001 else
9002 param_item->driverinit_value = init_val;
9003 param_item->driverinit_value_valid = true;
9004
c1e5786d 9005 devlink_param_notify(devlink, port_index, param_item, cmd);
5473a7bd
VV
9006 return 0;
9007}
9008
ffd19b9a
VV
9009/**
9010 * devlink_param_driverinit_value_get - get configuration parameter
9011 * value for driver initializing
9012 *
9013 * @devlink: devlink
9014 * @param_id: parameter ID
9015 * @init_val: value of parameter in driverinit configuration mode
9016 *
9017 * This function should be used by the driver to get driverinit
9018 * configuration for initialization after reload command.
9019 */
9020int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
9021 union devlink_param_value *init_val)
9022{
69d56e0e 9023 if (!devlink_reload_supported(devlink->ops))
ffd19b9a
VV
9024 return -EOPNOTSUPP;
9025
9026 return __devlink_param_driverinit_value_get(&devlink->param_list,
9027 param_id, init_val);
9028}
ec01aeb1
MS
9029EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_get);
9030
9031/**
9032 * devlink_param_driverinit_value_set - set value of configuration
9033 * parameter for driverinit
9034 * configuration mode
9035 *
9036 * @devlink: devlink
9037 * @param_id: parameter ID
9038 * @init_val: value of parameter to set for driverinit configuration mode
9039 *
9040 * This function should be used by the driver to set driverinit
9041 * configuration mode default value.
9042 */
9043int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
9044 union devlink_param_value init_val)
9045{
c1e5786d 9046 return __devlink_param_driverinit_value_set(devlink, 0,
5473a7bd
VV
9047 &devlink->param_list,
9048 param_id, init_val,
9049 DEVLINK_CMD_PARAM_NEW);
ec01aeb1
MS
9050}
9051EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_set);
9052
ffd19b9a
VV
9053/**
9054 * devlink_port_param_driverinit_value_get - get configuration parameter
9055 * value for driver initializing
9056 *
9057 * @devlink_port: devlink_port
9058 * @param_id: parameter ID
9059 * @init_val: value of parameter in driverinit configuration mode
9060 *
9061 * This function should be used by the driver to get driverinit
9062 * configuration for initialization after reload command.
9063 */
9064int devlink_port_param_driverinit_value_get(struct devlink_port *devlink_port,
9065 u32 param_id,
9066 union devlink_param_value *init_val)
9067{
9068 struct devlink *devlink = devlink_port->devlink;
9069
69d56e0e 9070 if (!devlink_reload_supported(devlink->ops))
ffd19b9a
VV
9071 return -EOPNOTSUPP;
9072
9073 return __devlink_param_driverinit_value_get(&devlink_port->param_list,
9074 param_id, init_val);
9075}
9076EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_get);
9077
5473a7bd
VV
9078/**
9079 * devlink_port_param_driverinit_value_set - set value of configuration
9080 * parameter for driverinit
9081 * configuration mode
9082 *
9083 * @devlink_port: devlink_port
9084 * @param_id: parameter ID
9085 * @init_val: value of parameter to set for driverinit configuration mode
9086 *
9087 * This function should be used by the driver to set driverinit
9088 * configuration mode default value.
9089 */
9090int devlink_port_param_driverinit_value_set(struct devlink_port *devlink_port,
9091 u32 param_id,
9092 union devlink_param_value init_val)
9093{
9094 return __devlink_param_driverinit_value_set(devlink_port->devlink,
c1e5786d 9095 devlink_port->index,
5473a7bd 9096 &devlink_port->param_list,
c1e5786d
VV
9097 param_id, init_val,
9098 DEVLINK_CMD_PORT_PARAM_NEW);
5473a7bd
VV
9099}
9100EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_set);
9101
ea601e17
MS
9102/**
9103 * devlink_param_value_changed - notify devlink on a parameter's value
9104 * change. Should be called by the driver
9105 * right after the change.
9106 *
9107 * @devlink: devlink
9108 * @param_id: parameter ID
9109 *
9110 * This function should be used by the driver to notify devlink on value
9111 * change, excluding driverinit configuration mode.
9112 * For driverinit configuration mode driver should use the function
ea601e17
MS
9113 */
9114void devlink_param_value_changed(struct devlink *devlink, u32 param_id)
9115{
9116 struct devlink_param_item *param_item;
9117
9118 param_item = devlink_param_find_by_id(&devlink->param_list, param_id);
9119 WARN_ON(!param_item);
9120
c1e5786d 9121 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
ea601e17
MS
9122}
9123EXPORT_SYMBOL_GPL(devlink_param_value_changed);
9124
c1e5786d
VV
9125/**
9126 * devlink_port_param_value_changed - notify devlink on a parameter's value
9127 * change. Should be called by the driver
9128 * right after the change.
9129 *
9130 * @devlink_port: devlink_port
9131 * @param_id: parameter ID
9132 *
9133 * This function should be used by the driver to notify devlink on value
9134 * change, excluding driverinit configuration mode.
9135 * For driverinit configuration mode driver should use the function
9136 * devlink_port_param_driverinit_value_set() instead.
9137 */
9138void devlink_port_param_value_changed(struct devlink_port *devlink_port,
9139 u32 param_id)
9140{
9141 struct devlink_param_item *param_item;
9142
9143 param_item = devlink_param_find_by_id(&devlink_port->param_list,
9144 param_id);
9145 WARN_ON(!param_item);
9146
9147 devlink_param_notify(devlink_port->devlink, devlink_port->index,
9148 param_item, DEVLINK_CMD_PORT_PARAM_NEW);
9149}
9150EXPORT_SYMBOL_GPL(devlink_port_param_value_changed);
9151
bde74ad1
MS
9152/**
9153 * devlink_param_value_str_fill - Safely fill-up the string preventing
9154 * from overflow of the preallocated buffer
9155 *
9156 * @dst_val: destination devlink_param_value
9157 * @src: source buffer
9158 */
9159void devlink_param_value_str_fill(union devlink_param_value *dst_val,
9160 const char *src)
9161{
9162 size_t len;
9163
9164 len = strlcpy(dst_val->vstr, src, __DEVLINK_PARAM_MAX_STRING_VALUE);
9165 WARN_ON(len >= __DEVLINK_PARAM_MAX_STRING_VALUE);
9166}
9167EXPORT_SYMBOL_GPL(devlink_param_value_str_fill);
9168
b16ebe92
AV
9169/**
9170 * devlink_region_create - create a new address region
9171 *
9172 * @devlink: devlink
e8937681 9173 * @ops: region operations and name
b16ebe92
AV
9174 * @region_max_snapshots: Maximum supported number of snapshots for region
9175 * @region_size: size of region
9176 */
e8937681
JK
9177struct devlink_region *
9178devlink_region_create(struct devlink *devlink,
9179 const struct devlink_region_ops *ops,
9180 u32 region_max_snapshots, u64 region_size)
b16ebe92
AV
9181{
9182 struct devlink_region *region;
9183 int err = 0;
9184
a0a09f6b
JK
9185 if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
9186 return ERR_PTR(-EINVAL);
9187
b16ebe92
AV
9188 mutex_lock(&devlink->lock);
9189
e8937681 9190 if (devlink_region_get_by_name(devlink, ops->name)) {
b16ebe92
AV
9191 err = -EEXIST;
9192 goto unlock;
9193 }
9194
9195 region = kzalloc(sizeof(*region), GFP_KERNEL);
9196 if (!region) {
9197 err = -ENOMEM;
9198 goto unlock;
9199 }
9200
9201 region->devlink = devlink;
9202 region->max_snapshots = region_max_snapshots;
e8937681 9203 region->ops = ops;
b16ebe92
AV
9204 region->size = region_size;
9205 INIT_LIST_HEAD(&region->snapshot_list);
9206 list_add_tail(&region->list, &devlink->region_list);
866319bb 9207 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
b16ebe92
AV
9208
9209 mutex_unlock(&devlink->lock);
9210 return region;
9211
9212unlock:
9213 mutex_unlock(&devlink->lock);
9214 return ERR_PTR(err);
9215}
9216EXPORT_SYMBOL_GPL(devlink_region_create);
9217
544e7c33
AL
9218/**
9219 * devlink_port_region_create - create a new address region for a port
9220 *
9221 * @port: devlink port
9222 * @ops: region operations and name
9223 * @region_max_snapshots: Maximum supported number of snapshots for region
9224 * @region_size: size of region
9225 */
9226struct devlink_region *
9227devlink_port_region_create(struct devlink_port *port,
9228 const struct devlink_port_region_ops *ops,
9229 u32 region_max_snapshots, u64 region_size)
9230{
9231 struct devlink *devlink = port->devlink;
9232 struct devlink_region *region;
9233 int err = 0;
9234
9235 if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
9236 return ERR_PTR(-EINVAL);
9237
9238 mutex_lock(&devlink->lock);
9239
9240 if (devlink_port_region_get_by_name(port, ops->name)) {
9241 err = -EEXIST;
9242 goto unlock;
9243 }
9244
9245 region = kzalloc(sizeof(*region), GFP_KERNEL);
9246 if (!region) {
9247 err = -ENOMEM;
9248 goto unlock;
9249 }
9250
9251 region->devlink = devlink;
9252 region->port = port;
9253 region->max_snapshots = region_max_snapshots;
9254 region->port_ops = ops;
9255 region->size = region_size;
9256 INIT_LIST_HEAD(&region->snapshot_list);
9257 list_add_tail(&region->list, &port->region_list);
9258 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
9259
9260 mutex_unlock(&devlink->lock);
9261 return region;
9262
9263unlock:
9264 mutex_unlock(&devlink->lock);
9265 return ERR_PTR(err);
9266}
9267EXPORT_SYMBOL_GPL(devlink_port_region_create);
9268
b16ebe92
AV
9269/**
9270 * devlink_region_destroy - destroy address region
9271 *
9272 * @region: devlink region to destroy
9273 */
9274void devlink_region_destroy(struct devlink_region *region)
9275{
9276 struct devlink *devlink = region->devlink;
d7e52722 9277 struct devlink_snapshot *snapshot, *ts;
b16ebe92
AV
9278
9279 mutex_lock(&devlink->lock);
d7e52722
AV
9280
9281 /* Free all snapshots of region */
9282 list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list)
92b49822 9283 devlink_region_snapshot_del(region, snapshot);
d7e52722 9284
b16ebe92 9285 list_del(&region->list);
866319bb
AV
9286
9287 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
b16ebe92
AV
9288 mutex_unlock(&devlink->lock);
9289 kfree(region);
9290}
9291EXPORT_SYMBOL_GPL(devlink_region_destroy);
9292
ccadfa44 9293/**
b0efcae5 9294 * devlink_region_snapshot_id_get - get snapshot ID
ccadfa44
AV
9295 *
9296 * This callback should be called when adding a new snapshot,
9297 * Driver should use the same id for multiple snapshots taken
9298 * on multiple regions at the same time/by the same trigger.
9299 *
12102436
JK
9300 * The caller of this function must use devlink_region_snapshot_id_put
9301 * when finished creating regions using this id.
9302 *
7ef19d3b
JK
9303 * Returns zero on success, or a negative error code on failure.
9304 *
ccadfa44 9305 * @devlink: devlink
7ef19d3b 9306 * @id: storage to return id
ccadfa44 9307 */
7ef19d3b 9308int devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
ccadfa44 9309{
7ef19d3b 9310 int err;
ccadfa44
AV
9311
9312 mutex_lock(&devlink->lock);
7ef19d3b 9313 err = __devlink_region_snapshot_id_get(devlink, id);
ccadfa44
AV
9314 mutex_unlock(&devlink->lock);
9315
7ef19d3b 9316 return err;
ccadfa44 9317}
b0efcae5 9318EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get);
ccadfa44 9319
12102436
JK
9320/**
9321 * devlink_region_snapshot_id_put - put snapshot ID reference
9322 *
9323 * This should be called by a driver after finishing creating snapshots
9324 * with an id. Doing so ensures that the ID can later be released in the
9325 * event that all snapshots using it have been destroyed.
9326 *
9327 * @devlink: devlink
9328 * @id: id to release reference on
9329 */
9330void devlink_region_snapshot_id_put(struct devlink *devlink, u32 id)
9331{
9332 mutex_lock(&devlink->lock);
9333 __devlink_snapshot_id_decrement(devlink, id);
9334 mutex_unlock(&devlink->lock);
9335}
9336EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_put);
9337
d7e52722
AV
9338/**
9339 * devlink_region_snapshot_create - create a new snapshot
9340 * This will add a new snapshot of a region. The snapshot
9341 * will be stored on the region struct and can be accessed
6d82f67e 9342 * from devlink. This is useful for future analyses of snapshots.
d7e52722
AV
9343 * Multiple snapshots can be created on a region.
9344 * The @snapshot_id should be obtained using the getter function.
9345 *
eeaadd82 9346 * @region: devlink region of the snapshot
d7e52722
AV
9347 * @data: snapshot data
9348 * @snapshot_id: snapshot id to be created
d7e52722 9349 */
3a5e5234 9350int devlink_region_snapshot_create(struct devlink_region *region,
a0a09f6b 9351 u8 *data, u32 snapshot_id)
d7e52722
AV
9352{
9353 struct devlink *devlink = region->devlink;
d7e52722
AV
9354 int err;
9355
9356 mutex_lock(&devlink->lock);
cf80faee 9357 err = __devlink_region_snapshot_create(region, data, snapshot_id);
d7e52722 9358 mutex_unlock(&devlink->lock);
d7e52722 9359
d7e52722
AV
9360 return err;
9361}
9362EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);
9363
0f420b6c
IS
9364#define DEVLINK_TRAP(_id, _type) \
9365 { \
9366 .type = DEVLINK_TRAP_TYPE_##_type, \
9367 .id = DEVLINK_TRAP_GENERIC_ID_##_id, \
9368 .name = DEVLINK_TRAP_GENERIC_NAME_##_id, \
9369 }
9370
9371static const struct devlink_trap devlink_trap_generic[] = {
391203ab
IS
9372 DEVLINK_TRAP(SMAC_MC, DROP),
9373 DEVLINK_TRAP(VLAN_TAG_MISMATCH, DROP),
9374 DEVLINK_TRAP(INGRESS_VLAN_FILTER, DROP),
9375 DEVLINK_TRAP(INGRESS_STP_FILTER, DROP),
9376 DEVLINK_TRAP(EMPTY_TX_LIST, DROP),
9377 DEVLINK_TRAP(PORT_LOOPBACK_FILTER, DROP),
9378 DEVLINK_TRAP(BLACKHOLE_ROUTE, DROP),
9379 DEVLINK_TRAP(TTL_ERROR, EXCEPTION),
9380 DEVLINK_TRAP(TAIL_DROP, DROP),
6896cc4d
AC
9381 DEVLINK_TRAP(NON_IP_PACKET, DROP),
9382 DEVLINK_TRAP(UC_DIP_MC_DMAC, DROP),
9383 DEVLINK_TRAP(DIP_LB, DROP),
9384 DEVLINK_TRAP(SIP_MC, DROP),
9385 DEVLINK_TRAP(SIP_LB, DROP),
9386 DEVLINK_TRAP(CORRUPTED_IP_HDR, DROP),
9387 DEVLINK_TRAP(IPV4_SIP_BC, DROP),
9388 DEVLINK_TRAP(IPV6_MC_DIP_RESERVED_SCOPE, DROP),
9389 DEVLINK_TRAP(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE, DROP),
3b063ae5
AC
9390 DEVLINK_TRAP(MTU_ERROR, EXCEPTION),
9391 DEVLINK_TRAP(UNRESOLVED_NEIGH, EXCEPTION),
9392 DEVLINK_TRAP(RPF, EXCEPTION),
9393 DEVLINK_TRAP(REJECT_ROUTE, EXCEPTION),
9394 DEVLINK_TRAP(IPV4_LPM_UNICAST_MISS, EXCEPTION),
9395 DEVLINK_TRAP(IPV6_LPM_UNICAST_MISS, EXCEPTION),
95f0ead8 9396 DEVLINK_TRAP(NON_ROUTABLE, DROP),
13c056ec 9397 DEVLINK_TRAP(DECAP_ERROR, EXCEPTION),
c3cae491 9398 DEVLINK_TRAP(OVERLAY_SMAC_MC, DROP),
ecd942a0
JP
9399 DEVLINK_TRAP(INGRESS_FLOW_ACTION_DROP, DROP),
9400 DEVLINK_TRAP(EGRESS_FLOW_ACTION_DROP, DROP),
515eac67
IS
9401 DEVLINK_TRAP(STP, CONTROL),
9402 DEVLINK_TRAP(LACP, CONTROL),
9403 DEVLINK_TRAP(LLDP, CONTROL),
9404 DEVLINK_TRAP(IGMP_QUERY, CONTROL),
9405 DEVLINK_TRAP(IGMP_V1_REPORT, CONTROL),
9406 DEVLINK_TRAP(IGMP_V2_REPORT, CONTROL),
9407 DEVLINK_TRAP(IGMP_V3_REPORT, CONTROL),
9408 DEVLINK_TRAP(IGMP_V2_LEAVE, CONTROL),
9409 DEVLINK_TRAP(MLD_QUERY, CONTROL),
9410 DEVLINK_TRAP(MLD_V1_REPORT, CONTROL),
9411 DEVLINK_TRAP(MLD_V2_REPORT, CONTROL),
9412 DEVLINK_TRAP(MLD_V1_DONE, CONTROL),
d77cfd16
IS
9413 DEVLINK_TRAP(IPV4_DHCP, CONTROL),
9414 DEVLINK_TRAP(IPV6_DHCP, CONTROL),
9415 DEVLINK_TRAP(ARP_REQUEST, CONTROL),
9416 DEVLINK_TRAP(ARP_RESPONSE, CONTROL),
9417 DEVLINK_TRAP(ARP_OVERLAY, CONTROL),
9418 DEVLINK_TRAP(IPV6_NEIGH_SOLICIT, CONTROL),
9419 DEVLINK_TRAP(IPV6_NEIGH_ADVERT, CONTROL),
9420 DEVLINK_TRAP(IPV4_BFD, CONTROL),
9421 DEVLINK_TRAP(IPV6_BFD, CONTROL),
9422 DEVLINK_TRAP(IPV4_OSPF, CONTROL),
9423 DEVLINK_TRAP(IPV6_OSPF, CONTROL),
9424 DEVLINK_TRAP(IPV4_BGP, CONTROL),
9425 DEVLINK_TRAP(IPV6_BGP, CONTROL),
9426 DEVLINK_TRAP(IPV4_VRRP, CONTROL),
9427 DEVLINK_TRAP(IPV6_VRRP, CONTROL),
9428 DEVLINK_TRAP(IPV4_PIM, CONTROL),
9429 DEVLINK_TRAP(IPV6_PIM, CONTROL),
9430 DEVLINK_TRAP(UC_LB, CONTROL),
9431 DEVLINK_TRAP(LOCAL_ROUTE, CONTROL),
9432 DEVLINK_TRAP(EXTERNAL_ROUTE, CONTROL),
9433 DEVLINK_TRAP(IPV6_UC_DIP_LINK_LOCAL_SCOPE, CONTROL),
9434 DEVLINK_TRAP(IPV6_DIP_ALL_NODES, CONTROL),
9435 DEVLINK_TRAP(IPV6_DIP_ALL_ROUTERS, CONTROL),
9436 DEVLINK_TRAP(IPV6_ROUTER_SOLICIT, CONTROL),
9437 DEVLINK_TRAP(IPV6_ROUTER_ADVERT, CONTROL),
9438 DEVLINK_TRAP(IPV6_REDIRECT, CONTROL),
9439 DEVLINK_TRAP(IPV4_ROUTER_ALERT, CONTROL),
9440 DEVLINK_TRAP(IPV6_ROUTER_ALERT, CONTROL),
9441 DEVLINK_TRAP(PTP_EVENT, CONTROL),
9442 DEVLINK_TRAP(PTP_GENERAL, CONTROL),
5eb18a2b
IS
9443 DEVLINK_TRAP(FLOW_ACTION_SAMPLE, CONTROL),
9444 DEVLINK_TRAP(FLOW_ACTION_TRAP, CONTROL),
08e335f6 9445 DEVLINK_TRAP(EARLY_DROP, DROP),
10c24eb2
IC
9446 DEVLINK_TRAP(VXLAN_PARSING, DROP),
9447 DEVLINK_TRAP(LLC_SNAP_PARSING, DROP),
9448 DEVLINK_TRAP(VLAN_PARSING, DROP),
9449 DEVLINK_TRAP(PPPOE_PPP_PARSING, DROP),
9450 DEVLINK_TRAP(MPLS_PARSING, DROP),
9451 DEVLINK_TRAP(ARP_PARSING, DROP),
9452 DEVLINK_TRAP(IP_1_PARSING, DROP),
9453 DEVLINK_TRAP(IP_N_PARSING, DROP),
9454 DEVLINK_TRAP(GRE_PARSING, DROP),
9455 DEVLINK_TRAP(UDP_PARSING, DROP),
9456 DEVLINK_TRAP(TCP_PARSING, DROP),
9457 DEVLINK_TRAP(IPSEC_PARSING, DROP),
9458 DEVLINK_TRAP(SCTP_PARSING, DROP),
9459 DEVLINK_TRAP(DCCP_PARSING, DROP),
9460 DEVLINK_TRAP(GTP_PARSING, DROP),
9461 DEVLINK_TRAP(ESP_PARSING, DROP),
0f420b6c
IS
9462};
9463
9464#define DEVLINK_TRAP_GROUP(_id) \
9465 { \
9466 .id = DEVLINK_TRAP_GROUP_GENERIC_ID_##_id, \
9467 .name = DEVLINK_TRAP_GROUP_GENERIC_NAME_##_id, \
9468 }
9469
9470static const struct devlink_trap_group devlink_trap_group_generic[] = {
391203ab
IS
9471 DEVLINK_TRAP_GROUP(L2_DROPS),
9472 DEVLINK_TRAP_GROUP(L3_DROPS),
678eb199 9473 DEVLINK_TRAP_GROUP(L3_EXCEPTIONS),
391203ab 9474 DEVLINK_TRAP_GROUP(BUFFER_DROPS),
13c056ec 9475 DEVLINK_TRAP_GROUP(TUNNEL_DROPS),
ecd942a0 9476 DEVLINK_TRAP_GROUP(ACL_DROPS),
515eac67
IS
9477 DEVLINK_TRAP_GROUP(STP),
9478 DEVLINK_TRAP_GROUP(LACP),
9479 DEVLINK_TRAP_GROUP(LLDP),
9480 DEVLINK_TRAP_GROUP(MC_SNOOPING),
d77cfd16
IS
9481 DEVLINK_TRAP_GROUP(DHCP),
9482 DEVLINK_TRAP_GROUP(NEIGH_DISCOVERY),
9483 DEVLINK_TRAP_GROUP(BFD),
9484 DEVLINK_TRAP_GROUP(OSPF),
9485 DEVLINK_TRAP_GROUP(BGP),
9486 DEVLINK_TRAP_GROUP(VRRP),
9487 DEVLINK_TRAP_GROUP(PIM),
9488 DEVLINK_TRAP_GROUP(UC_LB),
9489 DEVLINK_TRAP_GROUP(LOCAL_DELIVERY),
ec4f5b36 9490 DEVLINK_TRAP_GROUP(EXTERNAL_DELIVERY),
d77cfd16
IS
9491 DEVLINK_TRAP_GROUP(IPV6),
9492 DEVLINK_TRAP_GROUP(PTP_EVENT),
9493 DEVLINK_TRAP_GROUP(PTP_GENERAL),
5eb18a2b
IS
9494 DEVLINK_TRAP_GROUP(ACL_SAMPLE),
9495 DEVLINK_TRAP_GROUP(ACL_TRAP),
10c24eb2 9496 DEVLINK_TRAP_GROUP(PARSER_ERROR_DROPS),
0f420b6c
IS
9497};
9498
9499static int devlink_trap_generic_verify(const struct devlink_trap *trap)
9500{
9501 if (trap->id > DEVLINK_TRAP_GENERIC_ID_MAX)
9502 return -EINVAL;
9503
9504 if (strcmp(trap->name, devlink_trap_generic[trap->id].name))
9505 return -EINVAL;
9506
9507 if (trap->type != devlink_trap_generic[trap->id].type)
9508 return -EINVAL;
9509
9510 return 0;
9511}
9512
9513static int devlink_trap_driver_verify(const struct devlink_trap *trap)
9514{
9515 int i;
9516
9517 if (trap->id <= DEVLINK_TRAP_GENERIC_ID_MAX)
9518 return -EINVAL;
9519
9520 for (i = 0; i < ARRAY_SIZE(devlink_trap_generic); i++) {
9521 if (!strcmp(trap->name, devlink_trap_generic[i].name))
9522 return -EEXIST;
9523 }
9524
9525 return 0;
9526}
9527
9528static int devlink_trap_verify(const struct devlink_trap *trap)
9529{
107f1678 9530 if (!trap || !trap->name)
0f420b6c
IS
9531 return -EINVAL;
9532
9533 if (trap->generic)
9534 return devlink_trap_generic_verify(trap);
9535 else
9536 return devlink_trap_driver_verify(trap);
9537}
9538
9539static int
9540devlink_trap_group_generic_verify(const struct devlink_trap_group *group)
9541{
9542 if (group->id > DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
9543 return -EINVAL;
9544
9545 if (strcmp(group->name, devlink_trap_group_generic[group->id].name))
9546 return -EINVAL;
9547
9548 return 0;
9549}
9550
9551static int
9552devlink_trap_group_driver_verify(const struct devlink_trap_group *group)
9553{
9554 int i;
9555
9556 if (group->id <= DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
9557 return -EINVAL;
9558
9559 for (i = 0; i < ARRAY_SIZE(devlink_trap_group_generic); i++) {
9560 if (!strcmp(group->name, devlink_trap_group_generic[i].name))
9561 return -EEXIST;
9562 }
9563
9564 return 0;
9565}
9566
9567static int devlink_trap_group_verify(const struct devlink_trap_group *group)
9568{
9569 if (group->generic)
9570 return devlink_trap_group_generic_verify(group);
9571 else
9572 return devlink_trap_group_driver_verify(group);
9573}
9574
9575static void
9576devlink_trap_group_notify(struct devlink *devlink,
9577 const struct devlink_trap_group_item *group_item,
9578 enum devlink_command cmd)
9579{
9580 struct sk_buff *msg;
9581 int err;
9582
9583 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_GROUP_NEW &&
9584 cmd != DEVLINK_CMD_TRAP_GROUP_DEL);
9585
9586 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
9587 if (!msg)
9588 return;
9589
9590 err = devlink_nl_trap_group_fill(msg, devlink, group_item, cmd, 0, 0,
9591 0);
9592 if (err) {
9593 nlmsg_free(msg);
9594 return;
9595 }
9596
9597 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
9598 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
9599}
9600
0f420b6c
IS
9601static int
9602devlink_trap_item_group_link(struct devlink *devlink,
9603 struct devlink_trap_item *trap_item)
9604{
107f1678 9605 u16 group_id = trap_item->trap->init_group_id;
0f420b6c
IS
9606 struct devlink_trap_group_item *group_item;
9607
107f1678 9608 group_item = devlink_trap_group_item_lookup_by_id(devlink, group_id);
a09b37fc
IS
9609 if (WARN_ON_ONCE(!group_item))
9610 return -EINVAL;
0f420b6c
IS
9611
9612 trap_item->group_item = group_item;
9613
9614 return 0;
9615}
9616
0f420b6c
IS
9617static void devlink_trap_notify(struct devlink *devlink,
9618 const struct devlink_trap_item *trap_item,
9619 enum devlink_command cmd)
9620{
9621 struct sk_buff *msg;
9622 int err;
9623
9624 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_NEW &&
9625 cmd != DEVLINK_CMD_TRAP_DEL);
9626
9627 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
9628 if (!msg)
9629 return;
9630
9631 err = devlink_nl_trap_fill(msg, devlink, trap_item, cmd, 0, 0, 0);
9632 if (err) {
9633 nlmsg_free(msg);
9634 return;
9635 }
9636
9637 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
9638 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
9639}
9640
9641static int
9642devlink_trap_register(struct devlink *devlink,
9643 const struct devlink_trap *trap, void *priv)
9644{
9645 struct devlink_trap_item *trap_item;
9646 int err;
9647
9648 if (devlink_trap_item_lookup(devlink, trap->name))
9649 return -EEXIST;
9650
9651 trap_item = kzalloc(sizeof(*trap_item), GFP_KERNEL);
9652 if (!trap_item)
9653 return -ENOMEM;
9654
9655 trap_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
9656 if (!trap_item->stats) {
9657 err = -ENOMEM;
9658 goto err_stats_alloc;
9659 }
9660
9661 trap_item->trap = trap;
9662 trap_item->action = trap->init_action;
9663 trap_item->priv = priv;
9664
9665 err = devlink_trap_item_group_link(devlink, trap_item);
9666 if (err)
9667 goto err_group_link;
9668
9669 err = devlink->ops->trap_init(devlink, trap, trap_item);
9670 if (err)
9671 goto err_trap_init;
9672
9673 list_add_tail(&trap_item->list, &devlink->trap_list);
9674 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW);
9675
9676 return 0;
9677
9678err_trap_init:
0f420b6c
IS
9679err_group_link:
9680 free_percpu(trap_item->stats);
9681err_stats_alloc:
9682 kfree(trap_item);
9683 return err;
9684}
9685
9686static void devlink_trap_unregister(struct devlink *devlink,
9687 const struct devlink_trap *trap)
9688{
9689 struct devlink_trap_item *trap_item;
9690
9691 trap_item = devlink_trap_item_lookup(devlink, trap->name);
9692 if (WARN_ON_ONCE(!trap_item))
9693 return;
9694
9695 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL);
9696 list_del(&trap_item->list);
9697 if (devlink->ops->trap_fini)
9698 devlink->ops->trap_fini(devlink, trap, trap_item);
0f420b6c
IS
9699 free_percpu(trap_item->stats);
9700 kfree(trap_item);
9701}
9702
9703static void devlink_trap_disable(struct devlink *devlink,
9704 const struct devlink_trap *trap)
9705{
9706 struct devlink_trap_item *trap_item;
9707
9708 trap_item = devlink_trap_item_lookup(devlink, trap->name);
9709 if (WARN_ON_ONCE(!trap_item))
9710 return;
9711
c88e11e0
IS
9712 devlink->ops->trap_action_set(devlink, trap, DEVLINK_TRAP_ACTION_DROP,
9713 NULL);
0f420b6c
IS
9714 trap_item->action = DEVLINK_TRAP_ACTION_DROP;
9715}
9716
9717/**
9718 * devlink_traps_register - Register packet traps with devlink.
9719 * @devlink: devlink.
9720 * @traps: Packet traps.
9721 * @traps_count: Count of provided packet traps.
9722 * @priv: Driver private information.
9723 *
9724 * Return: Non-zero value on failure.
9725 */
9726int devlink_traps_register(struct devlink *devlink,
9727 const struct devlink_trap *traps,
9728 size_t traps_count, void *priv)
9729{
9730 int i, err;
9731
9732 if (!devlink->ops->trap_init || !devlink->ops->trap_action_set)
9733 return -EINVAL;
9734
9735 mutex_lock(&devlink->lock);
9736 for (i = 0; i < traps_count; i++) {
9737 const struct devlink_trap *trap = &traps[i];
9738
9739 err = devlink_trap_verify(trap);
9740 if (err)
9741 goto err_trap_verify;
9742
9743 err = devlink_trap_register(devlink, trap, priv);
9744 if (err)
9745 goto err_trap_register;
9746 }
9747 mutex_unlock(&devlink->lock);
9748
9749 return 0;
9750
9751err_trap_register:
9752err_trap_verify:
9753 for (i--; i >= 0; i--)
9754 devlink_trap_unregister(devlink, &traps[i]);
9755 mutex_unlock(&devlink->lock);
9756 return err;
9757}
9758EXPORT_SYMBOL_GPL(devlink_traps_register);
9759
9760/**
9761 * devlink_traps_unregister - Unregister packet traps from devlink.
9762 * @devlink: devlink.
9763 * @traps: Packet traps.
9764 * @traps_count: Count of provided packet traps.
9765 */
9766void devlink_traps_unregister(struct devlink *devlink,
9767 const struct devlink_trap *traps,
9768 size_t traps_count)
9769{
9770 int i;
9771
9772 mutex_lock(&devlink->lock);
9773 /* Make sure we do not have any packets in-flight while unregistering
9774 * traps by disabling all of them and waiting for a grace period.
9775 */
9776 for (i = traps_count - 1; i >= 0; i--)
9777 devlink_trap_disable(devlink, &traps[i]);
9778 synchronize_rcu();
9779 for (i = traps_count - 1; i >= 0; i--)
9780 devlink_trap_unregister(devlink, &traps[i]);
9781 mutex_unlock(&devlink->lock);
9782}
9783EXPORT_SYMBOL_GPL(devlink_traps_unregister);
9784
9785static void
9786devlink_trap_stats_update(struct devlink_stats __percpu *trap_stats,
9787 size_t skb_len)
9788{
9789 struct devlink_stats *stats;
9790
9791 stats = this_cpu_ptr(trap_stats);
9792 u64_stats_update_begin(&stats->syncp);
9793 stats->rx_bytes += skb_len;
9794 stats->rx_packets++;
9795 u64_stats_update_end(&stats->syncp);
9796}
9797
5b88823b
IS
9798static void
9799devlink_trap_report_metadata_set(struct devlink_trap_metadata *metadata,
9800 const struct devlink_trap_item *trap_item,
9801 struct devlink_port *in_devlink_port,
9802 const struct flow_action_cookie *fa_cookie)
9803{
9804 metadata->trap_name = trap_item->trap->name;
9805 metadata->trap_group_name = trap_item->group_item->group->name;
9806 metadata->fa_cookie = fa_cookie;
93e15596 9807 metadata->trap_type = trap_item->trap->type;
5b88823b
IS
9808
9809 spin_lock(&in_devlink_port->type_lock);
9810 if (in_devlink_port->type == DEVLINK_PORT_TYPE_ETH)
9811 metadata->input_dev = in_devlink_port->type_dev;
9812 spin_unlock(&in_devlink_port->type_lock);
9813}
9814
0f420b6c
IS
9815/**
9816 * devlink_trap_report - Report trapped packet to drop monitor.
9817 * @devlink: devlink.
9818 * @skb: Trapped packet.
9819 * @trap_ctx: Trap context.
9820 * @in_devlink_port: Input devlink port.
5a2e106c 9821 * @fa_cookie: Flow action cookie. Could be NULL.
0f420b6c
IS
9822 */
9823void devlink_trap_report(struct devlink *devlink, struct sk_buff *skb,
5a2e106c
JP
9824 void *trap_ctx, struct devlink_port *in_devlink_port,
9825 const struct flow_action_cookie *fa_cookie)
9826
0f420b6c
IS
9827{
9828 struct devlink_trap_item *trap_item = trap_ctx;
0f420b6c
IS
9829
9830 devlink_trap_stats_update(trap_item->stats, skb->len);
9831 devlink_trap_stats_update(trap_item->group_item->stats, skb->len);
9832
5b88823b
IS
9833 if (trace_devlink_trap_report_enabled()) {
9834 struct devlink_trap_metadata metadata = {};
9835
9836 devlink_trap_report_metadata_set(&metadata, trap_item,
9837 in_devlink_port, fa_cookie);
9838 trace_devlink_trap_report(devlink, skb, &metadata);
9839 }
0f420b6c
IS
9840}
9841EXPORT_SYMBOL_GPL(devlink_trap_report);
9842
9843/**
9844 * devlink_trap_ctx_priv - Trap context to driver private information.
9845 * @trap_ctx: Trap context.
9846 *
9847 * Return: Driver private information passed during registration.
9848 */
9849void *devlink_trap_ctx_priv(void *trap_ctx)
9850{
9851 struct devlink_trap_item *trap_item = trap_ctx;
9852
9853 return trap_item->priv;
9854}
9855EXPORT_SYMBOL_GPL(devlink_trap_ctx_priv);
9856
f9f54392
IS
9857static int
9858devlink_trap_group_item_policer_link(struct devlink *devlink,
9859 struct devlink_trap_group_item *group_item)
9860{
9861 u32 policer_id = group_item->group->init_policer_id;
9862 struct devlink_trap_policer_item *policer_item;
9863
9864 if (policer_id == 0)
9865 return 0;
9866
9867 policer_item = devlink_trap_policer_item_lookup(devlink, policer_id);
9868 if (WARN_ON_ONCE(!policer_item))
9869 return -EINVAL;
9870
9871 group_item->policer_item = policer_item;
9872
9873 return 0;
9874}
9875
95ad9555
IS
9876static int
9877devlink_trap_group_register(struct devlink *devlink,
9878 const struct devlink_trap_group *group)
9879{
9880 struct devlink_trap_group_item *group_item;
9881 int err;
9882
9883 if (devlink_trap_group_item_lookup(devlink, group->name))
9884 return -EEXIST;
9885
9886 group_item = kzalloc(sizeof(*group_item), GFP_KERNEL);
9887 if (!group_item)
9888 return -ENOMEM;
9889
9890 group_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
9891 if (!group_item->stats) {
9892 err = -ENOMEM;
9893 goto err_stats_alloc;
9894 }
9895
9896 group_item->group = group;
95ad9555 9897
f9f54392
IS
9898 err = devlink_trap_group_item_policer_link(devlink, group_item);
9899 if (err)
9900 goto err_policer_link;
9901
95ad9555
IS
9902 if (devlink->ops->trap_group_init) {
9903 err = devlink->ops->trap_group_init(devlink, group);
9904 if (err)
9905 goto err_group_init;
9906 }
9907
9908 list_add_tail(&group_item->list, &devlink->trap_group_list);
9909 devlink_trap_group_notify(devlink, group_item,
9910 DEVLINK_CMD_TRAP_GROUP_NEW);
9911
9912 return 0;
9913
9914err_group_init:
f9f54392 9915err_policer_link:
95ad9555
IS
9916 free_percpu(group_item->stats);
9917err_stats_alloc:
9918 kfree(group_item);
9919 return err;
9920}
9921
9922static void
9923devlink_trap_group_unregister(struct devlink *devlink,
9924 const struct devlink_trap_group *group)
9925{
9926 struct devlink_trap_group_item *group_item;
9927
9928 group_item = devlink_trap_group_item_lookup(devlink, group->name);
9929 if (WARN_ON_ONCE(!group_item))
9930 return;
9931
9932 devlink_trap_group_notify(devlink, group_item,
9933 DEVLINK_CMD_TRAP_GROUP_DEL);
9934 list_del(&group_item->list);
9935 free_percpu(group_item->stats);
9936 kfree(group_item);
9937}
9938
9939/**
9940 * devlink_trap_groups_register - Register packet trap groups with devlink.
9941 * @devlink: devlink.
9942 * @groups: Packet trap groups.
9943 * @groups_count: Count of provided packet trap groups.
9944 *
9945 * Return: Non-zero value on failure.
9946 */
9947int devlink_trap_groups_register(struct devlink *devlink,
9948 const struct devlink_trap_group *groups,
9949 size_t groups_count)
9950{
9951 int i, err;
9952
9953 mutex_lock(&devlink->lock);
9954 for (i = 0; i < groups_count; i++) {
9955 const struct devlink_trap_group *group = &groups[i];
9956
9957 err = devlink_trap_group_verify(group);
9958 if (err)
9959 goto err_trap_group_verify;
9960
9961 err = devlink_trap_group_register(devlink, group);
9962 if (err)
9963 goto err_trap_group_register;
9964 }
9965 mutex_unlock(&devlink->lock);
9966
9967 return 0;
9968
9969err_trap_group_register:
9970err_trap_group_verify:
9971 for (i--; i >= 0; i--)
9972 devlink_trap_group_unregister(devlink, &groups[i]);
9973 mutex_unlock(&devlink->lock);
9974 return err;
9975}
9976EXPORT_SYMBOL_GPL(devlink_trap_groups_register);
9977
9978/**
9979 * devlink_trap_groups_unregister - Unregister packet trap groups from devlink.
9980 * @devlink: devlink.
9981 * @groups: Packet trap groups.
9982 * @groups_count: Count of provided packet trap groups.
9983 */
9984void devlink_trap_groups_unregister(struct devlink *devlink,
9985 const struct devlink_trap_group *groups,
9986 size_t groups_count)
9987{
9988 int i;
9989
9990 mutex_lock(&devlink->lock);
9991 for (i = groups_count - 1; i >= 0; i--)
9992 devlink_trap_group_unregister(devlink, &groups[i]);
9993 mutex_unlock(&devlink->lock);
9994}
9995EXPORT_SYMBOL_GPL(devlink_trap_groups_unregister);
9996
1e8c6619
IS
9997static void
9998devlink_trap_policer_notify(struct devlink *devlink,
9999 const struct devlink_trap_policer_item *policer_item,
10000 enum devlink_command cmd)
10001{
10002 struct sk_buff *msg;
10003 int err;
10004
10005 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_POLICER_NEW &&
10006 cmd != DEVLINK_CMD_TRAP_POLICER_DEL);
10007
10008 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
10009 if (!msg)
10010 return;
10011
10012 err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, cmd, 0,
10013 0, 0);
10014 if (err) {
10015 nlmsg_free(msg);
10016 return;
10017 }
10018
10019 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
10020 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
10021}
10022
10023static int
10024devlink_trap_policer_register(struct devlink *devlink,
10025 const struct devlink_trap_policer *policer)
10026{
10027 struct devlink_trap_policer_item *policer_item;
10028 int err;
10029
10030 if (devlink_trap_policer_item_lookup(devlink, policer->id))
10031 return -EEXIST;
10032
10033 policer_item = kzalloc(sizeof(*policer_item), GFP_KERNEL);
10034 if (!policer_item)
10035 return -ENOMEM;
10036
10037 policer_item->policer = policer;
10038 policer_item->rate = policer->init_rate;
10039 policer_item->burst = policer->init_burst;
10040
10041 if (devlink->ops->trap_policer_init) {
10042 err = devlink->ops->trap_policer_init(devlink, policer);
10043 if (err)
10044 goto err_policer_init;
10045 }
10046
10047 list_add_tail(&policer_item->list, &devlink->trap_policer_list);
10048 devlink_trap_policer_notify(devlink, policer_item,
10049 DEVLINK_CMD_TRAP_POLICER_NEW);
10050
10051 return 0;
10052
10053err_policer_init:
10054 kfree(policer_item);
10055 return err;
10056}
10057
10058static void
10059devlink_trap_policer_unregister(struct devlink *devlink,
10060 const struct devlink_trap_policer *policer)
10061{
10062 struct devlink_trap_policer_item *policer_item;
10063
10064 policer_item = devlink_trap_policer_item_lookup(devlink, policer->id);
10065 if (WARN_ON_ONCE(!policer_item))
10066 return;
10067
10068 devlink_trap_policer_notify(devlink, policer_item,
10069 DEVLINK_CMD_TRAP_POLICER_DEL);
10070 list_del(&policer_item->list);
10071 if (devlink->ops->trap_policer_fini)
10072 devlink->ops->trap_policer_fini(devlink, policer);
10073 kfree(policer_item);
10074}
10075
10076/**
10077 * devlink_trap_policers_register - Register packet trap policers with devlink.
10078 * @devlink: devlink.
10079 * @policers: Packet trap policers.
10080 * @policers_count: Count of provided packet trap policers.
10081 *
10082 * Return: Non-zero value on failure.
10083 */
10084int
10085devlink_trap_policers_register(struct devlink *devlink,
10086 const struct devlink_trap_policer *policers,
10087 size_t policers_count)
10088{
10089 int i, err;
10090
10091 mutex_lock(&devlink->lock);
10092 for (i = 0; i < policers_count; i++) {
10093 const struct devlink_trap_policer *policer = &policers[i];
10094
10095 if (WARN_ON(policer->id == 0 ||
10096 policer->max_rate < policer->min_rate ||
10097 policer->max_burst < policer->min_burst)) {
10098 err = -EINVAL;
10099 goto err_trap_policer_verify;
10100 }
10101
10102 err = devlink_trap_policer_register(devlink, policer);
10103 if (err)
10104 goto err_trap_policer_register;
10105 }
10106 mutex_unlock(&devlink->lock);
10107
10108 return 0;
10109
10110err_trap_policer_register:
10111err_trap_policer_verify:
10112 for (i--; i >= 0; i--)
10113 devlink_trap_policer_unregister(devlink, &policers[i]);
10114 mutex_unlock(&devlink->lock);
10115 return err;
10116}
10117EXPORT_SYMBOL_GPL(devlink_trap_policers_register);
10118
10119/**
10120 * devlink_trap_policers_unregister - Unregister packet trap policers from devlink.
10121 * @devlink: devlink.
10122 * @policers: Packet trap policers.
10123 * @policers_count: Count of provided packet trap policers.
10124 */
10125void
10126devlink_trap_policers_unregister(struct devlink *devlink,
10127 const struct devlink_trap_policer *policers,
10128 size_t policers_count)
10129{
10130 int i;
10131
10132 mutex_lock(&devlink->lock);
10133 for (i = policers_count - 1; i >= 0; i--)
10134 devlink_trap_policer_unregister(devlink, &policers[i]);
10135 mutex_unlock(&devlink->lock);
10136}
10137EXPORT_SYMBOL_GPL(devlink_trap_policers_unregister);
10138
ddb6e99e
JK
10139static void __devlink_compat_running_version(struct devlink *devlink,
10140 char *buf, size_t len)
10141{
10142 const struct nlattr *nlattr;
10143 struct devlink_info_req req;
10144 struct sk_buff *msg;
10145 int rem, err;
10146
ddb6e99e
JK
10147 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
10148 if (!msg)
10149 return;
10150
10151 req.msg = msg;
10152 err = devlink->ops->info_get(devlink, &req, NULL);
10153 if (err)
10154 goto free_msg;
10155
10156 nla_for_each_attr(nlattr, (void *)msg->data, msg->len, rem) {
10157 const struct nlattr *kv;
10158 int rem_kv;
10159
10160 if (nla_type(nlattr) != DEVLINK_ATTR_INFO_VERSION_RUNNING)
10161 continue;
10162
10163 nla_for_each_nested(kv, nlattr, rem_kv) {
10164 if (nla_type(kv) != DEVLINK_ATTR_INFO_VERSION_VALUE)
10165 continue;
10166
10167 strlcat(buf, nla_data(kv), len);
10168 strlcat(buf, " ", len);
10169 }
10170 }
10171free_msg:
10172 nlmsg_free(msg);
10173}
10174
10175void devlink_compat_running_version(struct net_device *dev,
10176 char *buf, size_t len)
10177{
ddb6e99e
JK
10178 struct devlink *devlink;
10179
1b45ff6c
JK
10180 dev_hold(dev);
10181 rtnl_unlock();
10182
b473b0d2 10183 devlink = netdev_to_devlink(dev);
be6fe1d8 10184 if (!devlink || !devlink->ops->info_get)
e0dcd386 10185 goto out;
b473b0d2
JK
10186
10187 mutex_lock(&devlink->lock);
10188 __devlink_compat_running_version(devlink, buf, len);
10189 mutex_unlock(&devlink->lock);
1b45ff6c 10190
e0dcd386 10191out:
1b45ff6c
JK
10192 rtnl_lock();
10193 dev_put(dev);
ddb6e99e
JK
10194}
10195
4eceba17
JK
10196int devlink_compat_flash_update(struct net_device *dev, const char *file_name)
10197{
bc75c054 10198 struct devlink_flash_update_params params = {};
4eceba17 10199 struct devlink *devlink;
e0dcd386 10200 int ret;
4eceba17 10201
1b45ff6c
JK
10202 dev_hold(dev);
10203 rtnl_unlock();
10204
b473b0d2 10205 devlink = netdev_to_devlink(dev);
e0dcd386
JP
10206 if (!devlink || !devlink->ops->flash_update) {
10207 ret = -EOPNOTSUPP;
10208 goto out;
10209 }
4eceba17 10210
bc75c054
JK
10211 params.file_name = file_name;
10212
b473b0d2 10213 mutex_lock(&devlink->lock);
bc75c054 10214 ret = devlink->ops->flash_update(devlink, &params, NULL);
b473b0d2 10215 mutex_unlock(&devlink->lock);
1b45ff6c 10216
e0dcd386 10217out:
1b45ff6c
JK
10218 rtnl_lock();
10219 dev_put(dev);
10220
b473b0d2 10221 return ret;
4eceba17
JK
10222}
10223
af3836df
JP
10224int devlink_compat_phys_port_name_get(struct net_device *dev,
10225 char *name, size_t len)
10226{
10227 struct devlink_port *devlink_port;
10228
10229 /* RTNL mutex is held here which ensures that devlink_port
10230 * instance cannot disappear in the middle. No need to take
10231 * any devlink lock as only permanent values are accessed.
10232 */
10233 ASSERT_RTNL();
10234
10235 devlink_port = netdev_to_devlink_port(dev);
10236 if (!devlink_port)
10237 return -EOPNOTSUPP;
10238
10239 return __devlink_port_phys_port_name_get(devlink_port, name, len);
10240}
10241
7e1146e8
JP
10242int devlink_compat_switch_id_get(struct net_device *dev,
10243 struct netdev_phys_item_id *ppid)
10244{
10245 struct devlink_port *devlink_port;
10246
043b8413
VB
10247 /* Caller must hold RTNL mutex or reference to dev, which ensures that
10248 * devlink_port instance cannot disappear in the middle. No need to take
7e1146e8
JP
10249 * any devlink lock as only permanent values are accessed.
10250 */
7e1146e8 10251 devlink_port = netdev_to_devlink_port(dev);
46737a19 10252 if (!devlink_port || !devlink_port->switch_port)
7e1146e8
JP
10253 return -EOPNOTSUPP;
10254
10255 memcpy(ppid, &devlink_port->attrs.switch_id, sizeof(*ppid));
10256
10257 return 0;
10258}
10259
070c63f2
JP
10260static void __net_exit devlink_pernet_pre_exit(struct net *net)
10261{
10262 struct devlink *devlink;
ccdf0721 10263 u32 actions_performed;
070c63f2
JP
10264 int err;
10265
10266 /* In case network namespace is getting destroyed, reload
10267 * all devlink instances from this namespace into init_net.
10268 */
10269 mutex_lock(&devlink_mutex);
10270 list_for_each_entry(devlink, &devlink_list, list) {
10271 if (net_eq(devlink_net(devlink), net)) {
69d56e0e 10272 if (WARN_ON(!devlink_reload_supported(devlink->ops)))
070c63f2 10273 continue;
ccdf0721
MS
10274 err = devlink_reload(devlink, &init_net,
10275 DEVLINK_RELOAD_ACTION_DRIVER_REINIT,
dc64cc7c 10276 DEVLINK_RELOAD_LIMIT_UNSPEC,
ccdf0721 10277 &actions_performed, NULL);
a0c76345 10278 if (err && err != -EOPNOTSUPP)
070c63f2
JP
10279 pr_warn("Failed to reload devlink instance into init_net\n");
10280 }
10281 }
10282 mutex_unlock(&devlink_mutex);
10283}
10284
10285static struct pernet_operations devlink_pernet_ops __net_initdata = {
10286 .pre_exit = devlink_pernet_pre_exit,
10287};
10288
f4b6bcc7 10289static int __init devlink_init(void)
bfcd3a46 10290{
070c63f2
JP
10291 int err;
10292
10293 err = genl_register_family(&devlink_nl_family);
10294 if (err)
10295 goto out;
10296 err = register_pernet_subsys(&devlink_pernet_ops);
10297
10298out:
10299 WARN_ON(err);
10300 return err;
bfcd3a46
JP
10301}
10302
f4b6bcc7 10303subsys_initcall(devlink_init);