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