devlink: move devlink reload notifications back in between _down() and _up() calls
[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
4233static void devlink_param_notify(struct devlink *devlink,
4234 unsigned int port_index,
4235 struct devlink_param_item *param_item,
4236 enum devlink_command cmd);
4237
7d7e9169
JP
4238static void devlink_reload_netns_change(struct devlink *devlink,
4239 struct net *curr_net,
4240 struct net *dest_net)
070c63f2
JP
4241{
4242 struct devlink_param_item *param_item;
4243
4244 /* Userspace needs to be notified about devlink objects
4245 * removed from original and entering new network namespace.
4246 * The rest of the devlink objects are re-created during
4247 * reload process so the notifications are generated separatelly.
4248 */
4249
7d7e9169
JP
4250 list_for_each_entry(param_item, &devlink->param_list, list)
4251 devlink_param_notify(devlink, 0, param_item,
4252 DEVLINK_CMD_PARAM_DEL);
4253 devlink_notify(devlink, DEVLINK_CMD_DEL);
070c63f2 4254
7d7e9169
JP
4255 move_netdevice_notifier_net(curr_net, dest_net,
4256 &devlink->netdevice_nb);
4257 write_pnet(&devlink->_net, dest_net);
070c63f2 4258
7d7e9169 4259 devlink_notify(devlink, DEVLINK_CMD_NEW);
070c63f2 4260 list_for_each_entry(param_item, &devlink->param_list, list)
7d7e9169
JP
4261 devlink_param_notify(devlink, 0, param_item,
4262 DEVLINK_CMD_PARAM_NEW);
070c63f2
JP
4263}
4264
2670ac26
JP
4265static void devlink_reload_failed_set(struct devlink *devlink,
4266 bool reload_failed)
4267{
4268 if (devlink->reload_failed == reload_failed)
4269 return;
4270 devlink->reload_failed = reload_failed;
4271 devlink_notify(devlink, DEVLINK_CMD_NEW);
4272}
4273
4274bool devlink_is_reload_failed(const struct devlink *devlink)
4275{
4276 return devlink->reload_failed;
4277}
4278EXPORT_SYMBOL_GPL(devlink_is_reload_failed);
4279
a254c264
MS
4280static void
4281__devlink_reload_stats_update(struct devlink *devlink, u32 *reload_stats,
4282 enum devlink_reload_limit limit, u32 actions_performed)
4283{
4284 unsigned long actions = actions_performed;
4285 int stat_idx;
4286 int action;
4287
4288 for_each_set_bit(action, &actions, __DEVLINK_RELOAD_ACTION_MAX) {
4289 stat_idx = limit * __DEVLINK_RELOAD_ACTION_MAX + action;
4290 reload_stats[stat_idx]++;
4291 }
4292 devlink_notify(devlink, DEVLINK_CMD_NEW);
4293}
4294
4295static void
4296devlink_reload_stats_update(struct devlink *devlink, enum devlink_reload_limit limit,
4297 u32 actions_performed)
4298{
4299 __devlink_reload_stats_update(devlink, devlink->stats.reload_stats, limit,
4300 actions_performed);
4301}
4302
77069ba2
MS
4303/**
4304 * devlink_remote_reload_actions_performed - Update devlink on reload actions
4305 * performed which are not a direct result of devlink reload call.
4306 *
4307 * This should be called by a driver after performing reload actions in case it was not
4308 * a result of devlink reload call. For example fw_activate was performed as a result
4309 * of devlink reload triggered fw_activate on another host.
4310 * The motivation for this function is to keep data on reload actions performed on this
4311 * function whether it was done due to direct devlink reload call or not.
4312 *
4313 * @devlink: devlink
4314 * @limit: reload limit
4315 * @actions_performed: bitmask of actions performed
4316 */
4317void devlink_remote_reload_actions_performed(struct devlink *devlink,
4318 enum devlink_reload_limit limit,
4319 u32 actions_performed)
4320{
4321 if (WARN_ON(!actions_performed ||
4322 actions_performed & BIT(DEVLINK_RELOAD_ACTION_UNSPEC) ||
4323 actions_performed >= BIT(__DEVLINK_RELOAD_ACTION_MAX) ||
4324 limit > DEVLINK_RELOAD_LIMIT_MAX))
4325 return;
4326
4327 __devlink_reload_stats_update(devlink, devlink->stats.remote_reload_stats, limit,
4328 actions_performed);
4329}
4330EXPORT_SYMBOL_GPL(devlink_remote_reload_actions_performed);
4331
687125b5
JK
4332int devlink_reload(struct devlink *devlink, struct net *dest_net,
4333 enum devlink_reload_action action,
4334 enum devlink_reload_limit limit,
4335 u32 *actions_performed, struct netlink_ext_ack *extack)
070c63f2 4336{
77069ba2 4337 u32 remote_reload_stats[DEVLINK_RELOAD_STATS_ARRAY_SIZE];
05a7f4a8 4338 struct net *curr_net;
070c63f2
JP
4339 int err;
4340
77069ba2
MS
4341 memcpy(remote_reload_stats, devlink->stats.remote_reload_stats,
4342 sizeof(remote_reload_stats));
05a7f4a8 4343
dc64cc7c 4344 err = devlink->ops->reload_down(devlink, !!dest_net, action, limit, extack);
070c63f2
JP
4345 if (err)
4346 return err;
4347
7d7e9169
JP
4348 curr_net = devlink_net(devlink);
4349 if (dest_net && !net_eq(dest_net, curr_net))
4350 devlink_reload_netns_change(devlink, curr_net, dest_net);
070c63f2 4351
dc64cc7c 4352 err = devlink->ops->reload_up(devlink, action, limit, actions_performed, extack);
070c63f2 4353 devlink_reload_failed_set(devlink, !!err);
ccdf0721
MS
4354 if (err)
4355 return err;
4356
4357 WARN_ON(!(*actions_performed & BIT(action)));
77069ba2
MS
4358 /* Catch driver on updating the remote action within devlink reload */
4359 WARN_ON(memcmp(remote_reload_stats, devlink->stats.remote_reload_stats,
4360 sizeof(remote_reload_stats)));
a254c264 4361 devlink_reload_stats_update(devlink, limit, *actions_performed);
ccdf0721
MS
4362 return 0;
4363}
4364
4365static int
4366devlink_nl_reload_actions_performed_snd(struct devlink *devlink, u32 actions_performed,
4367 enum devlink_command cmd, struct genl_info *info)
4368{
4369 struct sk_buff *msg;
4370 void *hdr;
4371
4372 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4373 if (!msg)
4374 return -ENOMEM;
4375
4376 hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, &devlink_nl_family, 0, cmd);
4377 if (!hdr)
4378 goto free_msg;
4379
4380 if (devlink_nl_put_handle(msg, devlink))
4381 goto nla_put_failure;
4382
4383 if (nla_put_bitfield32(msg, DEVLINK_ATTR_RELOAD_ACTIONS_PERFORMED, actions_performed,
4384 actions_performed))
4385 goto nla_put_failure;
4386 genlmsg_end(msg, hdr);
4387
4388 return genlmsg_reply(msg, info);
4389
4390nla_put_failure:
4391 genlmsg_cancel(msg, hdr);
4392free_msg:
4393 nlmsg_free(msg);
4394 return -EMSGSIZE;
070c63f2
JP
4395}
4396
2d8dc5bb
AS
4397static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
4398{
4399 struct devlink *devlink = info->user_ptr[0];
ccdf0721 4400 enum devlink_reload_action action;
dc64cc7c 4401 enum devlink_reload_limit limit;
070c63f2 4402 struct net *dest_net = NULL;
ccdf0721 4403 u32 actions_performed;
2d8dc5bb
AS
4404 int err;
4405
82465bec 4406 if (!(devlink->features & DEVLINK_F_RELOAD))
2d8dc5bb
AS
4407 return -EOPNOTSUPP;
4408
4409 err = devlink_resources_validate(devlink, NULL, info);
4410 if (err) {
4411 NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed");
4412 return err;
4413 }
070c63f2 4414
ccdf0721
MS
4415 if (info->attrs[DEVLINK_ATTR_RELOAD_ACTION])
4416 action = nla_get_u8(info->attrs[DEVLINK_ATTR_RELOAD_ACTION]);
4417 else
4418 action = DEVLINK_RELOAD_ACTION_DRIVER_REINIT;
4419
4420 if (!devlink_reload_action_is_supported(devlink, action)) {
4421 NL_SET_ERR_MSG_MOD(info->extack,
4422 "Requested reload action is not supported by the driver");
4423 return -EOPNOTSUPP;
4424 }
4425
dc64cc7c
MS
4426 limit = DEVLINK_RELOAD_LIMIT_UNSPEC;
4427 if (info->attrs[DEVLINK_ATTR_RELOAD_LIMITS]) {
4428 struct nla_bitfield32 limits;
4429 u32 limits_selected;
4430
4431 limits = nla_get_bitfield32(info->attrs[DEVLINK_ATTR_RELOAD_LIMITS]);
4432 limits_selected = limits.value & limits.selector;
4433 if (!limits_selected) {
4434 NL_SET_ERR_MSG_MOD(info->extack, "Invalid limit selected");
4435 return -EINVAL;
4436 }
4437 for (limit = 0 ; limit <= DEVLINK_RELOAD_LIMIT_MAX ; limit++)
4438 if (limits_selected & BIT(limit))
4439 break;
4440 /* UAPI enables multiselection, but currently it is not used */
4441 if (limits_selected != BIT(limit)) {
4442 NL_SET_ERR_MSG_MOD(info->extack,
4443 "Multiselection of limit is not supported");
4444 return -EOPNOTSUPP;
4445 }
4446 if (!devlink_reload_limit_is_supported(devlink, limit)) {
4447 NL_SET_ERR_MSG_MOD(info->extack,
4448 "Requested limit is not supported by the driver");
4449 return -EOPNOTSUPP;
4450 }
4451 if (devlink_reload_combination_is_invalid(action, limit)) {
4452 NL_SET_ERR_MSG_MOD(info->extack,
4453 "Requested limit is invalid for this action");
4454 return -EINVAL;
4455 }
4456 }
4dbb0dad
ED
4457 if (info->attrs[DEVLINK_ATTR_NETNS_PID] ||
4458 info->attrs[DEVLINK_ATTR_NETNS_FD] ||
4459 info->attrs[DEVLINK_ATTR_NETNS_ID]) {
4460 dest_net = devlink_netns_get(skb, info);
4461 if (IS_ERR(dest_net))
4462 return PTR_ERR(dest_net);
4463 }
4464
dc64cc7c 4465 err = devlink_reload(devlink, dest_net, action, limit, &actions_performed, info->extack);
070c63f2
JP
4466
4467 if (dest_net)
4468 put_net(dest_net);
4469
ccdf0721
MS
4470 if (err)
4471 return err;
4472 /* For backward compatibility generate reply only if attributes used by user */
dc64cc7c 4473 if (!info->attrs[DEVLINK_ATTR_RELOAD_ACTION] && !info->attrs[DEVLINK_ATTR_RELOAD_LIMITS])
ccdf0721
MS
4474 return 0;
4475
4476 return devlink_nl_reload_actions_performed_snd(devlink, actions_performed,
4477 DEVLINK_CMD_RELOAD, info);
2d8dc5bb
AS
4478}
4479
191ed202
JP
4480static int devlink_nl_flash_update_fill(struct sk_buff *msg,
4481 struct devlink *devlink,
4482 enum devlink_command cmd,
6700acc5 4483 struct devlink_flash_notify *params)
191ed202
JP
4484{
4485 void *hdr;
4486
4487 hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd);
4488 if (!hdr)
4489 return -EMSGSIZE;
4490
4491 if (devlink_nl_put_handle(msg, devlink))
4492 goto nla_put_failure;
4493
4494 if (cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS)
4495 goto out;
4496
6700acc5 4497 if (params->status_msg &&
191ed202 4498 nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_MSG,
6700acc5 4499 params->status_msg))
191ed202 4500 goto nla_put_failure;
6700acc5 4501 if (params->component &&
191ed202 4502 nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_COMPONENT,
6700acc5 4503 params->component))
191ed202
JP
4504 goto nla_put_failure;
4505 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_DONE,
6700acc5 4506 params->done, DEVLINK_ATTR_PAD))
191ed202
JP
4507 goto nla_put_failure;
4508 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TOTAL,
6700acc5 4509 params->total, DEVLINK_ATTR_PAD))
191ed202 4510 goto nla_put_failure;
f92970c6 4511 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TIMEOUT,
6700acc5 4512 params->timeout, DEVLINK_ATTR_PAD))
f92970c6 4513 goto nla_put_failure;
191ed202
JP
4514
4515out:
4516 genlmsg_end(msg, hdr);
4517 return 0;
4518
4519nla_put_failure:
4520 genlmsg_cancel(msg, hdr);
4521 return -EMSGSIZE;
4522}
4523
4524static void __devlink_flash_update_notify(struct devlink *devlink,
4525 enum devlink_command cmd,
6700acc5 4526 struct devlink_flash_notify *params)
191ed202
JP
4527{
4528 struct sk_buff *msg;
4529 int err;
4530
4531 WARN_ON(cmd != DEVLINK_CMD_FLASH_UPDATE &&
4532 cmd != DEVLINK_CMD_FLASH_UPDATE_END &&
4533 cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS);
fec1faf2
LR
4534
4535 if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED))
4536 return;
191ed202
JP
4537
4538 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4539 if (!msg)
4540 return;
4541
6700acc5 4542 err = devlink_nl_flash_update_fill(msg, devlink, cmd, params);
191ed202
JP
4543 if (err)
4544 goto out_free_msg;
4545
4546 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
4547 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
4548 return;
4549
4550out_free_msg:
4551 nlmsg_free(msg);
4552}
4553
52cc5f3a 4554static void devlink_flash_update_begin_notify(struct devlink *devlink)
191ed202 4555{
ed43fbac 4556 struct devlink_flash_notify params = {};
6700acc5 4557
191ed202
JP
4558 __devlink_flash_update_notify(devlink,
4559 DEVLINK_CMD_FLASH_UPDATE,
6700acc5 4560 &params);
191ed202 4561}
191ed202 4562
52cc5f3a 4563static void devlink_flash_update_end_notify(struct devlink *devlink)
191ed202 4564{
ed43fbac 4565 struct devlink_flash_notify params = {};
6700acc5 4566
191ed202
JP
4567 __devlink_flash_update_notify(devlink,
4568 DEVLINK_CMD_FLASH_UPDATE_END,
6700acc5 4569 &params);
191ed202 4570}
191ed202
JP
4571
4572void devlink_flash_update_status_notify(struct devlink *devlink,
4573 const char *status_msg,
4574 const char *component,
4575 unsigned long done,
4576 unsigned long total)
4577{
6700acc5
SN
4578 struct devlink_flash_notify params = {
4579 .status_msg = status_msg,
4580 .component = component,
4581 .done = done,
4582 .total = total,
4583 };
4584
191ed202
JP
4585 __devlink_flash_update_notify(devlink,
4586 DEVLINK_CMD_FLASH_UPDATE_STATUS,
6700acc5 4587 &params);
191ed202
JP
4588}
4589EXPORT_SYMBOL_GPL(devlink_flash_update_status_notify);
4590
f92970c6
SN
4591void devlink_flash_update_timeout_notify(struct devlink *devlink,
4592 const char *status_msg,
4593 const char *component,
4594 unsigned long timeout)
4595{
6700acc5
SN
4596 struct devlink_flash_notify params = {
4597 .status_msg = status_msg,
4598 .component = component,
4599 .timeout = timeout,
4600 };
4601
f92970c6
SN
4602 __devlink_flash_update_notify(devlink,
4603 DEVLINK_CMD_FLASH_UPDATE_STATUS,
6700acc5 4604 &params);
f92970c6
SN
4605}
4606EXPORT_SYMBOL_GPL(devlink_flash_update_timeout_notify);
4607
f94b6063
JP
4608struct devlink_info_req {
4609 struct sk_buff *msg;
4610 void (*version_cb)(const char *version_name,
4611 enum devlink_info_version_type version_type,
4612 void *version_cb_priv);
4613 void *version_cb_priv;
4614};
4615
4616struct devlink_flash_component_lookup_ctx {
4617 const char *lookup_name;
4618 bool lookup_name_found;
4619};
4620
4621static void
4622devlink_flash_component_lookup_cb(const char *version_name,
4623 enum devlink_info_version_type version_type,
4624 void *version_cb_priv)
4625{
4626 struct devlink_flash_component_lookup_ctx *lookup_ctx = version_cb_priv;
4627
4628 if (version_type != DEVLINK_INFO_VERSION_TYPE_COMPONENT ||
4629 lookup_ctx->lookup_name_found)
4630 return;
4631
4632 lookup_ctx->lookup_name_found =
4633 !strcmp(lookup_ctx->lookup_name, version_name);
4634}
4635
4636static int devlink_flash_component_get(struct devlink *devlink,
4637 struct nlattr *nla_component,
4638 const char **p_component,
4639 struct netlink_ext_ack *extack)
4640{
4641 struct devlink_flash_component_lookup_ctx lookup_ctx = {};
4642 struct devlink_info_req req = {};
4643 const char *component;
4644 int ret;
4645
4646 if (!nla_component)
4647 return 0;
4648
4649 component = nla_data(nla_component);
4650
4651 if (!devlink->ops->info_get) {
4652 NL_SET_ERR_MSG_ATTR(extack, nla_component,
4653 "component update is not supported by this device");
4654 return -EOPNOTSUPP;
4655 }
4656
4657 lookup_ctx.lookup_name = component;
4658 req.version_cb = devlink_flash_component_lookup_cb;
4659 req.version_cb_priv = &lookup_ctx;
4660
4661 ret = devlink->ops->info_get(devlink, &req, NULL);
4662 if (ret)
4663 return ret;
4664
4665 if (!lookup_ctx.lookup_name_found) {
4666 NL_SET_ERR_MSG_ATTR(extack, nla_component,
4667 "selected component is not supported by this device");
4668 return -EINVAL;
4669 }
4670 *p_component = component;
4671 return 0;
4672}
4673
76726ccb
JK
4674static int devlink_nl_cmd_flash_update(struct sk_buff *skb,
4675 struct genl_info *info)
4676{
f94b6063 4677 struct nlattr *nla_overwrite_mask, *nla_file_name;
bc75c054 4678 struct devlink_flash_update_params params = {};
76726ccb 4679 struct devlink *devlink = info->user_ptr[0];
b44cfd4f 4680 const char *file_name;
22ec3d23 4681 u32 supported_params;
b44cfd4f 4682 int ret;
76726ccb
JK
4683
4684 if (!devlink->ops->flash_update)
4685 return -EOPNOTSUPP;
4686
1f7633b5 4687 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME))
76726ccb 4688 return -EINVAL;
22ec3d23 4689
f94b6063
JP
4690 ret = devlink_flash_component_get(devlink,
4691 info->attrs[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT],
4692 &params.component, info->extack);
4693 if (ret)
4694 return ret;
22ec3d23 4695
f94b6063 4696 supported_params = devlink->ops->supported_flash_update_params;
76726ccb 4697
5d5b4128
JK
4698 nla_overwrite_mask = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK];
4699 if (nla_overwrite_mask) {
4700 struct nla_bitfield32 sections;
4701
4702 if (!(supported_params & DEVLINK_SUPPORT_FLASH_UPDATE_OVERWRITE_MASK)) {
4703 NL_SET_ERR_MSG_ATTR(info->extack, nla_overwrite_mask,
4704 "overwrite settings are not supported by this device");
4705 return -EOPNOTSUPP;
4706 }
4707 sections = nla_get_bitfield32(nla_overwrite_mask);
4708 params.overwrite_mask = sections.value & sections.selector;
4709 }
4710
b44cfd4f
JK
4711 nla_file_name = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME];
4712 file_name = nla_data(nla_file_name);
4713 ret = request_firmware(&params.fw, file_name, devlink->dev);
4714 if (ret) {
4715 NL_SET_ERR_MSG_ATTR(info->extack, nla_file_name, "failed to locate the requested firmware file");
4716 return ret;
4717 }
4718
52cc5f3a 4719 devlink_flash_update_begin_notify(devlink);
b44cfd4f 4720 ret = devlink->ops->flash_update(devlink, &params, info->extack);
52cc5f3a 4721 devlink_flash_update_end_notify(devlink);
b44cfd4f
JK
4722
4723 release_firmware(params.fw);
4724
4725 return ret;
76726ccb
JK
4726}
4727
08f588fa
VG
4728static int
4729devlink_nl_selftests_fill(struct sk_buff *msg, struct devlink *devlink,
4730 u32 portid, u32 seq, int flags,
4731 struct netlink_ext_ack *extack)
4732{
4733 struct nlattr *selftests;
4734 void *hdr;
4735 int err;
4736 int i;
4737
4738 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags,
4739 DEVLINK_CMD_SELFTESTS_GET);
4740 if (!hdr)
4741 return -EMSGSIZE;
4742
4743 err = -EMSGSIZE;
4744 if (devlink_nl_put_handle(msg, devlink))
4745 goto err_cancel_msg;
4746
4747 selftests = nla_nest_start(msg, DEVLINK_ATTR_SELFTESTS);
4748 if (!selftests)
4749 goto err_cancel_msg;
4750
4751 for (i = DEVLINK_ATTR_SELFTEST_ID_UNSPEC + 1;
4752 i <= DEVLINK_ATTR_SELFTEST_ID_MAX; i++) {
4753 if (devlink->ops->selftest_check(devlink, i, extack)) {
4754 err = nla_put_flag(msg, i);
4755 if (err)
4756 goto err_cancel_msg;
4757 }
4758 }
4759
4760 nla_nest_end(msg, selftests);
4761 genlmsg_end(msg, hdr);
4762 return 0;
4763
4764err_cancel_msg:
4765 genlmsg_cancel(msg, hdr);
4766 return err;
4767}
4768
4769static int devlink_nl_cmd_selftests_get_doit(struct sk_buff *skb,
4770 struct genl_info *info)
4771{
4772 struct devlink *devlink = info->user_ptr[0];
4773 struct sk_buff *msg;
4774 int err;
4775
4776 if (!devlink->ops->selftest_check)
4777 return -EOPNOTSUPP;
4778
4779 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4780 if (!msg)
4781 return -ENOMEM;
4782
4783 err = devlink_nl_selftests_fill(msg, devlink, info->snd_portid,
4784 info->snd_seq, 0, info->extack);
4785 if (err) {
4786 nlmsg_free(msg);
4787 return err;
4788 }
4789
4790 return genlmsg_reply(msg, info);
4791}
4792
5ce76d78
JK
4793static int
4794devlink_nl_cmd_selftests_get_dump_one(struct sk_buff *msg,
4795 struct devlink *devlink,
4796 struct netlink_callback *cb)
08f588fa 4797{
5ce76d78
JK
4798 if (!devlink->ops->selftest_check)
4799 return 0;
08f588fa 4800
5ce76d78
JK
4801 return devlink_nl_selftests_fill(msg, devlink,
4802 NETLINK_CB(cb->skb).portid,
4803 cb->nlh->nlmsg_seq, NLM_F_MULTI,
4804 cb->extack);
08f588fa
VG
4805}
4806
5ce76d78
JK
4807const struct devlink_gen_cmd devl_gen_selftests = {
4808 .dump_one = devlink_nl_cmd_selftests_get_dump_one,
4809};
4810
08f588fa
VG
4811static int devlink_selftest_result_put(struct sk_buff *skb, unsigned int id,
4812 enum devlink_selftest_status test_status)
4813{
4814 struct nlattr *result_attr;
4815
4816 result_attr = nla_nest_start(skb, DEVLINK_ATTR_SELFTEST_RESULT);
4817 if (!result_attr)
4818 return -EMSGSIZE;
4819
4820 if (nla_put_u32(skb, DEVLINK_ATTR_SELFTEST_RESULT_ID, id) ||
4821 nla_put_u8(skb, DEVLINK_ATTR_SELFTEST_RESULT_STATUS,
4822 test_status))
4823 goto nla_put_failure;
4824
4825 nla_nest_end(skb, result_attr);
4826 return 0;
4827
4828nla_put_failure:
4829 nla_nest_cancel(skb, result_attr);
4830 return -EMSGSIZE;
4831}
4832
4833static int devlink_nl_cmd_selftests_run(struct sk_buff *skb,
4834 struct genl_info *info)
4835{
4836 struct nlattr *tb[DEVLINK_ATTR_SELFTEST_ID_MAX + 1];
4837 struct devlink *devlink = info->user_ptr[0];
4838 struct nlattr *attrs, *selftests;
4839 struct sk_buff *msg;
4840 void *hdr;
4841 int err;
4842 int i;
4843
4844 if (!devlink->ops->selftest_run || !devlink->ops->selftest_check)
4845 return -EOPNOTSUPP;
4846
1f7633b5 4847 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_SELFTESTS))
08f588fa 4848 return -EINVAL;
08f588fa
VG
4849
4850 attrs = info->attrs[DEVLINK_ATTR_SELFTESTS];
4851
4852 err = nla_parse_nested(tb, DEVLINK_ATTR_SELFTEST_ID_MAX, attrs,
4853 devlink_selftest_nl_policy, info->extack);
4854 if (err < 0)
4855 return err;
4856
4857 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4858 if (!msg)
4859 return -ENOMEM;
4860
4861 err = -EMSGSIZE;
4862 hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
4863 &devlink_nl_family, 0, DEVLINK_CMD_SELFTESTS_RUN);
4864 if (!hdr)
4865 goto free_msg;
4866
4867 if (devlink_nl_put_handle(msg, devlink))
4868 goto genlmsg_cancel;
4869
4870 selftests = nla_nest_start(msg, DEVLINK_ATTR_SELFTESTS);
4871 if (!selftests)
4872 goto genlmsg_cancel;
4873
4874 for (i = DEVLINK_ATTR_SELFTEST_ID_UNSPEC + 1;
4875 i <= DEVLINK_ATTR_SELFTEST_ID_MAX; i++) {
4876 enum devlink_selftest_status test_status;
4877
4878 if (nla_get_flag(tb[i])) {
4879 if (!devlink->ops->selftest_check(devlink, i,
4880 info->extack)) {
4881 if (devlink_selftest_result_put(msg, i,
4882 DEVLINK_SELFTEST_STATUS_SKIP))
4883 goto selftests_nest_cancel;
4884 continue;
4885 }
4886
4887 test_status = devlink->ops->selftest_run(devlink, i,
4888 info->extack);
4889 if (devlink_selftest_result_put(msg, i, test_status))
4890 goto selftests_nest_cancel;
4891 }
4892 }
4893
4894 nla_nest_end(msg, selftests);
4895 genlmsg_end(msg, hdr);
4896 return genlmsg_reply(msg, info);
4897
4898selftests_nest_cancel:
4899 nla_nest_cancel(msg, selftests);
4900genlmsg_cancel:
4901 genlmsg_cancel(msg, hdr);
4902free_msg:
4903 nlmsg_free(msg);
4904 return err;
4905}
4906
036467c3
MS
4907static const struct devlink_param devlink_param_generic[] = {
4908 {
4909 .id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET,
4910 .name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME,
4911 .type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE,
4912 },
4913 {
4914 .id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
4915 .name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME,
4916 .type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE,
4917 },
f567bcda
VV
4918 {
4919 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV,
4920 .name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME,
4921 .type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE,
4922 },
f6a69885
AV
4923 {
4924 .id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT,
4925 .name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME,
4926 .type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE,
4927 },
e3b51061
VV
4928 {
4929 .id = DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI,
4930 .name = DEVLINK_PARAM_GENERIC_IGNORE_ARI_NAME,
4931 .type = DEVLINK_PARAM_GENERIC_IGNORE_ARI_TYPE,
4932 },
f61cba42
VV
4933 {
4934 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
4935 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_NAME,
4936 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_TYPE,
4937 },
16511789
VV
4938 {
4939 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
4940 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_NAME,
4941 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_TYPE,
4942 },
846e980a
ST
4943 {
4944 .id = DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY,
4945 .name = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME,
4946 .type = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE,
4947 },
5bbd21df
DM
4948 {
4949 .id = DEVLINK_PARAM_GENERIC_ID_RESET_DEV_ON_DRV_PROBE,
4950 .name = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_NAME,
4951 .type = DEVLINK_PARAM_GENERIC_RESET_DEV_ON_DRV_PROBE_TYPE,
4952 },
6c7295e1
MG
4953 {
4954 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_ROCE,
4955 .name = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_NAME,
4956 .type = DEVLINK_PARAM_GENERIC_ENABLE_ROCE_TYPE,
4957 },
195d9dec
MS
4958 {
4959 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_REMOTE_DEV_RESET,
4960 .name = DEVLINK_PARAM_GENERIC_ENABLE_REMOTE_DEV_RESET_NAME,
4961 .type = DEVLINK_PARAM_GENERIC_ENABLE_REMOTE_DEV_RESET_TYPE,
4962 },
f13a5ad8
PP
4963 {
4964 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_ETH,
4965 .name = DEVLINK_PARAM_GENERIC_ENABLE_ETH_NAME,
4966 .type = DEVLINK_PARAM_GENERIC_ENABLE_ETH_TYPE,
4967 },
8ddaabee
PP
4968 {
4969 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_RDMA,
4970 .name = DEVLINK_PARAM_GENERIC_ENABLE_RDMA_NAME,
4971 .type = DEVLINK_PARAM_GENERIC_ENABLE_RDMA_TYPE,
4972 },
076b2a9d
PP
4973 {
4974 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_VNET,
4975 .name = DEVLINK_PARAM_GENERIC_ENABLE_VNET_NAME,
4976 .type = DEVLINK_PARAM_GENERIC_ENABLE_VNET_TYPE,
4977 },
325e0d0a
SS
4978 {
4979 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_IWARP,
4980 .name = DEVLINK_PARAM_GENERIC_ENABLE_IWARP_NAME,
4981 .type = DEVLINK_PARAM_GENERIC_ENABLE_IWARP_TYPE,
4982 },
47402385
SD
4983 {
4984 .id = DEVLINK_PARAM_GENERIC_ID_IO_EQ_SIZE,
4985 .name = DEVLINK_PARAM_GENERIC_IO_EQ_SIZE_NAME,
4986 .type = DEVLINK_PARAM_GENERIC_IO_EQ_SIZE_TYPE,
4987 },
0b5705eb
SD
4988 {
4989 .id = DEVLINK_PARAM_GENERIC_ID_EVENT_EQ_SIZE,
4990 .name = DEVLINK_PARAM_GENERIC_EVENT_EQ_SIZE_NAME,
4991 .type = DEVLINK_PARAM_GENERIC_EVENT_EQ_SIZE_TYPE,
4992 },
036467c3 4993};
eabaef18
MS
4994
4995static int devlink_param_generic_verify(const struct devlink_param *param)
4996{
4997 /* verify it match generic parameter by id and name */
4998 if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX)
4999 return -EINVAL;
5000 if (strcmp(param->name, devlink_param_generic[param->id].name))
5001 return -ENOENT;
5002
5003 WARN_ON(param->type != devlink_param_generic[param->id].type);
5004
5005 return 0;
5006}
5007
5008static int devlink_param_driver_verify(const struct devlink_param *param)
5009{
5010 int i;
5011
5012 if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX)
5013 return -EINVAL;
5014 /* verify no such name in generic params */
5015 for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++)
5016 if (!strcmp(param->name, devlink_param_generic[i].name))
5017 return -EEXIST;
5018
5019 return 0;
5020}
5021
5022static struct devlink_param_item *
5023devlink_param_find_by_name(struct list_head *param_list,
5024 const char *param_name)
5025{
5026 struct devlink_param_item *param_item;
5027
5028 list_for_each_entry(param_item, param_list, list)
5029 if (!strcmp(param_item->param->name, param_name))
5030 return param_item;
5031 return NULL;
5032}
5033
ec01aeb1
MS
5034static struct devlink_param_item *
5035devlink_param_find_by_id(struct list_head *param_list, u32 param_id)
5036{
5037 struct devlink_param_item *param_item;
5038
5039 list_for_each_entry(param_item, param_list, list)
5040 if (param_item->param->id == param_id)
5041 return param_item;
5042 return NULL;
5043}
5044
45f05def
MS
5045static bool
5046devlink_param_cmode_is_supported(const struct devlink_param *param,
5047 enum devlink_param_cmode cmode)
5048{
5049 return test_bit(cmode, &param->supported_cmodes);
5050}
5051
5052static int devlink_param_get(struct devlink *devlink,
5053 const struct devlink_param *param,
5054 struct devlink_param_gset_ctx *ctx)
5055{
6b4db2e5 5056 if (!param->get || devlink->reload_failed)
45f05def
MS
5057 return -EOPNOTSUPP;
5058 return param->get(devlink, param->id, ctx);
5059}
5060
e3b7ca18
MS
5061static int devlink_param_set(struct devlink *devlink,
5062 const struct devlink_param *param,
5063 struct devlink_param_gset_ctx *ctx)
5064{
6b4db2e5 5065 if (!param->set || devlink->reload_failed)
e3b7ca18
MS
5066 return -EOPNOTSUPP;
5067 return param->set(devlink, param->id, ctx);
5068}
5069
45f05def
MS
5070static int
5071devlink_param_type_to_nla_type(enum devlink_param_type param_type)
5072{
5073 switch (param_type) {
5074 case DEVLINK_PARAM_TYPE_U8:
5075 return NLA_U8;
5076 case DEVLINK_PARAM_TYPE_U16:
5077 return NLA_U16;
5078 case DEVLINK_PARAM_TYPE_U32:
5079 return NLA_U32;
5080 case DEVLINK_PARAM_TYPE_STRING:
5081 return NLA_STRING;
5082 case DEVLINK_PARAM_TYPE_BOOL:
5083 return NLA_FLAG;
5084 default:
5085 return -EINVAL;
5086 }
5087}
5088
5089static int
5090devlink_nl_param_value_fill_one(struct sk_buff *msg,
5091 enum devlink_param_type type,
5092 enum devlink_param_cmode cmode,
5093 union devlink_param_value val)
5094{
5095 struct nlattr *param_value_attr;
5096
ae0be8de
MK
5097 param_value_attr = nla_nest_start_noflag(msg,
5098 DEVLINK_ATTR_PARAM_VALUE);
45f05def
MS
5099 if (!param_value_attr)
5100 goto nla_put_failure;
5101
5102 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
5103 goto value_nest_cancel;
5104
5105 switch (type) {
5106 case DEVLINK_PARAM_TYPE_U8:
5107 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8))
5108 goto value_nest_cancel;
5109 break;
5110 case DEVLINK_PARAM_TYPE_U16:
5111 if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16))
5112 goto value_nest_cancel;
5113 break;
5114 case DEVLINK_PARAM_TYPE_U32:
5115 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32))
5116 goto value_nest_cancel;
5117 break;
5118 case DEVLINK_PARAM_TYPE_STRING:
5119 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
5120 val.vstr))
5121 goto value_nest_cancel;
5122 break;
5123 case DEVLINK_PARAM_TYPE_BOOL:
5124 if (val.vbool &&
5125 nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA))
5126 goto value_nest_cancel;
5127 break;
5128 }
5129
5130 nla_nest_end(msg, param_value_attr);
5131 return 0;
5132
5133value_nest_cancel:
5134 nla_nest_cancel(msg, param_value_attr);
5135nla_put_failure:
5136 return -EMSGSIZE;
5137}
5138
5139static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
f4601dee 5140 unsigned int port_index,
45f05def
MS
5141 struct devlink_param_item *param_item,
5142 enum devlink_command cmd,
5143 u32 portid, u32 seq, int flags)
5144{
5145 union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
7c62cfb8 5146 bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
45f05def
MS
5147 const struct devlink_param *param = param_item->param;
5148 struct devlink_param_gset_ctx ctx;
5149 struct nlattr *param_values_list;
5150 struct nlattr *param_attr;
5151 int nla_type;
5152 void *hdr;
5153 int err;
5154 int i;
5155
5156 /* Get value from driver part to driverinit configuration mode */
5157 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
5158 if (!devlink_param_cmode_is_supported(param, i))
5159 continue;
5160 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
5161 if (!param_item->driverinit_value_valid)
5162 return -EOPNOTSUPP;
5163 param_value[i] = param_item->driverinit_value;
5164 } else {
5165 ctx.cmode = i;
5166 err = devlink_param_get(devlink, param, &ctx);
5167 if (err)
5168 return err;
5169 param_value[i] = ctx.val;
5170 }
7c62cfb8 5171 param_value_set[i] = true;
45f05def
MS
5172 }
5173
5174 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
5175 if (!hdr)
5176 return -EMSGSIZE;
5177
5178 if (devlink_nl_put_handle(msg, devlink))
5179 goto genlmsg_cancel;
f4601dee 5180
c1e5786d
VV
5181 if (cmd == DEVLINK_CMD_PORT_PARAM_GET ||
5182 cmd == DEVLINK_CMD_PORT_PARAM_NEW ||
5183 cmd == DEVLINK_CMD_PORT_PARAM_DEL)
f4601dee
VV
5184 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index))
5185 goto genlmsg_cancel;
5186
ae0be8de 5187 param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM);
45f05def
MS
5188 if (!param_attr)
5189 goto genlmsg_cancel;
5190 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name))
5191 goto param_nest_cancel;
5192 if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC))
5193 goto param_nest_cancel;
5194
5195 nla_type = devlink_param_type_to_nla_type(param->type);
5196 if (nla_type < 0)
5197 goto param_nest_cancel;
5198 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type))
5199 goto param_nest_cancel;
5200
ae0be8de
MK
5201 param_values_list = nla_nest_start_noflag(msg,
5202 DEVLINK_ATTR_PARAM_VALUES_LIST);
45f05def
MS
5203 if (!param_values_list)
5204 goto param_nest_cancel;
5205
5206 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
7c62cfb8 5207 if (!param_value_set[i])
45f05def
MS
5208 continue;
5209 err = devlink_nl_param_value_fill_one(msg, param->type,
5210 i, param_value[i]);
5211 if (err)
5212 goto values_list_nest_cancel;
5213 }
5214
5215 nla_nest_end(msg, param_values_list);
5216 nla_nest_end(msg, param_attr);
5217 genlmsg_end(msg, hdr);
5218 return 0;
5219
5220values_list_nest_cancel:
5221 nla_nest_end(msg, param_values_list);
5222param_nest_cancel:
5223 nla_nest_cancel(msg, param_attr);
5224genlmsg_cancel:
5225 genlmsg_cancel(msg, hdr);
5226 return -EMSGSIZE;
5227}
5228
ea601e17 5229static void devlink_param_notify(struct devlink *devlink,
c1e5786d 5230 unsigned int port_index,
ea601e17
MS
5231 struct devlink_param_item *param_item,
5232 enum devlink_command cmd)
5233{
5234 struct sk_buff *msg;
5235 int err;
5236
c1e5786d
VV
5237 WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL &&
5238 cmd != DEVLINK_CMD_PORT_PARAM_NEW &&
5239 cmd != DEVLINK_CMD_PORT_PARAM_DEL);
1d18bb1a
JK
5240
5241 /* devlink_notify_register() / devlink_notify_unregister()
5242 * will replay the notifications if the params are added/removed
5243 * outside of the lifetime of the instance.
5244 */
5245 if (!devl_is_registered(devlink))
5246 return;
ea601e17
MS
5247
5248 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5249 if (!msg)
5250 return;
c1e5786d
VV
5251 err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd,
5252 0, 0, 0);
ea601e17
MS
5253 if (err) {
5254 nlmsg_free(msg);
5255 return;
5256 }
5257
5258 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
5259 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
5260}
5261
5ce76d78
JK
5262static int
5263devlink_nl_cmd_param_get_dump_one(struct sk_buff *msg, struct devlink *devlink,
5264 struct netlink_callback *cb)
45f05def 5265{
3015f822 5266 struct devlink_nl_dump_state *state = devlink_dump_state(cb);
5ce76d78
JK
5267 struct devlink_param_item *param_item;
5268 int idx = 0;
c62c2cfb 5269 int err = 0;
45f05def 5270
5ce76d78
JK
5271 list_for_each_entry(param_item, &devlink->param_list, list) {
5272 if (idx < state->idx) {
45f05def 5273 idx++;
5ce76d78 5274 continue;
45f05def 5275 }
5ce76d78
JK
5276 err = devlink_nl_param_fill(msg, devlink, 0, param_item,
5277 DEVLINK_CMD_PARAM_GET,
5278 NETLINK_CB(cb->skb).portid,
5279 cb->nlh->nlmsg_seq,
5280 NLM_F_MULTI);
5281 if (err == -EOPNOTSUPP) {
5282 err = 0;
5283 } else if (err) {
5284 state->idx = idx;
5285 break;
5286 }
5287 idx++;
45f05def 5288 }
c62c2cfb 5289
5ce76d78 5290 return err;
45f05def
MS
5291}
5292
5ce76d78
JK
5293const struct devlink_gen_cmd devl_gen_param = {
5294 .dump_one = devlink_nl_cmd_param_get_dump_one,
5295};
5296
e3b7ca18
MS
5297static int
5298devlink_param_type_get_from_info(struct genl_info *info,
5299 enum devlink_param_type *param_type)
5300{
1f7633b5 5301 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_TYPE))
e3b7ca18
MS
5302 return -EINVAL;
5303
5304 switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) {
5305 case NLA_U8:
5306 *param_type = DEVLINK_PARAM_TYPE_U8;
5307 break;
5308 case NLA_U16:
5309 *param_type = DEVLINK_PARAM_TYPE_U16;
5310 break;
5311 case NLA_U32:
5312 *param_type = DEVLINK_PARAM_TYPE_U32;
5313 break;
5314 case NLA_STRING:
5315 *param_type = DEVLINK_PARAM_TYPE_STRING;
5316 break;
5317 case NLA_FLAG:
5318 *param_type = DEVLINK_PARAM_TYPE_BOOL;
5319 break;
5320 default:
5321 return -EINVAL;
5322 }
5323
5324 return 0;
5325}
5326
5327static int
5328devlink_param_value_get_from_info(const struct devlink_param *param,
5329 struct genl_info *info,
5330 union devlink_param_value *value)
5331{
8750939b 5332 struct nlattr *param_data;
f355cfcd
MS
5333 int len;
5334
8750939b
JK
5335 param_data = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA];
5336
5337 if (param->type != DEVLINK_PARAM_TYPE_BOOL && !param_data)
e3b7ca18
MS
5338 return -EINVAL;
5339
5340 switch (param->type) {
5341 case DEVLINK_PARAM_TYPE_U8:
8750939b
JK
5342 if (nla_len(param_data) != sizeof(u8))
5343 return -EINVAL;
5344 value->vu8 = nla_get_u8(param_data);
e3b7ca18
MS
5345 break;
5346 case DEVLINK_PARAM_TYPE_U16:
8750939b
JK
5347 if (nla_len(param_data) != sizeof(u16))
5348 return -EINVAL;
5349 value->vu16 = nla_get_u16(param_data);
e3b7ca18
MS
5350 break;
5351 case DEVLINK_PARAM_TYPE_U32:
8750939b
JK
5352 if (nla_len(param_data) != sizeof(u32))
5353 return -EINVAL;
5354 value->vu32 = nla_get_u32(param_data);
e3b7ca18
MS
5355 break;
5356 case DEVLINK_PARAM_TYPE_STRING:
8750939b
JK
5357 len = strnlen(nla_data(param_data), nla_len(param_data));
5358 if (len == nla_len(param_data) ||
bde74ad1 5359 len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
e3b7ca18 5360 return -EINVAL;
8750939b 5361 strcpy(value->vstr, nla_data(param_data));
e3b7ca18
MS
5362 break;
5363 case DEVLINK_PARAM_TYPE_BOOL:
8750939b
JK
5364 if (param_data && nla_len(param_data))
5365 return -EINVAL;
5366 value->vbool = nla_get_flag(param_data);
e3b7ca18
MS
5367 break;
5368 }
5369 return 0;
5370}
5371
45f05def 5372static struct devlink_param_item *
f4601dee 5373devlink_param_get_from_info(struct list_head *param_list,
45f05def
MS
5374 struct genl_info *info)
5375{
5376 char *param_name;
5377
1f7633b5 5378 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_NAME))
45f05def
MS
5379 return NULL;
5380
5381 param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]);
f4601dee 5382 return devlink_param_find_by_name(param_list, param_name);
45f05def
MS
5383}
5384
5385static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb,
5386 struct genl_info *info)
5387{
5388 struct devlink *devlink = info->user_ptr[0];
5389 struct devlink_param_item *param_item;
5390 struct sk_buff *msg;
5391 int err;
5392
f4601dee 5393 param_item = devlink_param_get_from_info(&devlink->param_list, info);
45f05def
MS
5394 if (!param_item)
5395 return -EINVAL;
5396
5397 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5398 if (!msg)
5399 return -ENOMEM;
5400
f4601dee 5401 err = devlink_nl_param_fill(msg, devlink, 0, param_item,
45f05def
MS
5402 DEVLINK_CMD_PARAM_GET,
5403 info->snd_portid, info->snd_seq, 0);
5404 if (err) {
5405 nlmsg_free(msg);
5406 return err;
5407 }
5408
5409 return genlmsg_reply(msg, info);
5410}
5411
9c54873b 5412static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
c1e5786d 5413 unsigned int port_index,
9c54873b
VV
5414 struct list_head *param_list,
5415 struct genl_info *info,
5416 enum devlink_command cmd)
e3b7ca18 5417{
e3b7ca18
MS
5418 enum devlink_param_type param_type;
5419 struct devlink_param_gset_ctx ctx;
5420 enum devlink_param_cmode cmode;
5421 struct devlink_param_item *param_item;
5422 const struct devlink_param *param;
5423 union devlink_param_value value;
5424 int err = 0;
5425
9c54873b 5426 param_item = devlink_param_get_from_info(param_list, info);
e3b7ca18
MS
5427 if (!param_item)
5428 return -EINVAL;
5429 param = param_item->param;
5430 err = devlink_param_type_get_from_info(info, &param_type);
5431 if (err)
5432 return err;
5433 if (param_type != param->type)
5434 return -EINVAL;
5435 err = devlink_param_value_get_from_info(param, info, &value);
5436 if (err)
5437 return err;
5438 if (param->validate) {
5439 err = param->validate(devlink, param->id, value, info->extack);
5440 if (err)
5441 return err;
5442 }
5443
1f7633b5 5444 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_PARAM_VALUE_CMODE))
e3b7ca18
MS
5445 return -EINVAL;
5446 cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
5447 if (!devlink_param_cmode_is_supported(param, cmode))
5448 return -EOPNOTSUPP;
5449
5450 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
1276534c
MS
5451 if (param->type == DEVLINK_PARAM_TYPE_STRING)
5452 strcpy(param_item->driverinit_value.vstr, value.vstr);
5453 else
5454 param_item->driverinit_value = value;
e3b7ca18
MS
5455 param_item->driverinit_value_valid = true;
5456 } else {
5457 if (!param->set)
5458 return -EOPNOTSUPP;
5459 ctx.val = value;
5460 ctx.cmode = cmode;
5461 err = devlink_param_set(devlink, param, &ctx);
5462 if (err)
5463 return err;
5464 }
5465
c1e5786d 5466 devlink_param_notify(devlink, port_index, param_item, cmd);
e3b7ca18
MS
5467 return 0;
5468}
5469
9c54873b
VV
5470static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb,
5471 struct genl_info *info)
5472{
5473 struct devlink *devlink = info->user_ptr[0];
5474
c1e5786d 5475 return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->param_list,
9c54873b
VV
5476 info, DEVLINK_CMD_PARAM_NEW);
5477}
5478
f4601dee
VV
5479static int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg,
5480 struct netlink_callback *cb)
5481{
146ecbac 5482 NL_SET_ERR_MSG_MOD(cb->extack, "Port params are not supported");
f4601dee
VV
5483 return msg->len;
5484}
5485
5486static int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb,
5487 struct genl_info *info)
5488{
146ecbac
JP
5489 NL_SET_ERR_MSG_MOD(info->extack, "Port params are not supported");
5490 return -EINVAL;
f4601dee
VV
5491}
5492
9c54873b
VV
5493static int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb,
5494 struct genl_info *info)
5495{
146ecbac
JP
5496 NL_SET_ERR_MSG_MOD(info->extack, "Port params are not supported");
5497 return -EINVAL;
9c54873b
VV
5498}
5499
a006d467
AV
5500static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg,
5501 struct devlink *devlink,
5502 struct devlink_snapshot *snapshot)
5503{
5504 struct nlattr *snap_attr;
5505 int err;
5506
ae0be8de 5507 snap_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_SNAPSHOT);
a006d467
AV
5508 if (!snap_attr)
5509 return -EINVAL;
5510
5511 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id);
5512 if (err)
5513 goto nla_put_failure;
5514
5515 nla_nest_end(msg, snap_attr);
5516 return 0;
5517
5518nla_put_failure:
5519 nla_nest_cancel(msg, snap_attr);
5520 return err;
5521}
5522
5523static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg,
5524 struct devlink *devlink,
5525 struct devlink_region *region)
5526{
5527 struct devlink_snapshot *snapshot;
5528 struct nlattr *snapshots_attr;
5529 int err;
5530
ae0be8de
MK
5531 snapshots_attr = nla_nest_start_noflag(msg,
5532 DEVLINK_ATTR_REGION_SNAPSHOTS);
a006d467
AV
5533 if (!snapshots_attr)
5534 return -EINVAL;
5535
5536 list_for_each_entry(snapshot, &region->snapshot_list, list) {
5537 err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot);
5538 if (err)
5539 goto nla_put_failure;
5540 }
5541
5542 nla_nest_end(msg, snapshots_attr);
5543 return 0;
5544
5545nla_put_failure:
5546 nla_nest_cancel(msg, snapshots_attr);
5547 return err;
5548}
5549
d8db7ea5
AV
5550static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink,
5551 enum devlink_command cmd, u32 portid,
5552 u32 seq, int flags,
5553 struct devlink_region *region)
5554{
5555 void *hdr;
5556 int err;
5557
5558 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
5559 if (!hdr)
5560 return -EMSGSIZE;
5561
5562 err = devlink_nl_put_handle(msg, devlink);
5563 if (err)
5564 goto nla_put_failure;
5565
6c211809
DC
5566 if (region->port) {
5567 err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
5568 region->port->index);
5569 if (err)
544e7c33 5570 goto nla_put_failure;
6c211809 5571 }
544e7c33 5572
e8937681 5573 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->ops->name);
d8db7ea5
AV
5574 if (err)
5575 goto nla_put_failure;
5576
5577 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
5578 region->size,
5579 DEVLINK_ATTR_PAD);
5580 if (err)
5581 goto nla_put_failure;
5582
a70e3f02
JK
5583 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_MAX_SNAPSHOTS,
5584 region->max_snapshots);
5585 if (err)
5586 goto nla_put_failure;
5587
a006d467
AV
5588 err = devlink_nl_region_snapshots_id_put(msg, devlink, region);
5589 if (err)
5590 goto nla_put_failure;
5591
d8db7ea5
AV
5592 genlmsg_end(msg, hdr);
5593 return 0;
5594
5595nla_put_failure:
5596 genlmsg_cancel(msg, hdr);
5597 return err;
5598}
5599
dd86fec7
JK
5600static struct sk_buff *
5601devlink_nl_region_notify_build(struct devlink_region *region,
5602 struct devlink_snapshot *snapshot,
5603 enum devlink_command cmd, u32 portid, u32 seq)
866319bb
AV
5604{
5605 struct devlink *devlink = region->devlink;
5606 struct sk_buff *msg;
5607 void *hdr;
5608 int err;
5609
866319bb
AV
5610
5611 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5612 if (!msg)
dd86fec7 5613 return ERR_PTR(-ENOMEM);
866319bb 5614
dd86fec7
JK
5615 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, 0, cmd);
5616 if (!hdr) {
5617 err = -EMSGSIZE;
866319bb 5618 goto out_free_msg;
dd86fec7 5619 }
866319bb
AV
5620
5621 err = devlink_nl_put_handle(msg, devlink);
5622 if (err)
5623 goto out_cancel_msg;
5624
6c211809
DC
5625 if (region->port) {
5626 err = nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX,
5627 region->port->index);
5628 if (err)
544e7c33 5629 goto out_cancel_msg;
6c211809 5630 }
544e7c33 5631
866319bb 5632 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME,
e8937681 5633 region->ops->name);
866319bb
AV
5634 if (err)
5635 goto out_cancel_msg;
5636
5637 if (snapshot) {
5638 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID,
5639 snapshot->id);
5640 if (err)
5641 goto out_cancel_msg;
5642 } else {
5643 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
5644 region->size, DEVLINK_ATTR_PAD);
5645 if (err)
5646 goto out_cancel_msg;
5647 }
5648 genlmsg_end(msg, hdr);
5649
dd86fec7 5650 return msg;
866319bb
AV
5651
5652out_cancel_msg:
5653 genlmsg_cancel(msg, hdr);
5654out_free_msg:
5655 nlmsg_free(msg);
dd86fec7
JK
5656 return ERR_PTR(err);
5657}
5658
5659static void devlink_nl_region_notify(struct devlink_region *region,
5660 struct devlink_snapshot *snapshot,
5661 enum devlink_command cmd)
5662{
cf530217 5663 struct devlink *devlink = region->devlink;
dd86fec7
JK
5664 struct sk_buff *msg;
5665
5666 WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL);
ef91abfb
LR
5667 if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED))
5668 return;
dd86fec7
JK
5669
5670 msg = devlink_nl_region_notify_build(region, snapshot, cmd, 0, 0);
5671 if (IS_ERR(msg))
5672 return;
5673
cf530217
LR
5674 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), msg,
5675 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
866319bb
AV
5676}
5677
12102436
JK
5678/**
5679 * __devlink_snapshot_id_increment - Increment number of snapshots using an id
5680 * @devlink: devlink instance
5681 * @id: the snapshot id
5682 *
5683 * Track when a new snapshot begins using an id. Load the count for the
5684 * given id from the snapshot xarray, increment it, and store it back.
5685 *
5686 * Called when a new snapshot is created with the given id.
5687 *
5688 * The id *must* have been previously allocated by
5689 * devlink_region_snapshot_id_get().
5690 *
5691 * Returns 0 on success, or an error on failure.
5692 */
5693static int __devlink_snapshot_id_increment(struct devlink *devlink, u32 id)
5694{
5695 unsigned long count;
5696 void *p;
5502e871 5697 int err;
12102436 5698
5502e871 5699 xa_lock(&devlink->snapshot_ids);
12102436 5700 p = xa_load(&devlink->snapshot_ids, id);
5502e871
JP
5701 if (WARN_ON(!p)) {
5702 err = -EINVAL;
5703 goto unlock;
5704 }
12102436 5705
5502e871
JP
5706 if (WARN_ON(!xa_is_value(p))) {
5707 err = -EINVAL;
5708 goto unlock;
5709 }
12102436
JK
5710
5711 count = xa_to_value(p);
5712 count++;
5713
5502e871
JP
5714 err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
5715 GFP_ATOMIC));
5716unlock:
5717 xa_unlock(&devlink->snapshot_ids);
5718 return err;
12102436
JK
5719}
5720
5721/**
5722 * __devlink_snapshot_id_decrement - Decrease number of snapshots using an id
5723 * @devlink: devlink instance
5724 * @id: the snapshot id
5725 *
5726 * Track when a snapshot is deleted and stops using an id. Load the count
5727 * for the given id from the snapshot xarray, decrement it, and store it
5728 * back.
5729 *
5730 * If the count reaches zero, erase this id from the xarray, freeing it
5731 * up for future re-use by devlink_region_snapshot_id_get().
5732 *
5733 * Called when a snapshot using the given id is deleted, and when the
5734 * initial allocator of the id is finished using it.
5735 */
5736static void __devlink_snapshot_id_decrement(struct devlink *devlink, u32 id)
5737{
5738 unsigned long count;
5739 void *p;
5740
5502e871 5741 xa_lock(&devlink->snapshot_ids);
12102436
JK
5742 p = xa_load(&devlink->snapshot_ids, id);
5743 if (WARN_ON(!p))
5502e871 5744 goto unlock;
12102436
JK
5745
5746 if (WARN_ON(!xa_is_value(p)))
5502e871 5747 goto unlock;
12102436
JK
5748
5749 count = xa_to_value(p);
5750
5751 if (count > 1) {
5752 count--;
5502e871
JP
5753 __xa_store(&devlink->snapshot_ids, id, xa_mk_value(count),
5754 GFP_ATOMIC);
12102436
JK
5755 } else {
5756 /* If this was the last user, we can erase this id */
5502e871 5757 __xa_erase(&devlink->snapshot_ids, id);
12102436 5758 }
5502e871
JP
5759unlock:
5760 xa_unlock(&devlink->snapshot_ids);
12102436
JK
5761}
5762
b9a17abf
JK
5763/**
5764 * __devlink_snapshot_id_insert - Insert a specific snapshot ID
5765 * @devlink: devlink instance
5766 * @id: the snapshot id
5767 *
5768 * Mark the given snapshot id as used by inserting a zero value into the
5769 * snapshot xarray.
5770 *
5771 * This must be called while holding the devlink instance lock. Unlike
5772 * devlink_snapshot_id_get, the initial reference count is zero, not one.
5773 * It is expected that the id will immediately be used before
5774 * releasing the devlink instance lock.
5775 *
5776 * Returns zero on success, or an error code if the snapshot id could not
5777 * be inserted.
5778 */
5779static int __devlink_snapshot_id_insert(struct devlink *devlink, u32 id)
5780{
5502e871 5781 int err;
b9a17abf 5782
5502e871
JP
5783 xa_lock(&devlink->snapshot_ids);
5784 if (xa_load(&devlink->snapshot_ids, id)) {
5785 xa_unlock(&devlink->snapshot_ids);
b9a17abf 5786 return -EEXIST;
5502e871
JP
5787 }
5788 err = xa_err(__xa_store(&devlink->snapshot_ids, id, xa_mk_value(0),
5789 GFP_ATOMIC));
5790 xa_unlock(&devlink->snapshot_ids);
5791 return err;
b9a17abf
JK
5792}
5793
7000108f
JK
5794/**
5795 * __devlink_region_snapshot_id_get - get snapshot ID
5796 * @devlink: devlink instance
7ef19d3b 5797 * @id: storage to return snapshot id
7000108f 5798 *
7ef19d3b
JK
5799 * Allocates a new snapshot id. Returns zero on success, or a negative
5800 * error on failure. Must be called while holding the devlink instance
5801 * lock.
12102436
JK
5802 *
5803 * Snapshot IDs are tracked using an xarray which stores the number of
5804 * users of the snapshot id.
5805 *
5806 * Note that the caller of this function counts as a 'user', in order to
5807 * avoid race conditions. The caller must release its hold on the
5808 * snapshot by using devlink_region_snapshot_id_put.
7000108f 5809 */
7ef19d3b 5810static int __devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
7000108f 5811{
12102436
JK
5812 return xa_alloc(&devlink->snapshot_ids, id, xa_mk_value(1),
5813 xa_limit_32b, GFP_KERNEL);
7000108f
JK
5814}
5815
cf80faee
JK
5816/**
5817 * __devlink_region_snapshot_create - create a new snapshot
5818 * This will add a new snapshot of a region. The snapshot
5819 * will be stored on the region struct and can be accessed
5820 * from devlink. This is useful for future analyses of snapshots.
5821 * Multiple snapshots can be created on a region.
5822 * The @snapshot_id should be obtained using the getter function.
5823 *
2dec18ad 5824 * Must be called only while holding the region snapshot lock.
cf80faee
JK
5825 *
5826 * @region: devlink region of the snapshot
5827 * @data: snapshot data
5828 * @snapshot_id: snapshot id to be created
5829 */
5830static int
5831__devlink_region_snapshot_create(struct devlink_region *region,
5832 u8 *data, u32 snapshot_id)
5833{
5834 struct devlink *devlink = region->devlink;
5835 struct devlink_snapshot *snapshot;
12102436 5836 int err;
cf80faee 5837
2dec18ad 5838 lockdep_assert_held(&region->snapshot_lock);
cf80faee
JK
5839
5840 /* check if region can hold one more snapshot */
5841 if (region->cur_snapshots == region->max_snapshots)
47a39f61 5842 return -ENOSPC;
cf80faee
JK
5843
5844 if (devlink_region_snapshot_get_by_id(region, snapshot_id))
5845 return -EEXIST;
5846
5847 snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL);
5848 if (!snapshot)
5849 return -ENOMEM;
5850
12102436
JK
5851 err = __devlink_snapshot_id_increment(devlink, snapshot_id);
5852 if (err)
5853 goto err_snapshot_id_increment;
5854
cf80faee
JK
5855 snapshot->id = snapshot_id;
5856 snapshot->region = region;
5857 snapshot->data = data;
5858
5859 list_add_tail(&snapshot->list, &region->snapshot_list);
5860
5861 region->cur_snapshots++;
5862
5863 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW);
5864 return 0;
12102436
JK
5865
5866err_snapshot_id_increment:
5867 kfree(snapshot);
5868 return err;
cf80faee
JK
5869}
5870
92b49822
JP
5871static void devlink_region_snapshot_del(struct devlink_region *region,
5872 struct devlink_snapshot *snapshot)
5873{
12102436
JK
5874 struct devlink *devlink = region->devlink;
5875
2dec18ad 5876 lockdep_assert_held(&region->snapshot_lock);
12102436 5877
92b49822
JP
5878 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL);
5879 region->cur_snapshots--;
5880 list_del(&snapshot->list);
a0a09f6b 5881 region->ops->destructor(snapshot->data);
12102436 5882 __devlink_snapshot_id_decrement(devlink, snapshot->id);
92b49822
JP
5883 kfree(snapshot);
5884}
5885
d8db7ea5
AV
5886static int devlink_nl_cmd_region_get_doit(struct sk_buff *skb,
5887 struct genl_info *info)
5888{
5889 struct devlink *devlink = info->user_ptr[0];
544e7c33 5890 struct devlink_port *port = NULL;
d8db7ea5
AV
5891 struct devlink_region *region;
5892 const char *region_name;
5893 struct sk_buff *msg;
544e7c33 5894 unsigned int index;
d8db7ea5
AV
5895 int err;
5896
1f7633b5 5897 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME))
d8db7ea5
AV
5898 return -EINVAL;
5899
544e7c33
AL
5900 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
5901 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
5902
5903 port = devlink_port_get_by_index(devlink, index);
5904 if (!port)
5905 return -ENODEV;
5906 }
5907
d8db7ea5 5908 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
544e7c33
AL
5909 if (port)
5910 region = devlink_port_region_get_by_name(port, region_name);
5911 else
5912 region = devlink_region_get_by_name(devlink, region_name);
5913
d8db7ea5
AV
5914 if (!region)
5915 return -EINVAL;
5916
5917 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
5918 if (!msg)
5919 return -ENOMEM;
5920
5921 err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET,
5922 info->snd_portid, info->snd_seq, 0,
5923 region);
5924 if (err) {
5925 nlmsg_free(msg);
5926 return err;
5927 }
5928
5929 return genlmsg_reply(msg, info);
5930}
5931
544e7c33
AL
5932static int devlink_nl_cmd_region_get_port_dumpit(struct sk_buff *msg,
5933 struct netlink_callback *cb,
5934 struct devlink_port *port,
5935 int *idx,
5936 int start)
5937{
5938 struct devlink_region *region;
5939 int err = 0;
5940
5941 list_for_each_entry(region, &port->region_list, list) {
5942 if (*idx < start) {
5943 (*idx)++;
5944 continue;
5945 }
5946 err = devlink_nl_region_fill(msg, port->devlink,
5947 DEVLINK_CMD_REGION_GET,
5948 NETLINK_CB(cb->skb).portid,
5949 cb->nlh->nlmsg_seq,
5950 NLM_F_MULTI, region);
5951 if (err)
5952 goto out;
5953 (*idx)++;
5954 }
5955
5956out:
5957 return err;
5958}
5959
5ce76d78
JK
5960static int
5961devlink_nl_cmd_region_get_dump_one(struct sk_buff *msg, struct devlink *devlink,
5962 struct netlink_callback *cb)
544e7c33 5963{
5ce76d78 5964 struct devlink_nl_dump_state *state = devlink_dump_state(cb);
544e7c33
AL
5965 struct devlink_region *region;
5966 struct devlink_port *port;
47b438cc 5967 unsigned long port_index;
5ce76d78 5968 int idx = 0;
e4d5015b 5969 int err;
544e7c33 5970
544e7c33 5971 list_for_each_entry(region, &devlink->region_list, list) {
5ce76d78
JK
5972 if (idx < state->idx) {
5973 idx++;
544e7c33
AL
5974 continue;
5975 }
5976 err = devlink_nl_region_fill(msg, devlink,
5977 DEVLINK_CMD_REGION_GET,
5978 NETLINK_CB(cb->skb).portid,
5979 cb->nlh->nlmsg_seq,
5980 NLM_F_MULTI, region);
5ce76d78
JK
5981 if (err) {
5982 state->idx = idx;
e4d5015b 5983 return err;
5ce76d78
JK
5984 }
5985 idx++;
544e7c33
AL
5986 }
5987
47b438cc 5988 xa_for_each(&devlink->ports, port_index, port) {
5ce76d78
JK
5989 err = devlink_nl_cmd_region_get_port_dumpit(msg, cb, port, &idx,
5990 state->idx);
5991 if (err) {
5992 state->idx = idx;
e4d5015b 5993 return err;
5ce76d78 5994 }
544e7c33
AL
5995 }
5996
e4d5015b 5997 return 0;
544e7c33
AL
5998}
5999
5ce76d78
JK
6000const struct devlink_gen_cmd devl_gen_region = {
6001 .dump_one = devlink_nl_cmd_region_get_dump_one,
6002};
d8db7ea5 6003
866319bb
AV
6004static int devlink_nl_cmd_region_del(struct sk_buff *skb,
6005 struct genl_info *info)
6006{
6007 struct devlink *devlink = info->user_ptr[0];
6008 struct devlink_snapshot *snapshot;
544e7c33 6009 struct devlink_port *port = NULL;
866319bb
AV
6010 struct devlink_region *region;
6011 const char *region_name;
544e7c33 6012 unsigned int index;
866319bb
AV
6013 u32 snapshot_id;
6014
1f7633b5
JK
6015 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME) ||
6016 GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_SNAPSHOT_ID))
866319bb
AV
6017 return -EINVAL;
6018
6019 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
6020 snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
6021
544e7c33
AL
6022 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
6023 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
6024
6025 port = devlink_port_get_by_index(devlink, index);
6026 if (!port)
6027 return -ENODEV;
6028 }
6029
6030 if (port)
6031 region = devlink_port_region_get_by_name(port, region_name);
6032 else
6033 region = devlink_region_get_by_name(devlink, region_name);
6034
866319bb
AV
6035 if (!region)
6036 return -EINVAL;
6037
2dec18ad 6038 mutex_lock(&region->snapshot_lock);
866319bb 6039 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
2dec18ad
JP
6040 if (!snapshot) {
6041 mutex_unlock(&region->snapshot_lock);
866319bb 6042 return -EINVAL;
2dec18ad 6043 }
866319bb 6044
92b49822 6045 devlink_region_snapshot_del(region, snapshot);
2dec18ad 6046 mutex_unlock(&region->snapshot_lock);
866319bb
AV
6047 return 0;
6048}
6049
b9a17abf
JK
6050static int
6051devlink_nl_cmd_region_new(struct sk_buff *skb, struct genl_info *info)
6052{
6053 struct devlink *devlink = info->user_ptr[0];
043b3e22 6054 struct devlink_snapshot *snapshot;
544e7c33 6055 struct devlink_port *port = NULL;
043b3e22 6056 struct nlattr *snapshot_id_attr;
b9a17abf
JK
6057 struct devlink_region *region;
6058 const char *region_name;
544e7c33 6059 unsigned int index;
b9a17abf
JK
6060 u32 snapshot_id;
6061 u8 *data;
6062 int err;
6063
1f7633b5 6064 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_REGION_NAME)) {
b9a17abf
JK
6065 NL_SET_ERR_MSG_MOD(info->extack, "No region name provided");
6066 return -EINVAL;
6067 }
6068
b9a17abf 6069 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
544e7c33
AL
6070
6071 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
6072 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
6073
6074 port = devlink_port_get_by_index(devlink, index);
6075 if (!port)
6076 return -ENODEV;
6077 }
6078
6079 if (port)
6080 region = devlink_port_region_get_by_name(port, region_name);
6081 else
6082 region = devlink_region_get_by_name(devlink, region_name);
6083
b9a17abf
JK
6084 if (!region) {
6085 NL_SET_ERR_MSG_MOD(info->extack, "The requested region does not exist");
6086 return -EINVAL;
6087 }
6088
6089 if (!region->ops->snapshot) {
6090 NL_SET_ERR_MSG_MOD(info->extack, "The requested region does not support taking an immediate snapshot");
6091 return -EOPNOTSUPP;
6092 }
6093
2dec18ad
JP
6094 mutex_lock(&region->snapshot_lock);
6095
b9a17abf
JK
6096 if (region->cur_snapshots == region->max_snapshots) {
6097 NL_SET_ERR_MSG_MOD(info->extack, "The region has reached the maximum number of stored snapshots");
2dec18ad
JP
6098 err = -ENOSPC;
6099 goto unlock;
b9a17abf
JK
6100 }
6101
043b3e22
JK
6102 snapshot_id_attr = info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID];
6103 if (snapshot_id_attr) {
6104 snapshot_id = nla_get_u32(snapshot_id_attr);
b9a17abf 6105
043b3e22
JK
6106 if (devlink_region_snapshot_get_by_id(region, snapshot_id)) {
6107 NL_SET_ERR_MSG_MOD(info->extack, "The requested snapshot id is already in use");
2dec18ad
JP
6108 err = -EEXIST;
6109 goto unlock;
043b3e22 6110 }
b9a17abf 6111
043b3e22
JK
6112 err = __devlink_snapshot_id_insert(devlink, snapshot_id);
6113 if (err)
2dec18ad 6114 goto unlock;
043b3e22
JK
6115 } else {
6116 err = __devlink_region_snapshot_id_get(devlink, &snapshot_id);
6117 if (err) {
6118 NL_SET_ERR_MSG_MOD(info->extack, "Failed to allocate a new snapshot id");
2dec18ad 6119 goto unlock;
043b3e22
JK
6120 }
6121 }
b9a17abf 6122
544e7c33
AL
6123 if (port)
6124 err = region->port_ops->snapshot(port, region->port_ops,
6125 info->extack, &data);
6126 else
6127 err = region->ops->snapshot(devlink, region->ops,
6128 info->extack, &data);
b9a17abf
JK
6129 if (err)
6130 goto err_snapshot_capture;
6131
6132 err = __devlink_region_snapshot_create(region, data, snapshot_id);
6133 if (err)
6134 goto err_snapshot_create;
6135
043b3e22
JK
6136 if (!snapshot_id_attr) {
6137 struct sk_buff *msg;
6138
6139 snapshot = devlink_region_snapshot_get_by_id(region,
6140 snapshot_id);
80ef9286
AF
6141 if (WARN_ON(!snapshot)) {
6142 err = -EINVAL;
6143 goto unlock;
6144 }
043b3e22
JK
6145
6146 msg = devlink_nl_region_notify_build(region, snapshot,
6147 DEVLINK_CMD_REGION_NEW,
6148 info->snd_portid,
6149 info->snd_seq);
6150 err = PTR_ERR_OR_ZERO(msg);
6151 if (err)
6152 goto err_notify;
6153
6154 err = genlmsg_reply(msg, info);
6155 if (err)
6156 goto err_notify;
6157 }
6158
2dec18ad 6159 mutex_unlock(&region->snapshot_lock);
b9a17abf
JK
6160 return 0;
6161
6162err_snapshot_create:
6163 region->ops->destructor(data);
6164err_snapshot_capture:
6165 __devlink_snapshot_id_decrement(devlink, snapshot_id);
2dec18ad 6166 mutex_unlock(&region->snapshot_lock);
b9a17abf 6167 return err;
043b3e22
JK
6168
6169err_notify:
6170 devlink_region_snapshot_del(region, snapshot);
2dec18ad
JP
6171unlock:
6172 mutex_unlock(&region->snapshot_lock);
043b3e22 6173 return err;
b9a17abf
JK
6174}
6175
4e54795a 6176static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg,
4e54795a
AV
6177 u8 *chunk, u32 chunk_size,
6178 u64 addr)
6179{
6180 struct nlattr *chunk_attr;
6181 int err;
6182
ae0be8de 6183 chunk_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_CHUNK);
4e54795a
AV
6184 if (!chunk_attr)
6185 return -EINVAL;
6186
6187 err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk);
6188 if (err)
6189 goto nla_put_failure;
6190
6191 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr,
6192 DEVLINK_ATTR_PAD);
6193 if (err)
6194 goto nla_put_failure;
6195
6196 nla_nest_end(msg, chunk_attr);
6197 return 0;
6198
6199nla_put_failure:
6200 nla_nest_cancel(msg, chunk_attr);
6201 return err;
6202}
6203
6204#define DEVLINK_REGION_READ_CHUNK_SIZE 256
6205
2d4caf09
JK
6206typedef int devlink_chunk_fill_t(void *cb_priv, u8 *chunk, u32 chunk_size,
6207 u64 curr_offset,
6208 struct netlink_ext_ack *extack);
6209
6210static int
6211devlink_nl_region_read_fill(struct sk_buff *skb, devlink_chunk_fill_t *cb,
6212 void *cb_priv, u64 start_offset, u64 end_offset,
6213 u64 *new_offset, struct netlink_ext_ack *extack)
4e54795a 6214{
4e54795a 6215 u64 curr_offset = start_offset;
4e54795a 6216 int err = 0;
2d4caf09
JK
6217 u8 *data;
6218
6219 /* Allocate and re-use a single buffer */
6220 data = kmalloc(DEVLINK_REGION_READ_CHUNK_SIZE, GFP_KERNEL);
6221 if (!data)
6222 return -ENOMEM;
4e54795a
AV
6223
6224 *new_offset = start_offset;
6225
4e54795a
AV
6226 while (curr_offset < end_offset) {
6227 u32 data_size;
4e54795a 6228
28e0c250
JK
6229 data_size = min_t(u32, end_offset - curr_offset,
6230 DEVLINK_REGION_READ_CHUNK_SIZE);
4e54795a 6231
2d4caf09
JK
6232 err = cb(cb_priv, data, data_size, curr_offset, extack);
6233 if (err)
6234 break;
6235
284e9d1e 6236 err = devlink_nl_cmd_region_read_chunk_fill(skb, data, data_size, curr_offset);
4e54795a
AV
6237 if (err)
6238 break;
6239
6240 curr_offset += data_size;
6241 }
6242 *new_offset = curr_offset;
6243
2d4caf09
JK
6244 kfree(data);
6245
4e54795a
AV
6246 return err;
6247}
6248
2d4caf09
JK
6249static int
6250devlink_region_snapshot_fill(void *cb_priv, u8 *chunk, u32 chunk_size,
6251 u64 curr_offset,
6252 struct netlink_ext_ack __always_unused *extack)
6253{
6254 struct devlink_snapshot *snapshot = cb_priv;
6255
6256 memcpy(chunk, &snapshot->data[curr_offset], chunk_size);
6257
6258 return 0;
6259}
6260
af6397c9
JK
6261static int
6262devlink_region_port_direct_fill(void *cb_priv, u8 *chunk, u32 chunk_size,
6263 u64 curr_offset, struct netlink_ext_ack *extack)
6264{
6265 struct devlink_region *region = cb_priv;
6266
6267 return region->port_ops->read(region->port, region->port_ops, extack,
6268 curr_offset, chunk_size, chunk);
6269}
6270
6271static int
6272devlink_region_direct_fill(void *cb_priv, u8 *chunk, u32 chunk_size,
6273 u64 curr_offset, struct netlink_ext_ack *extack)
6274{
6275 struct devlink_region *region = cb_priv;
6276
6277 return region->ops->read(region->devlink, region->ops, extack,
6278 curr_offset, chunk_size, chunk);
6279}
6280
4e54795a
AV
6281static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
6282 struct netlink_callback *cb)
6283{
ee85da53 6284 const struct genl_dumpit_info *info = genl_dumpit_info(cb);
3015f822 6285 struct devlink_nl_dump_state *state = devlink_dump_state(cb);
e004ea10 6286 struct nlattr *chunks_attr, *region_attr, *snapshot_attr;
5a46b062 6287 u64 ret_offset, start_offset, end_offset = U64_MAX;
ee85da53 6288 struct nlattr **attrs = info->attrs;
544e7c33 6289 struct devlink_port *port = NULL;
af6397c9 6290 devlink_chunk_fill_t *region_cb;
4e54795a 6291 struct devlink_region *region;
4e54795a
AV
6292 const char *region_name;
6293 struct devlink *devlink;
544e7c33 6294 unsigned int index;
af6397c9 6295 void *region_cb_priv;
4e54795a
AV
6296 void *hdr;
6297 int err;
6298
3015f822 6299 start_offset = state->start_offset;
4e54795a 6300
870c7ad4 6301 devlink = devlink_get_from_attrs_lock(sock_net(cb->skb->sk), attrs);
d3efc2a6
JP
6302 if (IS_ERR(devlink))
6303 return PTR_ERR(devlink);
4e54795a 6304
611fd12c
JK
6305 if (!attrs[DEVLINK_ATTR_REGION_NAME]) {
6306 NL_SET_ERR_MSG(cb->extack, "No region name provided");
6307 err = -EINVAL;
6308 goto out_unlock;
6309 }
6310
544e7c33
AL
6311 if (info->attrs[DEVLINK_ATTR_PORT_INDEX]) {
6312 index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
6313
6314 port = devlink_port_get_by_index(devlink, index);
0d8cb946
DC
6315 if (!port) {
6316 err = -ENODEV;
6317 goto out_unlock;
6318 }
544e7c33
AL
6319 }
6320
611fd12c
JK
6321 region_attr = attrs[DEVLINK_ATTR_REGION_NAME];
6322 region_name = nla_data(region_attr);
544e7c33
AL
6323
6324 if (port)
6325 region = devlink_port_region_get_by_name(port, region_name);
6326 else
6327 region = devlink_region_get_by_name(devlink, region_name);
6328
fdd41ec2 6329 if (!region) {
611fd12c 6330 NL_SET_ERR_MSG_ATTR(cb->extack, region_attr, "Requested region does not exist");
fdd41ec2 6331 err = -EINVAL;
4e54795a 6332 goto out_unlock;
fdd41ec2 6333 }
4e54795a 6334
e004ea10 6335 snapshot_attr = attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID];
af6397c9
JK
6336 if (!snapshot_attr) {
6337 if (!nla_get_flag(attrs[DEVLINK_ATTR_REGION_DIRECT])) {
6338 NL_SET_ERR_MSG(cb->extack, "No snapshot id provided");
6339 err = -EINVAL;
6340 goto out_unlock;
6341 }
6342
6343 if (!region->ops->read) {
6344 NL_SET_ERR_MSG(cb->extack, "Requested region does not support direct read");
6345 err = -EOPNOTSUPP;
6346 goto out_unlock;
6347 }
6348
6349 if (port)
6350 region_cb = &devlink_region_port_direct_fill;
6351 else
6352 region_cb = &devlink_region_direct_fill;
6353 region_cb_priv = region;
6354 } else {
6355 struct devlink_snapshot *snapshot;
6356 u32 snapshot_id;
6357
6358 if (nla_get_flag(attrs[DEVLINK_ATTR_REGION_DIRECT])) {
6359 NL_SET_ERR_MSG_ATTR(cb->extack, snapshot_attr, "Direct region read does not use snapshot");
6360 err = -EINVAL;
6361 goto out_unlock;
6362 }
6363
6364 snapshot_id = nla_get_u32(snapshot_attr);
6365 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
6366 if (!snapshot) {
6367 NL_SET_ERR_MSG_ATTR(cb->extack, snapshot_attr, "Requested snapshot does not exist");
6368 err = -EINVAL;
6369 goto out_unlock;
6370 }
6371 region_cb = &devlink_region_snapshot_fill;
6372 region_cb_priv = snapshot;
e004ea10
JK
6373 }
6374
5a46b062
JK
6375 if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] &&
6376 attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) {
6377 if (!start_offset)
6378 start_offset =
6379 nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
6380
6381 end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
6382 end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]);
6383 }
6384
6385 if (end_offset > region->size)
6386 end_offset = region->size;
6387
d5b90e99 6388 /* return 0 if there is no further data to read */
5a46b062 6389 if (start_offset == end_offset) {
d5b90e99
JK
6390 err = 0;
6391 goto out_unlock;
6392 }
6393
4e54795a
AV
6394 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
6395 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
6396 DEVLINK_CMD_REGION_READ);
fdd41ec2
PP
6397 if (!hdr) {
6398 err = -EMSGSIZE;
4e54795a 6399 goto out_unlock;
fdd41ec2 6400 }
4e54795a
AV
6401
6402 err = devlink_nl_put_handle(skb, devlink);
6403 if (err)
6404 goto nla_put_failure;
6405
6c211809
DC
6406 if (region->port) {
6407 err = nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX,
6408 region->port->index);
6409 if (err)
544e7c33 6410 goto nla_put_failure;
6c211809 6411 }
544e7c33 6412
4e54795a
AV
6413 err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
6414 if (err)
6415 goto nla_put_failure;
6416
ae0be8de 6417 chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS);
fdd41ec2
PP
6418 if (!chunks_attr) {
6419 err = -EMSGSIZE;
4e54795a 6420 goto nla_put_failure;
fdd41ec2 6421 }
4e54795a 6422
af6397c9
JK
6423 err = devlink_nl_region_read_fill(skb, region_cb, region_cb_priv,
6424 start_offset, end_offset, &ret_offset,
6425 cb->extack);
4e54795a
AV
6426
6427 if (err && err != -EMSGSIZE)
6428 goto nla_put_failure;
6429
6430 /* Check if there was any progress done to prevent infinite loop */
fdd41ec2
PP
6431 if (ret_offset == start_offset) {
6432 err = -EINVAL;
4e54795a 6433 goto nla_put_failure;
fdd41ec2 6434 }
4e54795a 6435
3015f822 6436 state->start_offset = ret_offset;
4e54795a
AV
6437
6438 nla_nest_end(skb, chunks_attr);
6439 genlmsg_end(skb, hdr);
7715023a 6440 devl_unlock(devlink);
437ebfd9 6441 devlink_put(devlink);
4e54795a
AV
6442 return skb->len;
6443
6444nla_put_failure:
6445 genlmsg_cancel(skb, hdr);
6446out_unlock:
7715023a 6447 devl_unlock(devlink);
437ebfd9 6448 devlink_put(devlink);
fdd41ec2 6449 return err;
4e54795a
AV
6450}
6451
f9cf2288
JK
6452int devlink_info_serial_number_put(struct devlink_info_req *req, const char *sn)
6453{
f94b6063
JP
6454 if (!req->msg)
6455 return 0;
f9cf2288
JK
6456 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_SERIAL_NUMBER, sn);
6457}
6458EXPORT_SYMBOL_GPL(devlink_info_serial_number_put);
6459
b5872cd0
VV
6460int devlink_info_board_serial_number_put(struct devlink_info_req *req,
6461 const char *bsn)
6462{
f94b6063
JP
6463 if (!req->msg)
6464 return 0;
b5872cd0
VV
6465 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_BOARD_SERIAL_NUMBER,
6466 bsn);
6467}
6468EXPORT_SYMBOL_GPL(devlink_info_board_serial_number_put);
6469
fc6fae7d
JK
6470static int devlink_info_version_put(struct devlink_info_req *req, int attr,
6471 const char *version_name,
bb670123
JP
6472 const char *version_value,
6473 enum devlink_info_version_type version_type)
fc6fae7d
JK
6474{
6475 struct nlattr *nest;
6476 int err;
6477
f94b6063
JP
6478 if (req->version_cb)
6479 req->version_cb(version_name, version_type,
6480 req->version_cb_priv);
6481
6482 if (!req->msg)
6483 return 0;
6484
ae0be8de 6485 nest = nla_nest_start_noflag(req->msg, attr);
fc6fae7d
JK
6486 if (!nest)
6487 return -EMSGSIZE;
6488
6489 err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_NAME,
6490 version_name);
6491 if (err)
6492 goto nla_put_failure;
6493
6494 err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_VALUE,
6495 version_value);
6496 if (err)
6497 goto nla_put_failure;
6498
6499 nla_nest_end(req->msg, nest);
6500
6501 return 0;
6502
6503nla_put_failure:
6504 nla_nest_cancel(req->msg, nest);
6505 return err;
6506}
6507
6508int devlink_info_version_fixed_put(struct devlink_info_req *req,
6509 const char *version_name,
6510 const char *version_value)
6511{
6512 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_FIXED,
bb670123
JP
6513 version_name, version_value,
6514 DEVLINK_INFO_VERSION_TYPE_NONE);
fc6fae7d
JK
6515}
6516EXPORT_SYMBOL_GPL(devlink_info_version_fixed_put);
6517
6518int devlink_info_version_stored_put(struct devlink_info_req *req,
6519 const char *version_name,
6520 const char *version_value)
6521{
6522 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_STORED,
bb670123
JP
6523 version_name, version_value,
6524 DEVLINK_INFO_VERSION_TYPE_NONE);
fc6fae7d
JK
6525}
6526EXPORT_SYMBOL_GPL(devlink_info_version_stored_put);
6527
bb670123
JP
6528int devlink_info_version_stored_put_ext(struct devlink_info_req *req,
6529 const char *version_name,
6530 const char *version_value,
6531 enum devlink_info_version_type version_type)
6532{
6533 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_STORED,
6534 version_name, version_value,
6535 version_type);
6536}
6537EXPORT_SYMBOL_GPL(devlink_info_version_stored_put_ext);
6538
fc6fae7d
JK
6539int devlink_info_version_running_put(struct devlink_info_req *req,
6540 const char *version_name,
6541 const char *version_value)
6542{
6543 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_RUNNING,
bb670123
JP
6544 version_name, version_value,
6545 DEVLINK_INFO_VERSION_TYPE_NONE);
fc6fae7d
JK
6546}
6547EXPORT_SYMBOL_GPL(devlink_info_version_running_put);
6548
bb670123
JP
6549int devlink_info_version_running_put_ext(struct devlink_info_req *req,
6550 const char *version_name,
6551 const char *version_value,
6552 enum devlink_info_version_type version_type)
6553{
6554 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_RUNNING,
6555 version_name, version_value,
6556 version_type);
6557}
6558EXPORT_SYMBOL_GPL(devlink_info_version_running_put_ext);
6559
226bf980
VM
6560static int devlink_nl_driver_info_get(struct device_driver *drv,
6561 struct devlink_info_req *req)
6562{
6563 if (!drv)
6564 return 0;
6565
6566 if (drv->name[0])
6567 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRIVER_NAME,
6568 drv->name);
6569
6570 return 0;
6571}
6572
f9cf2288
JK
6573static int
6574devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
6575 enum devlink_command cmd, u32 portid,
6576 u32 seq, int flags, struct netlink_ext_ack *extack)
6577{
226bf980 6578 struct device *dev = devlink_to_dev(devlink);
f94b6063 6579 struct devlink_info_req req = {};
f9cf2288
JK
6580 void *hdr;
6581 int err;
6582
6583 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
6584 if (!hdr)
6585 return -EMSGSIZE;
6586
6587 err = -EMSGSIZE;
6588 if (devlink_nl_put_handle(msg, devlink))
6589 goto err_cancel_msg;
6590
6591 req.msg = msg;
c5cd7c86
VM
6592 if (devlink->ops->info_get) {
6593 err = devlink->ops->info_get(devlink, &req, extack);
6594 if (err)
6595 goto err_cancel_msg;
6596 }
f9cf2288 6597
226bf980
VM
6598 err = devlink_nl_driver_info_get(dev->driver, &req);
6599 if (err)
6600 goto err_cancel_msg;
6601
f9cf2288
JK
6602 genlmsg_end(msg, hdr);
6603 return 0;
6604
6605err_cancel_msg:
6606 genlmsg_cancel(msg, hdr);
6607 return err;
6608}
6609
6610static int devlink_nl_cmd_info_get_doit(struct sk_buff *skb,
6611 struct genl_info *info)
6612{
6613 struct devlink *devlink = info->user_ptr[0];
6614 struct sk_buff *msg;
6615 int err;
6616
f9cf2288
JK
6617 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
6618 if (!msg)
6619 return -ENOMEM;
6620
6621 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
6622 info->snd_portid, info->snd_seq, 0,
6623 info->extack);
6624 if (err) {
6625 nlmsg_free(msg);
6626 return err;
6627 }
6628
6629 return genlmsg_reply(msg, info);
6630}
6631
5ce76d78
JK
6632static int
6633devlink_nl_cmd_info_get_dump_one(struct sk_buff *msg, struct devlink *devlink,
6634 struct netlink_callback *cb)
f9cf2288 6635{
5ce76d78 6636 int err;
c62c2cfb 6637
5ce76d78
JK
6638 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
6639 NETLINK_CB(cb->skb).portid,
6640 cb->nlh->nlmsg_seq, NLM_F_MULTI,
6641 cb->extack);
6642 if (err == -EOPNOTSUPP)
6643 err = 0;
6644 return err;
f9cf2288
JK
6645}
6646
5ce76d78
JK
6647const struct devlink_gen_cmd devl_gen_info = {
6648 .dump_one = devlink_nl_cmd_info_get_dump_one,
6649};
6650
1db64e87
EBE
6651struct devlink_fmsg_item {
6652 struct list_head list;
6653 int attrtype;
6654 u8 nla_type;
6655 u16 len;
d2afb41a 6656 int value[];
1db64e87
EBE
6657};
6658
6659struct devlink_fmsg {
6660 struct list_head item_list;
573ed90a
AL
6661 bool putting_binary; /* This flag forces enclosing of binary data
6662 * in an array brackets. It forces using
6663 * of designated API:
6664 * devlink_fmsg_binary_pair_nest_start()
6665 * devlink_fmsg_binary_pair_nest_end()
6666 */
1db64e87
EBE
6667};
6668
6669static struct devlink_fmsg *devlink_fmsg_alloc(void)
6670{
6671 struct devlink_fmsg *fmsg;
6672
6673 fmsg = kzalloc(sizeof(*fmsg), GFP_KERNEL);
6674 if (!fmsg)
6675 return NULL;
6676
6677 INIT_LIST_HEAD(&fmsg->item_list);
6678
6679 return fmsg;
6680}
6681
6682static void devlink_fmsg_free(struct devlink_fmsg *fmsg)
6683{
6684 struct devlink_fmsg_item *item, *tmp;
6685
6686 list_for_each_entry_safe(item, tmp, &fmsg->item_list, list) {
6687 list_del(&item->list);
6688 kfree(item);
6689 }
6690 kfree(fmsg);
6691}
6692
6693static int devlink_fmsg_nest_common(struct devlink_fmsg *fmsg,
6694 int attrtype)
6695{
6696 struct devlink_fmsg_item *item;
6697
6698 item = kzalloc(sizeof(*item), GFP_KERNEL);
6699 if (!item)
6700 return -ENOMEM;
6701
6702 item->attrtype = attrtype;
6703 list_add_tail(&item->list, &fmsg->item_list);
6704
6705 return 0;
6706}
6707
6708int devlink_fmsg_obj_nest_start(struct devlink_fmsg *fmsg)
6709{
573ed90a
AL
6710 if (fmsg->putting_binary)
6711 return -EINVAL;
6712
1db64e87
EBE
6713 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_OBJ_NEST_START);
6714}
6715EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_start);
6716
6717static int devlink_fmsg_nest_end(struct devlink_fmsg *fmsg)
6718{
573ed90a
AL
6719 if (fmsg->putting_binary)
6720 return -EINVAL;
6721
1db64e87
EBE
6722 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_NEST_END);
6723}
6724
6725int devlink_fmsg_obj_nest_end(struct devlink_fmsg *fmsg)
6726{
573ed90a
AL
6727 if (fmsg->putting_binary)
6728 return -EINVAL;
6729
1db64e87
EBE
6730 return devlink_fmsg_nest_end(fmsg);
6731}
6732EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_end);
6733
6734#define DEVLINK_FMSG_MAX_SIZE (GENLMSG_DEFAULT_SIZE - GENL_HDRLEN - NLA_HDRLEN)
6735
6736static int devlink_fmsg_put_name(struct devlink_fmsg *fmsg, const char *name)
6737{
6738 struct devlink_fmsg_item *item;
6739
573ed90a
AL
6740 if (fmsg->putting_binary)
6741 return -EINVAL;
6742
1db64e87
EBE
6743 if (strlen(name) + 1 > DEVLINK_FMSG_MAX_SIZE)
6744 return -EMSGSIZE;
6745
6746 item = kzalloc(sizeof(*item) + strlen(name) + 1, GFP_KERNEL);
6747 if (!item)
6748 return -ENOMEM;
6749
6750 item->nla_type = NLA_NUL_STRING;
6751 item->len = strlen(name) + 1;
6752 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_NAME;
6753 memcpy(&item->value, name, item->len);
6754 list_add_tail(&item->list, &fmsg->item_list);
6755
6756 return 0;
6757}
6758
6759int devlink_fmsg_pair_nest_start(struct devlink_fmsg *fmsg, const char *name)
6760{
6761 int err;
6762
573ed90a
AL
6763 if (fmsg->putting_binary)
6764 return -EINVAL;
6765
1db64e87
EBE
6766 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_PAIR_NEST_START);
6767 if (err)
6768 return err;
6769
6770 err = devlink_fmsg_put_name(fmsg, name);
6771 if (err)
6772 return err;
6773
6774 return 0;
6775}
6776EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_start);
6777
6778int devlink_fmsg_pair_nest_end(struct devlink_fmsg *fmsg)
6779{
573ed90a
AL
6780 if (fmsg->putting_binary)
6781 return -EINVAL;
6782
1db64e87
EBE
6783 return devlink_fmsg_nest_end(fmsg);
6784}
6785EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_end);
6786
6787int devlink_fmsg_arr_pair_nest_start(struct devlink_fmsg *fmsg,
6788 const char *name)
6789{
6790 int err;
6791
573ed90a
AL
6792 if (fmsg->putting_binary)
6793 return -EINVAL;
6794
1db64e87
EBE
6795 err = devlink_fmsg_pair_nest_start(fmsg, name);
6796 if (err)
6797 return err;
6798
6799 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_ARR_NEST_START);
6800 if (err)
6801 return err;
6802
6803 return 0;
6804}
6805EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_start);
6806
6807int devlink_fmsg_arr_pair_nest_end(struct devlink_fmsg *fmsg)
6808{
6809 int err;
6810
573ed90a
AL
6811 if (fmsg->putting_binary)
6812 return -EINVAL;
6813
1db64e87
EBE
6814 err = devlink_fmsg_nest_end(fmsg);
6815 if (err)
6816 return err;
6817
6818 err = devlink_fmsg_nest_end(fmsg);
6819 if (err)
6820 return err;
6821
6822 return 0;
6823}
6824EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_end);
6825
573ed90a
AL
6826int devlink_fmsg_binary_pair_nest_start(struct devlink_fmsg *fmsg,
6827 const char *name)
6828{
6829 int err;
6830
6831 err = devlink_fmsg_arr_pair_nest_start(fmsg, name);
6832 if (err)
6833 return err;
6834
6835 fmsg->putting_binary = true;
6836 return err;
6837}
6838EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_nest_start);
6839
6840int devlink_fmsg_binary_pair_nest_end(struct devlink_fmsg *fmsg)
6841{
6842 if (!fmsg->putting_binary)
6843 return -EINVAL;
6844
6845 fmsg->putting_binary = false;
6846 return devlink_fmsg_arr_pair_nest_end(fmsg);
6847}
6848EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_nest_end);
6849
1db64e87
EBE
6850static int devlink_fmsg_put_value(struct devlink_fmsg *fmsg,
6851 const void *value, u16 value_len,
6852 u8 value_nla_type)
6853{
6854 struct devlink_fmsg_item *item;
6855
6856 if (value_len > DEVLINK_FMSG_MAX_SIZE)
6857 return -EMSGSIZE;
6858
6859 item = kzalloc(sizeof(*item) + value_len, GFP_KERNEL);
6860 if (!item)
6861 return -ENOMEM;
6862
6863 item->nla_type = value_nla_type;
6864 item->len = value_len;
6865 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
6866 memcpy(&item->value, value, item->len);
6867 list_add_tail(&item->list, &fmsg->item_list);
6868
6869 return 0;
6870}
6871
6db9350a 6872static int devlink_fmsg_bool_put(struct devlink_fmsg *fmsg, bool value)
1db64e87 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_FLAG);
6878}
1db64e87 6879
6db9350a 6880static int devlink_fmsg_u8_put(struct devlink_fmsg *fmsg, u8 value)
1db64e87 6881{
573ed90a
AL
6882 if (fmsg->putting_binary)
6883 return -EINVAL;
6884
1db64e87
EBE
6885 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U8);
6886}
1db64e87
EBE
6887
6888int devlink_fmsg_u32_put(struct devlink_fmsg *fmsg, u32 value)
6889{
573ed90a
AL
6890 if (fmsg->putting_binary)
6891 return -EINVAL;
6892
1db64e87
EBE
6893 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U32);
6894}
6895EXPORT_SYMBOL_GPL(devlink_fmsg_u32_put);
6896
6db9350a 6897static int devlink_fmsg_u64_put(struct devlink_fmsg *fmsg, u64 value)
1db64e87 6898{
573ed90a
AL
6899 if (fmsg->putting_binary)
6900 return -EINVAL;
6901
1db64e87
EBE
6902 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U64);
6903}
1db64e87
EBE
6904
6905int devlink_fmsg_string_put(struct devlink_fmsg *fmsg, const char *value)
6906{
573ed90a
AL
6907 if (fmsg->putting_binary)
6908 return -EINVAL;
6909
1db64e87
EBE
6910 return devlink_fmsg_put_value(fmsg, value, strlen(value) + 1,
6911 NLA_NUL_STRING);
6912}
6913EXPORT_SYMBOL_GPL(devlink_fmsg_string_put);
6914
573ed90a
AL
6915int devlink_fmsg_binary_put(struct devlink_fmsg *fmsg, const void *value,
6916 u16 value_len)
1db64e87 6917{
573ed90a
AL
6918 if (!fmsg->putting_binary)
6919 return -EINVAL;
6920
1db64e87
EBE
6921 return devlink_fmsg_put_value(fmsg, value, value_len, NLA_BINARY);
6922}
573ed90a 6923EXPORT_SYMBOL_GPL(devlink_fmsg_binary_put);
1db64e87
EBE
6924
6925int devlink_fmsg_bool_pair_put(struct devlink_fmsg *fmsg, const char *name,
6926 bool value)
6927{
6928 int err;
6929
6930 err = devlink_fmsg_pair_nest_start(fmsg, name);
6931 if (err)
6932 return err;
6933
6934 err = devlink_fmsg_bool_put(fmsg, value);
6935 if (err)
6936 return err;
6937
6938 err = devlink_fmsg_pair_nest_end(fmsg);
6939 if (err)
6940 return err;
6941
6942 return 0;
6943}
6944EXPORT_SYMBOL_GPL(devlink_fmsg_bool_pair_put);
6945
6946int devlink_fmsg_u8_pair_put(struct devlink_fmsg *fmsg, const char *name,
6947 u8 value)
6948{
6949 int err;
6950
6951 err = devlink_fmsg_pair_nest_start(fmsg, name);
6952 if (err)
6953 return err;
6954
6955 err = devlink_fmsg_u8_put(fmsg, value);
6956 if (err)
6957 return err;
6958
6959 err = devlink_fmsg_pair_nest_end(fmsg);
6960 if (err)
6961 return err;
6962
6963 return 0;
6964}
6965EXPORT_SYMBOL_GPL(devlink_fmsg_u8_pair_put);
6966
6967int devlink_fmsg_u32_pair_put(struct devlink_fmsg *fmsg, const char *name,
6968 u32 value)
6969{
6970 int err;
6971
6972 err = devlink_fmsg_pair_nest_start(fmsg, name);
6973 if (err)
6974 return err;
6975
6976 err = devlink_fmsg_u32_put(fmsg, value);
6977 if (err)
6978 return err;
6979
6980 err = devlink_fmsg_pair_nest_end(fmsg);
6981 if (err)
6982 return err;
6983
6984 return 0;
6985}
6986EXPORT_SYMBOL_GPL(devlink_fmsg_u32_pair_put);
6987
6988int devlink_fmsg_u64_pair_put(struct devlink_fmsg *fmsg, const char *name,
6989 u64 value)
6990{
6991 int err;
6992
6993 err = devlink_fmsg_pair_nest_start(fmsg, name);
6994 if (err)
6995 return err;
6996
6997 err = devlink_fmsg_u64_put(fmsg, value);
6998 if (err)
6999 return err;
7000
7001 err = devlink_fmsg_pair_nest_end(fmsg);
7002 if (err)
7003 return err;
7004
7005 return 0;
7006}
7007EXPORT_SYMBOL_GPL(devlink_fmsg_u64_pair_put);
7008
7009int devlink_fmsg_string_pair_put(struct devlink_fmsg *fmsg, const char *name,
7010 const char *value)
7011{
7012 int err;
7013
7014 err = devlink_fmsg_pair_nest_start(fmsg, name);
7015 if (err)
7016 return err;
7017
7018 err = devlink_fmsg_string_put(fmsg, value);
7019 if (err)
7020 return err;
7021
7022 err = devlink_fmsg_pair_nest_end(fmsg);
7023 if (err)
7024 return err;
7025
7026 return 0;
7027}
7028EXPORT_SYMBOL_GPL(devlink_fmsg_string_pair_put);
7029
7030int devlink_fmsg_binary_pair_put(struct devlink_fmsg *fmsg, const char *name,
e2cde864 7031 const void *value, u32 value_len)
1db64e87 7032{
e2cde864 7033 u32 data_size;
573ed90a 7034 int end_err;
e2cde864 7035 u32 offset;
1db64e87
EBE
7036 int err;
7037
573ed90a 7038 err = devlink_fmsg_binary_pair_nest_start(fmsg, name);
1db64e87
EBE
7039 if (err)
7040 return err;
7041
e2cde864
AL
7042 for (offset = 0; offset < value_len; offset += data_size) {
7043 data_size = value_len - offset;
7044 if (data_size > DEVLINK_FMSG_MAX_SIZE)
7045 data_size = DEVLINK_FMSG_MAX_SIZE;
7046 err = devlink_fmsg_binary_put(fmsg, value + offset, data_size);
7047 if (err)
573ed90a
AL
7048 break;
7049 /* Exit from loop with a break (instead of
7050 * return) to make sure putting_binary is turned off in
7051 * devlink_fmsg_binary_pair_nest_end
7052 */
e2cde864 7053 }
1db64e87 7054
573ed90a
AL
7055 end_err = devlink_fmsg_binary_pair_nest_end(fmsg);
7056 if (end_err)
7057 err = end_err;
1db64e87 7058
573ed90a 7059 return err;
1db64e87
EBE
7060}
7061EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_put);
7062
7063static int
7064devlink_fmsg_item_fill_type(struct devlink_fmsg_item *msg, struct sk_buff *skb)
7065{
7066 switch (msg->nla_type) {
7067 case NLA_FLAG:
7068 case NLA_U8:
7069 case NLA_U32:
7070 case NLA_U64:
7071 case NLA_NUL_STRING:
7072 case NLA_BINARY:
7073 return nla_put_u8(skb, DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE,
7074 msg->nla_type);
7075 default:
7076 return -EINVAL;
7077 }
7078}
7079
7080static int
7081devlink_fmsg_item_fill_data(struct devlink_fmsg_item *msg, struct sk_buff *skb)
7082{
7083 int attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
7084 u8 tmp;
7085
7086 switch (msg->nla_type) {
7087 case NLA_FLAG:
7088 /* Always provide flag data, regardless of its value */
7089 tmp = *(bool *) msg->value;
7090
7091 return nla_put_u8(skb, attrtype, tmp);
7092 case NLA_U8:
7093 return nla_put_u8(skb, attrtype, *(u8 *) msg->value);
7094 case NLA_U32:
7095 return nla_put_u32(skb, attrtype, *(u32 *) msg->value);
7096 case NLA_U64:
7097 return nla_put_u64_64bit(skb, attrtype, *(u64 *) msg->value,
7098 DEVLINK_ATTR_PAD);
7099 case NLA_NUL_STRING:
7100 return nla_put_string(skb, attrtype, (char *) &msg->value);
7101 case NLA_BINARY:
7102 return nla_put(skb, attrtype, msg->len, (void *) &msg->value);
7103 default:
7104 return -EINVAL;
7105 }
7106}
7107
7108static int
7109devlink_fmsg_prepare_skb(struct devlink_fmsg *fmsg, struct sk_buff *skb,
7110 int *start)
7111{
7112 struct devlink_fmsg_item *item;
7113 struct nlattr *fmsg_nlattr;
4373a023 7114 int err = 0;
1db64e87 7115 int i = 0;
1db64e87 7116
ae0be8de 7117 fmsg_nlattr = nla_nest_start_noflag(skb, DEVLINK_ATTR_FMSG);
1db64e87
EBE
7118 if (!fmsg_nlattr)
7119 return -EMSGSIZE;
7120
7121 list_for_each_entry(item, &fmsg->item_list, list) {
7122 if (i < *start) {
7123 i++;
7124 continue;
7125 }
7126
7127 switch (item->attrtype) {
7128 case DEVLINK_ATTR_FMSG_OBJ_NEST_START:
7129 case DEVLINK_ATTR_FMSG_PAIR_NEST_START:
7130 case DEVLINK_ATTR_FMSG_ARR_NEST_START:
7131 case DEVLINK_ATTR_FMSG_NEST_END:
7132 err = nla_put_flag(skb, item->attrtype);
7133 break;
7134 case DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA:
7135 err = devlink_fmsg_item_fill_type(item, skb);
7136 if (err)
7137 break;
7138 err = devlink_fmsg_item_fill_data(item, skb);
7139 break;
7140 case DEVLINK_ATTR_FMSG_OBJ_NAME:
7141 err = nla_put_string(skb, item->attrtype,
7142 (char *) &item->value);
7143 break;
7144 default:
7145 err = -EINVAL;
7146 break;
7147 }
7148 if (!err)
7149 *start = ++i;
7150 else
7151 break;
7152 }
7153
7154 nla_nest_end(skb, fmsg_nlattr);
7155 return err;
7156}
7157
7158static int devlink_fmsg_snd(struct devlink_fmsg *fmsg,
7159 struct genl_info *info,
7160 enum devlink_command cmd, int flags)
7161{
7162 struct nlmsghdr *nlh;
7163 struct sk_buff *skb;
7164 bool last = false;
7165 int index = 0;
7166 void *hdr;
7167 int err;
7168
7169 while (!last) {
7170 int tmp_index = index;
7171
7172 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
7173 if (!skb)
7174 return -ENOMEM;
7175
7176 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
7177 &devlink_nl_family, flags | NLM_F_MULTI, cmd);
7178 if (!hdr) {
7179 err = -EMSGSIZE;
7180 goto nla_put_failure;
7181 }
7182
7183 err = devlink_fmsg_prepare_skb(fmsg, skb, &index);
7184 if (!err)
7185 last = true;
7186 else if (err != -EMSGSIZE || tmp_index == index)
7187 goto nla_put_failure;
7188
7189 genlmsg_end(skb, hdr);
7190 err = genlmsg_reply(skb, info);
7191 if (err)
7192 return err;
7193 }
7194
7195 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
7196 if (!skb)
7197 return -ENOMEM;
7198 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
7199 NLMSG_DONE, 0, flags | NLM_F_MULTI);
7200 if (!nlh) {
7201 err = -EMSGSIZE;
7202 goto nla_put_failure;
7203 }
1db64e87 7204
fde55ea7 7205 return genlmsg_reply(skb, info);
1db64e87
EBE
7206
7207nla_put_failure:
7208 nlmsg_free(skb);
7209 return err;
7210}
7211
e44ef4e4
AL
7212static int devlink_fmsg_dumpit(struct devlink_fmsg *fmsg, struct sk_buff *skb,
7213 struct netlink_callback *cb,
7214 enum devlink_command cmd)
7215{
3015f822
JK
7216 struct devlink_nl_dump_state *state = devlink_dump_state(cb);
7217 int index = state->idx;
e44ef4e4
AL
7218 int tmp_index = index;
7219 void *hdr;
7220 int err;
7221
7222 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
7223 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, cmd);
7224 if (!hdr) {
7225 err = -EMSGSIZE;
7226 goto nla_put_failure;
7227 }
7228
7229 err = devlink_fmsg_prepare_skb(fmsg, skb, &index);
7230 if ((err && err != -EMSGSIZE) || tmp_index == index)
7231 goto nla_put_failure;
7232
3015f822 7233 state->idx = index;
e44ef4e4
AL
7234 genlmsg_end(skb, hdr);
7235 return skb->len;
7236
7237nla_put_failure:
7238 genlmsg_cancel(skb, hdr);
7239 return err;
7240}
7241
a0bdcc59
EBE
7242struct devlink_health_reporter {
7243 struct list_head list;
7244 void *priv;
7245 const struct devlink_health_reporter_ops *ops;
7246 struct devlink *devlink;
f4f54166 7247 struct devlink_port *devlink_port;
c8e1da0b
EBE
7248 struct devlink_fmsg *dump_fmsg;
7249 struct mutex dump_lock; /* lock parallel read/write from dump buffers */
a0bdcc59
EBE
7250 u64 graceful_period;
7251 bool auto_recover;
48bb52c8 7252 bool auto_dump;
a0bdcc59 7253 u8 health_state;
c8e1da0b 7254 u64 dump_ts;
d279505b 7255 u64 dump_real_ts;
c8e1da0b
EBE
7256 u64 error_count;
7257 u64 recovery_count;
7258 u64 last_recovery_ts;
7259};
7260
a0bdcc59
EBE
7261void *
7262devlink_health_reporter_priv(struct devlink_health_reporter *reporter)
7263{
7264 return reporter->priv;
7265}
7266EXPORT_SYMBOL_GPL(devlink_health_reporter_priv);
7267
7268static struct devlink_health_reporter *
bd821005 7269__devlink_health_reporter_find_by_name(struct list_head *reporter_list,
bd821005 7270 const char *reporter_name)
a0bdcc59
EBE
7271{
7272 struct devlink_health_reporter *reporter;
7273
bd821005 7274 list_for_each_entry(reporter, reporter_list, list)
a0bdcc59
EBE
7275 if (!strcmp(reporter->ops->name, reporter_name))
7276 return reporter;
7277 return NULL;
7278}
7279
bd821005
VT
7280static struct devlink_health_reporter *
7281devlink_health_reporter_find_by_name(struct devlink *devlink,
7282 const char *reporter_name)
7283{
7284 return __devlink_health_reporter_find_by_name(&devlink->reporter_list,
bd821005
VT
7285 reporter_name);
7286}
7287
f4f54166
VT
7288static struct devlink_health_reporter *
7289devlink_port_health_reporter_find_by_name(struct devlink_port *devlink_port,
7290 const char *reporter_name)
7291{
7292 return __devlink_health_reporter_find_by_name(&devlink_port->reporter_list,
f4f54166
VT
7293 reporter_name);
7294}
7295
c57544b3
VT
7296static struct devlink_health_reporter *
7297__devlink_health_reporter_create(struct devlink *devlink,
7298 const struct devlink_health_reporter_ops *ops,
7299 u64 graceful_period, void *priv)
7300{
7301 struct devlink_health_reporter *reporter;
7302
7303 if (WARN_ON(graceful_period && !ops->recover))
7304 return ERR_PTR(-EINVAL);
7305
7306 reporter = kzalloc(sizeof(*reporter), GFP_KERNEL);
7307 if (!reporter)
7308 return ERR_PTR(-ENOMEM);
7309
7310 reporter->priv = priv;
7311 reporter->ops = ops;
7312 reporter->devlink = devlink;
7313 reporter->graceful_period = graceful_period;
7314 reporter->auto_recover = !!ops->recover;
7315 reporter->auto_dump = !!ops->dump;
7316 mutex_init(&reporter->dump_lock);
c57544b3
VT
7317 return reporter;
7318}
7319
15c724b9 7320/**
dfdfd130
JP
7321 * devl_port_health_reporter_create - create devlink health reporter for
7322 * specified port instance
15c724b9
VT
7323 *
7324 * @port: devlink_port which should contain the new reporter
7325 * @ops: ops
7326 * @graceful_period: to avoid recovery loops, in msecs
7327 * @priv: priv
7328 */
7329struct devlink_health_reporter *
dfdfd130
JP
7330devl_port_health_reporter_create(struct devlink_port *port,
7331 const struct devlink_health_reporter_ops *ops,
7332 u64 graceful_period, void *priv)
15c724b9
VT
7333{
7334 struct devlink_health_reporter *reporter;
7335
dfdfd130 7336 devl_assert_locked(port->devlink);
1dea3b4e 7337
15c724b9 7338 if (__devlink_health_reporter_find_by_name(&port->reporter_list,
1dea3b4e
JP
7339 ops->name))
7340 return ERR_PTR(-EEXIST);
15c724b9
VT
7341
7342 reporter = __devlink_health_reporter_create(port->devlink, ops,
7343 graceful_period, priv);
7344 if (IS_ERR(reporter))
1dea3b4e 7345 return reporter;
15c724b9
VT
7346
7347 reporter->devlink_port = port;
7348 list_add_tail(&reporter->list, &port->reporter_list);
15c724b9
VT
7349 return reporter;
7350}
dfdfd130
JP
7351EXPORT_SYMBOL_GPL(devl_port_health_reporter_create);
7352
7353struct devlink_health_reporter *
7354devlink_port_health_reporter_create(struct devlink_port *port,
7355 const struct devlink_health_reporter_ops *ops,
7356 u64 graceful_period, void *priv)
7357{
7358 struct devlink_health_reporter *reporter;
7359 struct devlink *devlink = port->devlink;
7360
7361 devl_lock(devlink);
7362 reporter = devl_port_health_reporter_create(port, ops,
7363 graceful_period, priv);
7364 devl_unlock(devlink);
7365 return reporter;
7366}
15c724b9
VT
7367EXPORT_SYMBOL_GPL(devlink_port_health_reporter_create);
7368
a0bdcc59 7369/**
dfdfd130 7370 * devl_health_reporter_create - create devlink health reporter
a0bdcc59
EBE
7371 *
7372 * @devlink: devlink
7373 * @ops: ops
7374 * @graceful_period: to avoid recovery loops, in msecs
a0bdcc59
EBE
7375 * @priv: priv
7376 */
7377struct devlink_health_reporter *
dfdfd130
JP
7378devl_health_reporter_create(struct devlink *devlink,
7379 const struct devlink_health_reporter_ops *ops,
7380 u64 graceful_period, void *priv)
a0bdcc59
EBE
7381{
7382 struct devlink_health_reporter *reporter;
7383
dfdfd130 7384 devl_assert_locked(devlink);
1dea3b4e
JP
7385
7386 if (devlink_health_reporter_find_by_name(devlink, ops->name))
7387 return ERR_PTR(-EEXIST);
a0bdcc59 7388
c57544b3
VT
7389 reporter = __devlink_health_reporter_create(devlink, ops,
7390 graceful_period, priv);
7391 if (IS_ERR(reporter))
1dea3b4e 7392 return reporter;
a0bdcc59 7393
a0bdcc59 7394 list_add_tail(&reporter->list, &devlink->reporter_list);
a0bdcc59
EBE
7395 return reporter;
7396}
dfdfd130
JP
7397EXPORT_SYMBOL_GPL(devl_health_reporter_create);
7398
7399struct devlink_health_reporter *
7400devlink_health_reporter_create(struct devlink *devlink,
7401 const struct devlink_health_reporter_ops *ops,
7402 u64 graceful_period, void *priv)
7403{
7404 struct devlink_health_reporter *reporter;
7405
7406 devl_lock(devlink);
7407 reporter = devl_health_reporter_create(devlink, ops,
7408 graceful_period, priv);
7409 devl_unlock(devlink);
7410 return reporter;
7411}
a0bdcc59
EBE
7412EXPORT_SYMBOL_GPL(devlink_health_reporter_create);
7413
3c5584bf
VT
7414static void
7415devlink_health_reporter_free(struct devlink_health_reporter *reporter)
7416{
7417 mutex_destroy(&reporter->dump_lock);
7418 if (reporter->dump_fmsg)
7419 devlink_fmsg_free(reporter->dump_fmsg);
7420 kfree(reporter);
7421}
7422
a0bdcc59 7423/**
dfdfd130 7424 * devl_health_reporter_destroy - destroy devlink health reporter
a0bdcc59
EBE
7425 *
7426 * @reporter: devlink health reporter to destroy
7427 */
7428void
dfdfd130 7429devl_health_reporter_destroy(struct devlink_health_reporter *reporter)
a0bdcc59 7430{
dfdfd130
JP
7431 devl_assert_locked(reporter->devlink);
7432
9f167327 7433 list_del(&reporter->list);
e994a75f 7434 devlink_health_reporter_free(reporter);
a0bdcc59 7435}
dfdfd130
JP
7436EXPORT_SYMBOL_GPL(devl_health_reporter_destroy);
7437
7438void
7439devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
7440{
7441 struct devlink *devlink = reporter->devlink;
7442
7443 devl_lock(devlink);
7444 devl_health_reporter_destroy(reporter);
7445 devl_unlock(devlink);
7446}
a0bdcc59
EBE
7447EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
7448
6ec8b6cd
MS
7449static int
7450devlink_nl_health_reporter_fill(struct sk_buff *msg,
6ec8b6cd
MS
7451 struct devlink_health_reporter *reporter,
7452 enum devlink_command cmd, u32 portid,
7453 u32 seq, int flags)
7454{
7ca973dc 7455 struct devlink *devlink = reporter->devlink;
6ec8b6cd
MS
7456 struct nlattr *reporter_attr;
7457 void *hdr;
7458
7459 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
7460 if (!hdr)
7461 return -EMSGSIZE;
7462
7463 if (devlink_nl_put_handle(msg, devlink))
7464 goto genlmsg_cancel;
7465
f4f54166
VT
7466 if (reporter->devlink_port) {
7467 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, reporter->devlink_port->index))
7468 goto genlmsg_cancel;
7469 }
6ec8b6cd
MS
7470 reporter_attr = nla_nest_start_noflag(msg,
7471 DEVLINK_ATTR_HEALTH_REPORTER);
7472 if (!reporter_attr)
7473 goto genlmsg_cancel;
7474 if (nla_put_string(msg, DEVLINK_ATTR_HEALTH_REPORTER_NAME,
7475 reporter->ops->name))
7476 goto reporter_nest_cancel;
7477 if (nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_STATE,
7478 reporter->health_state))
7479 goto reporter_nest_cancel;
7480 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_ERR_COUNT,
7481 reporter->error_count, DEVLINK_ATTR_PAD))
7482 goto reporter_nest_cancel;
7483 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_RECOVER_COUNT,
7484 reporter->recovery_count, DEVLINK_ATTR_PAD))
7485 goto reporter_nest_cancel;
7486 if (reporter->ops->recover &&
7487 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD,
7488 reporter->graceful_period,
7489 DEVLINK_ATTR_PAD))
7490 goto reporter_nest_cancel;
7491 if (reporter->ops->recover &&
7492 nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER,
7493 reporter->auto_recover))
7494 goto reporter_nest_cancel;
7495 if (reporter->dump_fmsg &&
7496 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS,
7497 jiffies_to_msecs(reporter->dump_ts),
7498 DEVLINK_ATTR_PAD))
7499 goto reporter_nest_cancel;
7500 if (reporter->dump_fmsg &&
7501 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS_NS,
7502 reporter->dump_real_ts, DEVLINK_ATTR_PAD))
7503 goto reporter_nest_cancel;
48bb52c8
EBE
7504 if (reporter->ops->dump &&
7505 nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP,
7506 reporter->auto_dump))
7507 goto reporter_nest_cancel;
6ec8b6cd
MS
7508
7509 nla_nest_end(msg, reporter_attr);
7510 genlmsg_end(msg, hdr);
7511 return 0;
7512
7513reporter_nest_cancel:
7514 nla_nest_end(msg, reporter_attr);
7515genlmsg_cancel:
7516 genlmsg_cancel(msg, hdr);
7517 return -EMSGSIZE;
7518}
7519
7520static void devlink_recover_notify(struct devlink_health_reporter *reporter,
7521 enum devlink_command cmd)
7522{
cf530217 7523 struct devlink *devlink = reporter->devlink;
6ec8b6cd
MS
7524 struct sk_buff *msg;
7525 int err;
7526
7527 WARN_ON(cmd != DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
cf530217 7528 WARN_ON(!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED));
6ec8b6cd
MS
7529
7530 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
7531 if (!msg)
7532 return;
7533
7ca973dc 7534 err = devlink_nl_health_reporter_fill(msg, reporter, cmd, 0, 0, 0);
6ec8b6cd
MS
7535 if (err) {
7536 nlmsg_free(msg);
7537 return;
7538 }
7539
cf530217
LR
7540 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), msg,
7541 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
6ec8b6cd
MS
7542}
7543
6181e5cb
VG
7544void
7545devlink_health_reporter_recovery_done(struct devlink_health_reporter *reporter)
7546{
7547 reporter->recovery_count++;
7548 reporter->last_recovery_ts = jiffies;
7549}
7550EXPORT_SYMBOL_GPL(devlink_health_reporter_recovery_done);
7551
c8e1da0b
EBE
7552static int
7553devlink_health_reporter_recover(struct devlink_health_reporter *reporter,
e7a98105 7554 void *priv_ctx, struct netlink_ext_ack *extack)
c8e1da0b
EBE
7555{
7556 int err;
7557
40281820
JP
7558 if (reporter->health_state == DEVLINK_HEALTH_REPORTER_STATE_HEALTHY)
7559 return 0;
7560
c8e1da0b
EBE
7561 if (!reporter->ops->recover)
7562 return -EOPNOTSUPP;
7563
e7a98105 7564 err = reporter->ops->recover(reporter, priv_ctx, extack);
c8e1da0b
EBE
7565 if (err)
7566 return err;
7567
6181e5cb 7568 devlink_health_reporter_recovery_done(reporter);
c8e1da0b 7569 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY;
6ec8b6cd 7570 devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
c8e1da0b
EBE
7571
7572 return 0;
7573}
7574
7575static void
7576devlink_health_dump_clear(struct devlink_health_reporter *reporter)
7577{
7578 if (!reporter->dump_fmsg)
7579 return;
7580 devlink_fmsg_free(reporter->dump_fmsg);
7581 reporter->dump_fmsg = NULL;
7582}
7583
7584static int devlink_health_do_dump(struct devlink_health_reporter *reporter,
e7a98105
JP
7585 void *priv_ctx,
7586 struct netlink_ext_ack *extack)
c8e1da0b
EBE
7587{
7588 int err;
7589
7590 if (!reporter->ops->dump)
7591 return 0;
7592
7593 if (reporter->dump_fmsg)
7594 return 0;
7595
7596 reporter->dump_fmsg = devlink_fmsg_alloc();
7597 if (!reporter->dump_fmsg) {
7598 err = -ENOMEM;
7599 return err;
7600 }
7601
7602 err = devlink_fmsg_obj_nest_start(reporter->dump_fmsg);
7603 if (err)
7604 goto dump_err;
7605
7606 err = reporter->ops->dump(reporter, reporter->dump_fmsg,
e7a98105 7607 priv_ctx, extack);
c8e1da0b
EBE
7608 if (err)
7609 goto dump_err;
7610
7611 err = devlink_fmsg_obj_nest_end(reporter->dump_fmsg);
7612 if (err)
7613 goto dump_err;
7614
7615 reporter->dump_ts = jiffies;
d279505b 7616 reporter->dump_real_ts = ktime_get_real_ns();
c8e1da0b
EBE
7617
7618 return 0;
7619
7620dump_err:
7621 devlink_health_dump_clear(reporter);
7622 return err;
7623}
7624
7625int devlink_health_report(struct devlink_health_reporter *reporter,
7626 const char *msg, void *priv_ctx)
7627{
a0a21adb 7628 enum devlink_health_reporter_state prev_health_state;
c8e1da0b 7629 struct devlink *devlink = reporter->devlink;
bea0c5c9 7630 unsigned long recover_ts_threshold;
c90005b5 7631 int ret;
c8e1da0b
EBE
7632
7633 /* write a log message of the current error */
7634 WARN_ON(!msg);
7635 trace_devlink_health_report(devlink, reporter->ops->name, msg);
7636 reporter->error_count++;
a0a21adb
EBE
7637 prev_health_state = reporter->health_state;
7638 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
6ec8b6cd 7639 devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
c8e1da0b
EBE
7640
7641 /* abort if the previous error wasn't recovered */
bea0c5c9
AL
7642 recover_ts_threshold = reporter->last_recovery_ts +
7643 msecs_to_jiffies(reporter->graceful_period);
c8e1da0b 7644 if (reporter->auto_recover &&
a0a21adb 7645 (prev_health_state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY ||
bea0c5c9
AL
7646 (reporter->last_recovery_ts && reporter->recovery_count &&
7647 time_is_after_jiffies(recover_ts_threshold)))) {
c8e1da0b
EBE
7648 trace_devlink_health_recover_aborted(devlink,
7649 reporter->ops->name,
7650 reporter->health_state,
7651 jiffies -
7652 reporter->last_recovery_ts);
7653 return -ECANCELED;
7654 }
7655
48bb52c8
EBE
7656 if (reporter->auto_dump) {
7657 mutex_lock(&reporter->dump_lock);
7658 /* store current dump of current error, for later analysis */
7659 devlink_health_do_dump(reporter, priv_ctx, NULL);
7660 mutex_unlock(&reporter->dump_lock);
7661 }
c8e1da0b 7662
c90005b5
MS
7663 if (!reporter->auto_recover)
7664 return 0;
c8e1da0b 7665
c90005b5
MS
7666 devl_lock(devlink);
7667 ret = devlink_health_reporter_recover(reporter, priv_ctx, NULL);
7668 devl_unlock(devlink);
7669
7670 return ret;
c8e1da0b
EBE
7671}
7672EXPORT_SYMBOL_GPL(devlink_health_report);
7673
7afe335a 7674static struct devlink_health_reporter *
e44ef4e4
AL
7675devlink_health_reporter_get_from_attrs(struct devlink *devlink,
7676 struct nlattr **attrs)
7afe335a 7677{
f4f54166 7678 struct devlink_port *devlink_port;
7afe335a
EBE
7679 char *reporter_name;
7680
e44ef4e4 7681 if (!attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME])
7afe335a
EBE
7682 return NULL;
7683
e44ef4e4 7684 reporter_name = nla_data(attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]);
f4f54166 7685 devlink_port = devlink_port_get_from_attrs(devlink, attrs);
e994a75f
JP
7686 if (IS_ERR(devlink_port))
7687 return devlink_health_reporter_find_by_name(devlink,
7688 reporter_name);
7689 else
7690 return devlink_port_health_reporter_find_by_name(devlink_port,
7691 reporter_name);
b587bdaf
MS
7692}
7693
e44ef4e4
AL
7694static struct devlink_health_reporter *
7695devlink_health_reporter_get_from_info(struct devlink *devlink,
7696 struct genl_info *info)
7697{
7698 return devlink_health_reporter_get_from_attrs(devlink, info->attrs);
7699}
7700
7701static struct devlink_health_reporter *
7702devlink_health_reporter_get_from_cb(struct netlink_callback *cb)
7703{
ee85da53 7704 const struct genl_dumpit_info *info = genl_dumpit_info(cb);
e44ef4e4 7705 struct devlink_health_reporter *reporter;
ee85da53 7706 struct nlattr **attrs = info->attrs;
e44ef4e4 7707 struct devlink *devlink;
e44ef4e4 7708
870c7ad4 7709 devlink = devlink_get_from_attrs_lock(sock_net(cb->skb->sk), attrs);
e44ef4e4 7710 if (IS_ERR(devlink))
d3efc2a6 7711 return NULL;
870c7ad4 7712 devl_unlock(devlink);
e44ef4e4
AL
7713
7714 reporter = devlink_health_reporter_get_from_attrs(devlink, attrs);
437ebfd9 7715 devlink_put(devlink);
e44ef4e4 7716 return reporter;
e44ef4e4
AL
7717}
7718
97ff3bd3
VG
7719void
7720devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
7721 enum devlink_health_reporter_state state)
7722{
7723 if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY &&
7724 state != DEVLINK_HEALTH_REPORTER_STATE_ERROR))
7725 return;
7726
7727 if (reporter->health_state == state)
7728 return;
7729
7730 reporter->health_state = state;
7731 trace_devlink_health_reporter_state_update(reporter->devlink,
7732 reporter->ops->name, state);
7733 devlink_recover_notify(reporter, DEVLINK_CMD_HEALTH_REPORTER_RECOVER);
7734}
7735EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update);
7736
7afe335a
EBE
7737static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb,
7738 struct genl_info *info)
7739{
7740 struct devlink *devlink = info->user_ptr[0];
7741 struct devlink_health_reporter *reporter;
7742 struct sk_buff *msg;
7743 int err;
7744
7745 reporter = devlink_health_reporter_get_from_info(devlink, info);
7746 if (!reporter)
7747 return -EINVAL;
7748
7749 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
e994a75f
JP
7750 if (!msg)
7751 return -ENOMEM;
7afe335a 7752
7ca973dc 7753 err = devlink_nl_health_reporter_fill(msg, reporter,
7afe335a
EBE
7754 DEVLINK_CMD_HEALTH_REPORTER_GET,
7755 info->snd_portid, info->snd_seq,
7756 0);
7757 if (err) {
7758 nlmsg_free(msg);
e994a75f 7759 return err;
7afe335a
EBE
7760 }
7761
e994a75f 7762 return genlmsg_reply(msg, info);
7afe335a
EBE
7763}
7764
7765static int
19be51a9
JP
7766devlink_nl_cmd_health_reporter_get_dump_one(struct sk_buff *msg,
7767 struct devlink *devlink,
7768 struct netlink_callback *cb)
7afe335a 7769{
3015f822 7770 struct devlink_nl_dump_state *state = devlink_dump_state(cb);
19be51a9
JP
7771 struct devlink_health_reporter *reporter;
7772 struct devlink_port *port;
7773 unsigned long port_index;
7774 int idx = 0;
7afe335a
EBE
7775 int err;
7776
19be51a9
JP
7777 list_for_each_entry(reporter, &devlink->reporter_list, list) {
7778 if (idx < state->idx) {
7779 idx++;
7780 continue;
7781 }
7782 err = devlink_nl_health_reporter_fill(msg, reporter,
7783 DEVLINK_CMD_HEALTH_REPORTER_GET,
7784 NETLINK_CB(cb->skb).portid,
7785 cb->nlh->nlmsg_seq,
7786 NLM_F_MULTI);
7787 if (err) {
7788 state->idx = idx;
7789 return err;
7790 }
7791 idx++;
7792 }
7793 xa_for_each(&devlink->ports, port_index, port) {
7794 list_for_each_entry(reporter, &port->reporter_list, list) {
20615659 7795 if (idx < state->idx) {
7afe335a
EBE
7796 idx++;
7797 continue;
7798 }
19be51a9
JP
7799 err = devlink_nl_health_reporter_fill(msg, reporter,
7800 DEVLINK_CMD_HEALTH_REPORTER_GET,
7801 NETLINK_CB(cb->skb).portid,
7802 cb->nlh->nlmsg_seq,
7803 NLM_F_MULTI);
7afe335a 7804 if (err) {
a8f94707 7805 state->idx = idx;
19be51a9 7806 return err;
7afe335a
EBE
7807 }
7808 idx++;
7809 }
f4f54166 7810 }
19be51a9
JP
7811
7812 return 0;
7afe335a
EBE
7813}
7814
19be51a9
JP
7815const struct devlink_gen_cmd devl_gen_health_reporter = {
7816 .dump_one = devlink_nl_cmd_health_reporter_get_dump_one,
7817};
7818
a1e55ec0
EBE
7819static int
7820devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb,
7821 struct genl_info *info)
7822{
7823 struct devlink *devlink = info->user_ptr[0];
7824 struct devlink_health_reporter *reporter;
7825
7826 reporter = devlink_health_reporter_get_from_info(devlink, info);
7827 if (!reporter)
7828 return -EINVAL;
7829
7830 if (!reporter->ops->recover &&
7831 (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] ||
e994a75f
JP
7832 info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]))
7833 return -EOPNOTSUPP;
7834
48bb52c8 7835 if (!reporter->ops->dump &&
e994a75f
JP
7836 info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP])
7837 return -EOPNOTSUPP;
a1e55ec0
EBE
7838
7839 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD])
7840 reporter->graceful_period =
7841 nla_get_u64(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]);
7842
7843 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])
7844 reporter->auto_recover =
7845 nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]);
7846
48bb52c8
EBE
7847 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP])
7848 reporter->auto_dump =
7849 nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP]);
7850
a1e55ec0
EBE
7851 return 0;
7852}
7853
20a0943a
EBE
7854static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb,
7855 struct genl_info *info)
7856{
7857 struct devlink *devlink = info->user_ptr[0];
7858 struct devlink_health_reporter *reporter;
7859
7860 reporter = devlink_health_reporter_get_from_info(devlink, info);
7861 if (!reporter)
7862 return -EINVAL;
7863
e994a75f 7864 return devlink_health_reporter_recover(reporter, NULL, info->extack);
20a0943a
EBE
7865}
7866
fca42a27
EBE
7867static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb,
7868 struct genl_info *info)
7869{
7870 struct devlink *devlink = info->user_ptr[0];
7871 struct devlink_health_reporter *reporter;
7872 struct devlink_fmsg *fmsg;
7873 int err;
7874
7875 reporter = devlink_health_reporter_get_from_info(devlink, info);
7876 if (!reporter)
7877 return -EINVAL;
7878
e994a75f 7879 if (!reporter->ops->diagnose)
fca42a27
EBE
7880 return -EOPNOTSUPP;
7881
7882 fmsg = devlink_fmsg_alloc();
e994a75f 7883 if (!fmsg)
fca42a27
EBE
7884 return -ENOMEM;
7885
7886 err = devlink_fmsg_obj_nest_start(fmsg);
7887 if (err)
e994a75f 7888 return err;
fca42a27 7889
e7a98105 7890 err = reporter->ops->diagnose(reporter, fmsg, info->extack);
fca42a27 7891 if (err)
e994a75f 7892 return err;
fca42a27
EBE
7893
7894 err = devlink_fmsg_obj_nest_end(fmsg);
7895 if (err)
e994a75f 7896 return err;
fca42a27 7897
e994a75f
JP
7898 return devlink_fmsg_snd(fmsg, info,
7899 DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 0);
fca42a27
EBE
7900}
7901
e44ef4e4
AL
7902static int
7903devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb,
7904 struct netlink_callback *cb)
35455e23 7905{
3015f822 7906 struct devlink_nl_dump_state *state = devlink_dump_state(cb);
35455e23
EBE
7907 struct devlink_health_reporter *reporter;
7908 int err;
7909
e44ef4e4 7910 reporter = devlink_health_reporter_get_from_cb(cb);
35455e23
EBE
7911 if (!reporter)
7912 return -EINVAL;
7913
e994a75f
JP
7914 if (!reporter->ops->dump)
7915 return -EOPNOTSUPP;
7916
35455e23 7917 mutex_lock(&reporter->dump_lock);
3015f822 7918 if (!state->idx) {
e7a98105 7919 err = devlink_health_do_dump(reporter, NULL, cb->extack);
e44ef4e4
AL
7920 if (err)
7921 goto unlock;
3015f822 7922 state->dump_ts = reporter->dump_ts;
e44ef4e4 7923 }
3015f822 7924 if (!reporter->dump_fmsg || state->dump_ts != reporter->dump_ts) {
e44ef4e4
AL
7925 NL_SET_ERR_MSG_MOD(cb->extack, "Dump trampled, please retry");
7926 err = -EAGAIN;
7927 goto unlock;
7928 }
35455e23 7929
e44ef4e4
AL
7930 err = devlink_fmsg_dumpit(reporter->dump_fmsg, skb, cb,
7931 DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET);
7932unlock:
35455e23
EBE
7933 mutex_unlock(&reporter->dump_lock);
7934 return err;
7935}
7936
7937static int
7938devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb,
7939 struct genl_info *info)
7940{
7941 struct devlink *devlink = info->user_ptr[0];
7942 struct devlink_health_reporter *reporter;
7943
7944 reporter = devlink_health_reporter_get_from_info(devlink, info);
7945 if (!reporter)
7946 return -EINVAL;
7947
e994a75f 7948 if (!reporter->ops->dump)
35455e23
EBE
7949 return -EOPNOTSUPP;
7950
7951 mutex_lock(&reporter->dump_lock);
7952 devlink_health_dump_clear(reporter);
7953 mutex_unlock(&reporter->dump_lock);
7954 return 0;
7955}
7956
e2ce94dc
JP
7957static int devlink_nl_cmd_health_reporter_test_doit(struct sk_buff *skb,
7958 struct genl_info *info)
7959{
7960 struct devlink *devlink = info->user_ptr[0];
7961 struct devlink_health_reporter *reporter;
e2ce94dc
JP
7962
7963 reporter = devlink_health_reporter_get_from_info(devlink, info);
7964 if (!reporter)
7965 return -EINVAL;
7966
e994a75f 7967 if (!reporter->ops->test)
e2ce94dc 7968 return -EOPNOTSUPP;
e2ce94dc 7969
e994a75f 7970 return reporter->ops->test(reporter, info->extack);
e2ce94dc
JP
7971}
7972
0f420b6c 7973struct devlink_stats {
958751e0
ED
7974 u64_stats_t rx_bytes;
7975 u64_stats_t rx_packets;
0f420b6c
IS
7976 struct u64_stats_sync syncp;
7977};
7978
1e8c6619
IS
7979/**
7980 * struct devlink_trap_policer_item - Packet trap policer attributes.
7981 * @policer: Immutable packet trap policer attributes.
7982 * @rate: Rate in packets / sec.
7983 * @burst: Burst size in packets.
7984 * @list: trap_policer_list member.
7985 *
7986 * Describes packet trap policer attributes. Created by devlink during trap
7987 * policer registration.
7988 */
7989struct devlink_trap_policer_item {
7990 const struct devlink_trap_policer *policer;
7991 u64 rate;
7992 u64 burst;
7993 struct list_head list;
7994};
7995
0f420b6c
IS
7996/**
7997 * struct devlink_trap_group_item - Packet trap group attributes.
7998 * @group: Immutable packet trap group attributes.
f9f54392 7999 * @policer_item: Associated policer item. Can be NULL.
0f420b6c
IS
8000 * @list: trap_group_list member.
8001 * @stats: Trap group statistics.
8002 *
8003 * Describes packet trap group attributes. Created by devlink during trap
a09b37fc 8004 * group registration.
0f420b6c
IS
8005 */
8006struct devlink_trap_group_item {
8007 const struct devlink_trap_group *group;
f9f54392 8008 struct devlink_trap_policer_item *policer_item;
0f420b6c
IS
8009 struct list_head list;
8010 struct devlink_stats __percpu *stats;
8011};
8012
8013/**
8014 * struct devlink_trap_item - Packet trap attributes.
8015 * @trap: Immutable packet trap attributes.
8016 * @group_item: Associated group item.
8017 * @list: trap_list member.
8018 * @action: Trap action.
8019 * @stats: Trap statistics.
8020 * @priv: Driver private information.
8021 *
8022 * Describes both mutable and immutable packet trap attributes. Created by
8023 * devlink during trap registration and used for all trap related operations.
8024 */
8025struct devlink_trap_item {
8026 const struct devlink_trap *trap;
8027 struct devlink_trap_group_item *group_item;
8028 struct list_head list;
8029 enum devlink_trap_action action;
8030 struct devlink_stats __percpu *stats;
8031 void *priv;
8032};
8033
1e8c6619
IS
8034static struct devlink_trap_policer_item *
8035devlink_trap_policer_item_lookup(struct devlink *devlink, u32 id)
8036{
8037 struct devlink_trap_policer_item *policer_item;
8038
8039 list_for_each_entry(policer_item, &devlink->trap_policer_list, list) {
8040 if (policer_item->policer->id == id)
8041 return policer_item;
8042 }
8043
8044 return NULL;
8045}
8046
0f420b6c
IS
8047static struct devlink_trap_item *
8048devlink_trap_item_lookup(struct devlink *devlink, const char *name)
8049{
8050 struct devlink_trap_item *trap_item;
8051
8052 list_for_each_entry(trap_item, &devlink->trap_list, list) {
8053 if (!strcmp(trap_item->trap->name, name))
8054 return trap_item;
8055 }
8056
8057 return NULL;
8058}
8059
8060static struct devlink_trap_item *
8061devlink_trap_item_get_from_info(struct devlink *devlink,
8062 struct genl_info *info)
8063{
8064 struct nlattr *attr;
8065
8066 if (!info->attrs[DEVLINK_ATTR_TRAP_NAME])
8067 return NULL;
8068 attr = info->attrs[DEVLINK_ATTR_TRAP_NAME];
8069
8070 return devlink_trap_item_lookup(devlink, nla_data(attr));
8071}
8072
8073static int
8074devlink_trap_action_get_from_info(struct genl_info *info,
8075 enum devlink_trap_action *p_trap_action)
8076{
8077 u8 val;
8078
8079 val = nla_get_u8(info->attrs[DEVLINK_ATTR_TRAP_ACTION]);
8080 switch (val) {
df561f66
GS
8081 case DEVLINK_TRAP_ACTION_DROP:
8082 case DEVLINK_TRAP_ACTION_TRAP:
9eefeabe 8083 case DEVLINK_TRAP_ACTION_MIRROR:
0f420b6c
IS
8084 *p_trap_action = val;
8085 break;
8086 default:
8087 return -EINVAL;
8088 }
8089
8090 return 0;
8091}
8092
8093static int devlink_trap_metadata_put(struct sk_buff *msg,
8094 const struct devlink_trap *trap)
8095{
8096 struct nlattr *attr;
8097
8098 attr = nla_nest_start(msg, DEVLINK_ATTR_TRAP_METADATA);
8099 if (!attr)
8100 return -EMSGSIZE;
8101
8102 if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT) &&
8103 nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_IN_PORT))
8104 goto nla_put_failure;
85b0589e
JP
8105 if ((trap->metadata_cap & DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE) &&
8106 nla_put_flag(msg, DEVLINK_ATTR_TRAP_METADATA_TYPE_FA_COOKIE))
8107 goto nla_put_failure;
0f420b6c
IS
8108
8109 nla_nest_end(msg, attr);
8110
8111 return 0;
8112
8113nla_put_failure:
8114 nla_nest_cancel(msg, attr);
8115 return -EMSGSIZE;
8116}
8117
8118static void devlink_trap_stats_read(struct devlink_stats __percpu *trap_stats,
8119 struct devlink_stats *stats)
8120{
8121 int i;
8122
8123 memset(stats, 0, sizeof(*stats));
8124 for_each_possible_cpu(i) {
8125 struct devlink_stats *cpu_stats;
8126 u64 rx_packets, rx_bytes;
8127 unsigned int start;
8128
8129 cpu_stats = per_cpu_ptr(trap_stats, i);
8130 do {
d120d1a6 8131 start = u64_stats_fetch_begin(&cpu_stats->syncp);
958751e0
ED
8132 rx_packets = u64_stats_read(&cpu_stats->rx_packets);
8133 rx_bytes = u64_stats_read(&cpu_stats->rx_bytes);
d120d1a6 8134 } while (u64_stats_fetch_retry(&cpu_stats->syncp, start));
0f420b6c 8135
958751e0
ED
8136 u64_stats_add(&stats->rx_packets, rx_packets);
8137 u64_stats_add(&stats->rx_bytes, rx_bytes);
0f420b6c
IS
8138 }
8139}
8140
ddee9dbc
OM
8141static int
8142devlink_trap_group_stats_put(struct sk_buff *msg,
8143 struct devlink_stats __percpu *trap_stats)
0f420b6c
IS
8144{
8145 struct devlink_stats stats;
8146 struct nlattr *attr;
8147
8148 devlink_trap_stats_read(trap_stats, &stats);
8149
8150 attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
8151 if (!attr)
8152 return -EMSGSIZE;
8153
8154 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS,
958751e0
ED
8155 u64_stats_read(&stats.rx_packets),
8156 DEVLINK_ATTR_PAD))
0f420b6c
IS
8157 goto nla_put_failure;
8158
8159 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES,
958751e0
ED
8160 u64_stats_read(&stats.rx_bytes),
8161 DEVLINK_ATTR_PAD))
0f420b6c
IS
8162 goto nla_put_failure;
8163
8164 nla_nest_end(msg, attr);
8165
8166 return 0;
8167
8168nla_put_failure:
8169 nla_nest_cancel(msg, attr);
8170 return -EMSGSIZE;
8171}
8172
ddee9dbc
OM
8173static int devlink_trap_stats_put(struct sk_buff *msg, struct devlink *devlink,
8174 const struct devlink_trap_item *trap_item)
8175{
8176 struct devlink_stats stats;
8177 struct nlattr *attr;
8178 u64 drops = 0;
8179 int err;
8180
8181 if (devlink->ops->trap_drop_counter_get) {
8182 err = devlink->ops->trap_drop_counter_get(devlink,
8183 trap_item->trap,
8184 &drops);
8185 if (err)
8186 return err;
8187 }
8188
8189 devlink_trap_stats_read(trap_item->stats, &stats);
8190
8191 attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
8192 if (!attr)
8193 return -EMSGSIZE;
8194
8195 if (devlink->ops->trap_drop_counter_get &&
8196 nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops,
8197 DEVLINK_ATTR_PAD))
8198 goto nla_put_failure;
8199
8200 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_PACKETS,
958751e0
ED
8201 u64_stats_read(&stats.rx_packets),
8202 DEVLINK_ATTR_PAD))
ddee9dbc
OM
8203 goto nla_put_failure;
8204
8205 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_BYTES,
958751e0
ED
8206 u64_stats_read(&stats.rx_bytes),
8207 DEVLINK_ATTR_PAD))
ddee9dbc
OM
8208 goto nla_put_failure;
8209
8210 nla_nest_end(msg, attr);
8211
8212 return 0;
8213
8214nla_put_failure:
8215 nla_nest_cancel(msg, attr);
8216 return -EMSGSIZE;
8217}
8218
0f420b6c
IS
8219static int devlink_nl_trap_fill(struct sk_buff *msg, struct devlink *devlink,
8220 const struct devlink_trap_item *trap_item,
8221 enum devlink_command cmd, u32 portid, u32 seq,
8222 int flags)
8223{
8224 struct devlink_trap_group_item *group_item = trap_item->group_item;
8225 void *hdr;
8226 int err;
8227
8228 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
8229 if (!hdr)
8230 return -EMSGSIZE;
8231
8232 if (devlink_nl_put_handle(msg, devlink))
8233 goto nla_put_failure;
8234
8235 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
8236 group_item->group->name))
8237 goto nla_put_failure;
8238
8239 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_NAME, trap_item->trap->name))
8240 goto nla_put_failure;
8241
8242 if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_TYPE, trap_item->trap->type))
8243 goto nla_put_failure;
8244
8245 if (trap_item->trap->generic &&
8246 nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
8247 goto nla_put_failure;
8248
8249 if (nla_put_u8(msg, DEVLINK_ATTR_TRAP_ACTION, trap_item->action))
8250 goto nla_put_failure;
8251
8252 err = devlink_trap_metadata_put(msg, trap_item->trap);
8253 if (err)
8254 goto nla_put_failure;
8255
ddee9dbc 8256 err = devlink_trap_stats_put(msg, devlink, trap_item);
0f420b6c
IS
8257 if (err)
8258 goto nla_put_failure;
8259
8260 genlmsg_end(msg, hdr);
8261
8262 return 0;
8263
8264nla_put_failure:
8265 genlmsg_cancel(msg, hdr);
8266 return -EMSGSIZE;
8267}
8268
8269static int devlink_nl_cmd_trap_get_doit(struct sk_buff *skb,
8270 struct genl_info *info)
8271{
8272 struct netlink_ext_ack *extack = info->extack;
8273 struct devlink *devlink = info->user_ptr[0];
8274 struct devlink_trap_item *trap_item;
8275 struct sk_buff *msg;
8276 int err;
8277
8278 if (list_empty(&devlink->trap_list))
8279 return -EOPNOTSUPP;
8280
8281 trap_item = devlink_trap_item_get_from_info(devlink, info);
8282 if (!trap_item) {
8283 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap");
8284 return -ENOENT;
8285 }
8286
8287 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
8288 if (!msg)
8289 return -ENOMEM;
8290
8291 err = devlink_nl_trap_fill(msg, devlink, trap_item,
8292 DEVLINK_CMD_TRAP_NEW, info->snd_portid,
8293 info->snd_seq, 0);
8294 if (err)
8295 goto err_trap_fill;
8296
8297 return genlmsg_reply(msg, info);
8298
8299err_trap_fill:
8300 nlmsg_free(msg);
8301 return err;
8302}
8303
5ce76d78
JK
8304static int
8305devlink_nl_cmd_trap_get_dump_one(struct sk_buff *msg, struct devlink *devlink,
8306 struct netlink_callback *cb)
0f420b6c 8307{
3015f822 8308 struct devlink_nl_dump_state *state = devlink_dump_state(cb);
5ce76d78
JK
8309 struct devlink_trap_item *trap_item;
8310 int idx = 0;
8311 int err = 0;
a8f94707 8312
5ce76d78
JK
8313 list_for_each_entry(trap_item, &devlink->trap_list, list) {
8314 if (idx < state->idx) {
0f420b6c 8315 idx++;
5ce76d78 8316 continue;
0f420b6c 8317 }
5ce76d78
JK
8318 err = devlink_nl_trap_fill(msg, devlink, trap_item,
8319 DEVLINK_CMD_TRAP_NEW,
8320 NETLINK_CB(cb->skb).portid,
8321 cb->nlh->nlmsg_seq,
8322 NLM_F_MULTI);
8323 if (err) {
8324 state->idx = idx;
8325 break;
8326 }
8327 idx++;
0f420b6c 8328 }
5ce76d78
JK
8329
8330 return err;
0f420b6c
IS
8331}
8332
5ce76d78
JK
8333const struct devlink_gen_cmd devl_gen_trap = {
8334 .dump_one = devlink_nl_cmd_trap_get_dump_one,
8335};
8336
0f420b6c
IS
8337static int __devlink_trap_action_set(struct devlink *devlink,
8338 struct devlink_trap_item *trap_item,
8339 enum devlink_trap_action trap_action,
8340 struct netlink_ext_ack *extack)
8341{
8342 int err;
8343
8344 if (trap_item->action != trap_action &&
8345 trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP) {
8346 NL_SET_ERR_MSG_MOD(extack, "Cannot change action of non-drop traps. Skipping");
8347 return 0;
8348 }
8349
8350 err = devlink->ops->trap_action_set(devlink, trap_item->trap,
c88e11e0 8351 trap_action, extack);
0f420b6c
IS
8352 if (err)
8353 return err;
8354
8355 trap_item->action = trap_action;
8356
8357 return 0;
8358}
8359
8360static int devlink_trap_action_set(struct devlink *devlink,
8361 struct devlink_trap_item *trap_item,
8362 struct genl_info *info)
8363{
8364 enum devlink_trap_action trap_action;
8365 int err;
8366
8367 if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
8368 return 0;
8369
8370 err = devlink_trap_action_get_from_info(info, &trap_action);
8371 if (err) {
8372 NL_SET_ERR_MSG_MOD(info->extack, "Invalid trap action");
8373 return -EINVAL;
8374 }
8375
8376 return __devlink_trap_action_set(devlink, trap_item, trap_action,
8377 info->extack);
8378}
8379
8380static int devlink_nl_cmd_trap_set_doit(struct sk_buff *skb,
8381 struct genl_info *info)
8382{
8383 struct netlink_ext_ack *extack = info->extack;
8384 struct devlink *devlink = info->user_ptr[0];
8385 struct devlink_trap_item *trap_item;
0f420b6c
IS
8386
8387 if (list_empty(&devlink->trap_list))
8388 return -EOPNOTSUPP;
8389
8390 trap_item = devlink_trap_item_get_from_info(devlink, info);
8391 if (!trap_item) {
8392 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap");
8393 return -ENOENT;
8394 }
8395
8daa76a5 8396 return devlink_trap_action_set(devlink, trap_item, info);
0f420b6c
IS
8397}
8398
8399static struct devlink_trap_group_item *
8400devlink_trap_group_item_lookup(struct devlink *devlink, const char *name)
8401{
8402 struct devlink_trap_group_item *group_item;
8403
8404 list_for_each_entry(group_item, &devlink->trap_group_list, list) {
8405 if (!strcmp(group_item->group->name, name))
8406 return group_item;
8407 }
8408
8409 return NULL;
8410}
8411
107f1678
IS
8412static struct devlink_trap_group_item *
8413devlink_trap_group_item_lookup_by_id(struct devlink *devlink, u16 id)
8414{
8415 struct devlink_trap_group_item *group_item;
8416
8417 list_for_each_entry(group_item, &devlink->trap_group_list, list) {
8418 if (group_item->group->id == id)
8419 return group_item;
8420 }
8421
8422 return NULL;
8423}
8424
0f420b6c
IS
8425static struct devlink_trap_group_item *
8426devlink_trap_group_item_get_from_info(struct devlink *devlink,
8427 struct genl_info *info)
8428{
8429 char *name;
8430
8431 if (!info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME])
8432 return NULL;
8433 name = nla_data(info->attrs[DEVLINK_ATTR_TRAP_GROUP_NAME]);
8434
8435 return devlink_trap_group_item_lookup(devlink, name);
8436}
8437
8438static int
8439devlink_nl_trap_group_fill(struct sk_buff *msg, struct devlink *devlink,
8440 const struct devlink_trap_group_item *group_item,
8441 enum devlink_command cmd, u32 portid, u32 seq,
8442 int flags)
8443{
8444 void *hdr;
8445 int err;
8446
8447 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
8448 if (!hdr)
8449 return -EMSGSIZE;
8450
8451 if (devlink_nl_put_handle(msg, devlink))
8452 goto nla_put_failure;
8453
8454 if (nla_put_string(msg, DEVLINK_ATTR_TRAP_GROUP_NAME,
8455 group_item->group->name))
8456 goto nla_put_failure;
8457
8458 if (group_item->group->generic &&
8459 nla_put_flag(msg, DEVLINK_ATTR_TRAP_GENERIC))
8460 goto nla_put_failure;
8461
f9f54392
IS
8462 if (group_item->policer_item &&
8463 nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID,
8464 group_item->policer_item->policer->id))
8465 goto nla_put_failure;
8466
ddee9dbc 8467 err = devlink_trap_group_stats_put(msg, group_item->stats);
0f420b6c
IS
8468 if (err)
8469 goto nla_put_failure;
8470
8471 genlmsg_end(msg, hdr);
8472
8473 return 0;
8474
8475nla_put_failure:
8476 genlmsg_cancel(msg, hdr);
8477 return -EMSGSIZE;
8478}
8479
8480static int devlink_nl_cmd_trap_group_get_doit(struct sk_buff *skb,
8481 struct genl_info *info)
8482{
8483 struct netlink_ext_ack *extack = info->extack;
8484 struct devlink *devlink = info->user_ptr[0];
8485 struct devlink_trap_group_item *group_item;
8486 struct sk_buff *msg;
8487 int err;
8488
8489 if (list_empty(&devlink->trap_group_list))
8490 return -EOPNOTSUPP;
8491
8492 group_item = devlink_trap_group_item_get_from_info(devlink, info);
8493 if (!group_item) {
8494 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap group");
8495 return -ENOENT;
8496 }
8497
8498 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
8499 if (!msg)
8500 return -ENOMEM;
8501
8502 err = devlink_nl_trap_group_fill(msg, devlink, group_item,
8503 DEVLINK_CMD_TRAP_GROUP_NEW,
8504 info->snd_portid, info->snd_seq, 0);
8505 if (err)
8506 goto err_trap_group_fill;
8507
8508 return genlmsg_reply(msg, info);
8509
8510err_trap_group_fill:
8511 nlmsg_free(msg);
8512 return err;
8513}
8514
5ce76d78
JK
8515static int
8516devlink_nl_cmd_trap_group_get_dump_one(struct sk_buff *msg,
8517 struct devlink *devlink,
8518 struct netlink_callback *cb)
0f420b6c 8519{
3015f822 8520 struct devlink_nl_dump_state *state = devlink_dump_state(cb);
5ce76d78
JK
8521 struct devlink_trap_group_item *group_item;
8522 int idx = 0;
8523 int err = 0;
0f420b6c 8524
a8f94707 8525
5ce76d78
JK
8526 list_for_each_entry(group_item, &devlink->trap_group_list, list) {
8527 if (idx < state->idx) {
0f420b6c 8528 idx++;
5ce76d78 8529 continue;
0f420b6c 8530 }
5ce76d78
JK
8531 err = devlink_nl_trap_group_fill(msg, devlink, group_item,
8532 DEVLINK_CMD_TRAP_GROUP_NEW,
8533 NETLINK_CB(cb->skb).portid,
8534 cb->nlh->nlmsg_seq,
8535 NLM_F_MULTI);
8536 if (err) {
8537 state->idx = idx;
8538 break;
8539 }
8540 idx++;
0f420b6c 8541 }
5ce76d78
JK
8542
8543 return err;
0f420b6c
IS
8544}
8545
5ce76d78
JK
8546const struct devlink_gen_cmd devl_gen_trap_group = {
8547 .dump_one = devlink_nl_cmd_trap_group_get_dump_one,
8548};
8549
0f420b6c
IS
8550static int
8551__devlink_trap_group_action_set(struct devlink *devlink,
8552 struct devlink_trap_group_item *group_item,
8553 enum devlink_trap_action trap_action,
8554 struct netlink_ext_ack *extack)
8555{
8556 const char *group_name = group_item->group->name;
8557 struct devlink_trap_item *trap_item;
8558 int err;
8559
c50bf2be
IC
8560 if (devlink->ops->trap_group_action_set) {
8561 err = devlink->ops->trap_group_action_set(devlink, group_item->group,
8562 trap_action, extack);
8563 if (err)
8564 return err;
8565
8566 list_for_each_entry(trap_item, &devlink->trap_list, list) {
8567 if (strcmp(trap_item->group_item->group->name, group_name))
8568 continue;
8569 if (trap_item->action != trap_action &&
8570 trap_item->trap->type != DEVLINK_TRAP_TYPE_DROP)
8571 continue;
8572 trap_item->action = trap_action;
8573 }
8574
8575 return 0;
8576 }
8577
0f420b6c 8578 list_for_each_entry(trap_item, &devlink->trap_list, list) {
107f1678 8579 if (strcmp(trap_item->group_item->group->name, group_name))
0f420b6c
IS
8580 continue;
8581 err = __devlink_trap_action_set(devlink, trap_item,
8582 trap_action, extack);
8583 if (err)
8584 return err;
8585 }
8586
8587 return 0;
8588}
8589
8590static int
8591devlink_trap_group_action_set(struct devlink *devlink,
8592 struct devlink_trap_group_item *group_item,
c064875a 8593 struct genl_info *info, bool *p_modified)
0f420b6c
IS
8594{
8595 enum devlink_trap_action trap_action;
8596 int err;
8597
8598 if (!info->attrs[DEVLINK_ATTR_TRAP_ACTION])
8599 return 0;
8600
8601 err = devlink_trap_action_get_from_info(info, &trap_action);
8602 if (err) {
8603 NL_SET_ERR_MSG_MOD(info->extack, "Invalid trap action");
8604 return -EINVAL;
8605 }
8606
8607 err = __devlink_trap_group_action_set(devlink, group_item, trap_action,
8608 info->extack);
8609 if (err)
8610 return err;
8611
c064875a
IS
8612 *p_modified = true;
8613
8614 return 0;
8615}
8616
8617static int devlink_trap_group_set(struct devlink *devlink,
8618 struct devlink_trap_group_item *group_item,
8619 struct genl_info *info)
8620{
8621 struct devlink_trap_policer_item *policer_item;
8622 struct netlink_ext_ack *extack = info->extack;
8623 const struct devlink_trap_policer *policer;
8624 struct nlattr **attrs = info->attrs;
501543b4 8625 u32 policer_id;
c064875a
IS
8626 int err;
8627
8628 if (!attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
8629 return 0;
8630
8631 if (!devlink->ops->trap_group_set)
8632 return -EOPNOTSUPP;
8633
501543b4
DC
8634 policer_id = nla_get_u32(attrs[DEVLINK_ATTR_TRAP_POLICER_ID]);
8635 policer_item = devlink_trap_policer_item_lookup(devlink, policer_id);
8636 if (policer_id && !policer_item) {
8637 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");
8638 return -ENOENT;
c064875a
IS
8639 }
8640 policer = policer_item ? policer_item->policer : NULL;
8641
c88e11e0
IS
8642 err = devlink->ops->trap_group_set(devlink, group_item->group, policer,
8643 extack);
c064875a
IS
8644 if (err)
8645 return err;
8646
8647 group_item->policer_item = policer_item;
8648
0f420b6c
IS
8649 return 0;
8650}
8651
8652static int devlink_nl_cmd_trap_group_set_doit(struct sk_buff *skb,
8653 struct genl_info *info)
8654{
8655 struct netlink_ext_ack *extack = info->extack;
8656 struct devlink *devlink = info->user_ptr[0];
8657 struct devlink_trap_group_item *group_item;
c064875a 8658 bool modified = false;
0f420b6c
IS
8659 int err;
8660
8661 if (list_empty(&devlink->trap_group_list))
8662 return -EOPNOTSUPP;
8663
8664 group_item = devlink_trap_group_item_get_from_info(devlink, info);
8665 if (!group_item) {
8666 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap group");
8667 return -ENOENT;
8668 }
8669
c064875a
IS
8670 err = devlink_trap_group_action_set(devlink, group_item, info,
8671 &modified);
0f420b6c
IS
8672 if (err)
8673 return err;
8674
c064875a
IS
8675 err = devlink_trap_group_set(devlink, group_item, info);
8676 if (err)
8677 goto err_trap_group_set;
8678
0f420b6c 8679 return 0;
c064875a
IS
8680
8681err_trap_group_set:
8682 if (modified)
8683 NL_SET_ERR_MSG_MOD(extack, "Trap group set failed, but some changes were committed already");
8684 return err;
0f420b6c
IS
8685}
8686
1e8c6619
IS
8687static struct devlink_trap_policer_item *
8688devlink_trap_policer_item_get_from_info(struct devlink *devlink,
8689 struct genl_info *info)
8690{
8691 u32 id;
8692
8693 if (!info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID])
8694 return NULL;
8695 id = nla_get_u32(info->attrs[DEVLINK_ATTR_TRAP_POLICER_ID]);
8696
8697 return devlink_trap_policer_item_lookup(devlink, id);
8698}
8699
8700static int
8701devlink_trap_policer_stats_put(struct sk_buff *msg, struct devlink *devlink,
8702 const struct devlink_trap_policer *policer)
8703{
8704 struct nlattr *attr;
8705 u64 drops;
8706 int err;
8707
8708 if (!devlink->ops->trap_policer_counter_get)
8709 return 0;
8710
8711 err = devlink->ops->trap_policer_counter_get(devlink, policer, &drops);
8712 if (err)
8713 return err;
8714
8715 attr = nla_nest_start(msg, DEVLINK_ATTR_STATS);
8716 if (!attr)
8717 return -EMSGSIZE;
8718
8719 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_STATS_RX_DROPPED, drops,
8720 DEVLINK_ATTR_PAD))
8721 goto nla_put_failure;
8722
8723 nla_nest_end(msg, attr);
8724
8725 return 0;
8726
8727nla_put_failure:
8728 nla_nest_cancel(msg, attr);
8729 return -EMSGSIZE;
8730}
8731
8732static int
8733devlink_nl_trap_policer_fill(struct sk_buff *msg, struct devlink *devlink,
8734 const struct devlink_trap_policer_item *policer_item,
8735 enum devlink_command cmd, u32 portid, u32 seq,
8736 int flags)
8737{
8738 void *hdr;
8739 int err;
8740
8741 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
8742 if (!hdr)
8743 return -EMSGSIZE;
8744
8745 if (devlink_nl_put_handle(msg, devlink))
8746 goto nla_put_failure;
8747
8748 if (nla_put_u32(msg, DEVLINK_ATTR_TRAP_POLICER_ID,
8749 policer_item->policer->id))
8750 goto nla_put_failure;
8751
8752 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_RATE,
8753 policer_item->rate, DEVLINK_ATTR_PAD))
8754 goto nla_put_failure;
8755
8756 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_TRAP_POLICER_BURST,
8757 policer_item->burst, DEVLINK_ATTR_PAD))
8758 goto nla_put_failure;
8759
8760 err = devlink_trap_policer_stats_put(msg, devlink,
8761 policer_item->policer);
8762 if (err)
8763 goto nla_put_failure;
8764
8765 genlmsg_end(msg, hdr);
8766
8767 return 0;
8768
8769nla_put_failure:
8770 genlmsg_cancel(msg, hdr);
8771 return -EMSGSIZE;
8772}
8773
8774static int devlink_nl_cmd_trap_policer_get_doit(struct sk_buff *skb,
8775 struct genl_info *info)
8776{
8777 struct devlink_trap_policer_item *policer_item;
8778 struct netlink_ext_ack *extack = info->extack;
8779 struct devlink *devlink = info->user_ptr[0];
8780 struct sk_buff *msg;
8781 int err;
8782
8783 if (list_empty(&devlink->trap_policer_list))
8784 return -EOPNOTSUPP;
8785
8786 policer_item = devlink_trap_policer_item_get_from_info(devlink, info);
8787 if (!policer_item) {
8788 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");
8789 return -ENOENT;
8790 }
8791
8792 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
8793 if (!msg)
8794 return -ENOMEM;
8795
8796 err = devlink_nl_trap_policer_fill(msg, devlink, policer_item,
8797 DEVLINK_CMD_TRAP_POLICER_NEW,
8798 info->snd_portid, info->snd_seq, 0);
8799 if (err)
8800 goto err_trap_policer_fill;
8801
8802 return genlmsg_reply(msg, info);
8803
8804err_trap_policer_fill:
8805 nlmsg_free(msg);
8806 return err;
8807}
8808
5ce76d78
JK
8809static int
8810devlink_nl_cmd_trap_policer_get_dump_one(struct sk_buff *msg,
8811 struct devlink *devlink,
8812 struct netlink_callback *cb)
1e8c6619 8813{
3015f822 8814 struct devlink_nl_dump_state *state = devlink_dump_state(cb);
5ce76d78
JK
8815 struct devlink_trap_policer_item *policer_item;
8816 int idx = 0;
8817 int err = 0;
a8f94707 8818
5ce76d78
JK
8819 list_for_each_entry(policer_item, &devlink->trap_policer_list, list) {
8820 if (idx < state->idx) {
1e8c6619 8821 idx++;
5ce76d78 8822 continue;
1e8c6619 8823 }
5ce76d78
JK
8824 err = devlink_nl_trap_policer_fill(msg, devlink, policer_item,
8825 DEVLINK_CMD_TRAP_POLICER_NEW,
8826 NETLINK_CB(cb->skb).portid,
8827 cb->nlh->nlmsg_seq,
8828 NLM_F_MULTI);
8829 if (err) {
8830 state->idx = idx;
8831 break;
8832 }
8833 idx++;
1e8c6619 8834 }
5ce76d78
JK
8835
8836 return err;
1e8c6619
IS
8837}
8838
5ce76d78
JK
8839const struct devlink_gen_cmd devl_gen_trap_policer = {
8840 .dump_one = devlink_nl_cmd_trap_policer_get_dump_one,
8841};
8842
1e8c6619
IS
8843static int
8844devlink_trap_policer_set(struct devlink *devlink,
8845 struct devlink_trap_policer_item *policer_item,
8846 struct genl_info *info)
8847{
8848 struct netlink_ext_ack *extack = info->extack;
8849 struct nlattr **attrs = info->attrs;
8850 u64 rate, burst;
8851 int err;
8852
8853 rate = policer_item->rate;
8854 burst = policer_item->burst;
8855
8856 if (attrs[DEVLINK_ATTR_TRAP_POLICER_RATE])
8857 rate = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_RATE]);
8858
8859 if (attrs[DEVLINK_ATTR_TRAP_POLICER_BURST])
8860 burst = nla_get_u64(attrs[DEVLINK_ATTR_TRAP_POLICER_BURST]);
8861
8862 if (rate < policer_item->policer->min_rate) {
8863 NL_SET_ERR_MSG_MOD(extack, "Policer rate lower than limit");
8864 return -EINVAL;
8865 }
8866
8867 if (rate > policer_item->policer->max_rate) {
8868 NL_SET_ERR_MSG_MOD(extack, "Policer rate higher than limit");
8869 return -EINVAL;
8870 }
8871
8872 if (burst < policer_item->policer->min_burst) {
8873 NL_SET_ERR_MSG_MOD(extack, "Policer burst size lower than limit");
8874 return -EINVAL;
8875 }
8876
8877 if (burst > policer_item->policer->max_burst) {
8878 NL_SET_ERR_MSG_MOD(extack, "Policer burst size higher than limit");
8879 return -EINVAL;
8880 }
8881
8882 err = devlink->ops->trap_policer_set(devlink, policer_item->policer,
8883 rate, burst, info->extack);
8884 if (err)
8885 return err;
8886
8887 policer_item->rate = rate;
8888 policer_item->burst = burst;
8889
8890 return 0;
8891}
8892
8893static int devlink_nl_cmd_trap_policer_set_doit(struct sk_buff *skb,
8894 struct genl_info *info)
8895{
8896 struct devlink_trap_policer_item *policer_item;
8897 struct netlink_ext_ack *extack = info->extack;
8898 struct devlink *devlink = info->user_ptr[0];
8899
8900 if (list_empty(&devlink->trap_policer_list))
8901 return -EOPNOTSUPP;
8902
8903 if (!devlink->ops->trap_policer_set)
8904 return -EOPNOTSUPP;
8905
8906 policer_item = devlink_trap_policer_item_get_from_info(devlink, info);
8907 if (!policer_item) {
8908 NL_SET_ERR_MSG_MOD(extack, "Device did not register this trap policer");
8909 return -ENOENT;
8910 }
8911
8912 return devlink_trap_policer_set(devlink, policer_item, info);
8913}
8914
623cd13b 8915const struct genl_small_ops devlink_nl_ops[56] = {
bfcd3a46
JP
8916 {
8917 .cmd = DEVLINK_CMD_GET,
ef6243ac 8918 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bfcd3a46 8919 .doit = devlink_nl_cmd_get_doit,
5ce76d78 8920 .dumpit = devlink_nl_instance_iter_dump,
bfcd3a46
JP
8921 /* can be retrieved by unprivileged users */
8922 },
8923 {
8924 .cmd = DEVLINK_CMD_PORT_GET,
ef6243ac 8925 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bfcd3a46 8926 .doit = devlink_nl_cmd_port_get_doit,
5ce76d78 8927 .dumpit = devlink_nl_instance_iter_dump,
bfcd3a46
JP
8928 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
8929 /* can be retrieved by unprivileged users */
8930 },
8931 {
8932 .cmd = DEVLINK_CMD_PORT_SET,
ef6243ac 8933 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bfcd3a46 8934 .doit = devlink_nl_cmd_port_set_doit,
bfcd3a46
JP
8935 .flags = GENL_ADMIN_PERM,
8936 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
8937 },
4677efc4
DL
8938 {
8939 .cmd = DEVLINK_CMD_RATE_GET,
8940 .doit = devlink_nl_cmd_rate_get_doit,
07f3af66 8941 .dumpit = devlink_nl_instance_iter_dump,
4677efc4
DL
8942 .internal_flags = DEVLINK_NL_FLAG_NEED_RATE,
8943 /* can be retrieved by unprivileged users */
8944 },
1897db2e
DL
8945 {
8946 .cmd = DEVLINK_CMD_RATE_SET,
8947 .doit = devlink_nl_cmd_rate_set_doit,
8948 .flags = GENL_ADMIN_PERM,
8949 .internal_flags = DEVLINK_NL_FLAG_NEED_RATE,
8950 },
a8ecb93e
DL
8951 {
8952 .cmd = DEVLINK_CMD_RATE_NEW,
8953 .doit = devlink_nl_cmd_rate_new_doit,
8954 .flags = GENL_ADMIN_PERM,
8955 },
8956 {
8957 .cmd = DEVLINK_CMD_RATE_DEL,
8958 .doit = devlink_nl_cmd_rate_del_doit,
8959 .flags = GENL_ADMIN_PERM,
8960 .internal_flags = DEVLINK_NL_FLAG_NEED_RATE_NODE,
8961 },
bfcd3a46
JP
8962 {
8963 .cmd = DEVLINK_CMD_PORT_SPLIT,
ef6243ac 8964 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bfcd3a46 8965 .doit = devlink_nl_cmd_port_split_doit,
bfcd3a46 8966 .flags = GENL_ADMIN_PERM,
706217c1 8967 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
bfcd3a46
JP
8968 },
8969 {
8970 .cmd = DEVLINK_CMD_PORT_UNSPLIT,
ef6243ac 8971 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bfcd3a46 8972 .doit = devlink_nl_cmd_port_unsplit_doit,
bfcd3a46 8973 .flags = GENL_ADMIN_PERM,
706217c1 8974 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
bfcd3a46 8975 },
cd76dcd6
PP
8976 {
8977 .cmd = DEVLINK_CMD_PORT_NEW,
8978 .doit = devlink_nl_cmd_port_new_doit,
8979 .flags = GENL_ADMIN_PERM,
cd76dcd6
PP
8980 },
8981 {
8982 .cmd = DEVLINK_CMD_PORT_DEL,
8983 .doit = devlink_nl_cmd_port_del_doit,
8984 .flags = GENL_ADMIN_PERM,
cd76dcd6 8985 },
c246f9b5
JP
8986 {
8987 .cmd = DEVLINK_CMD_LINECARD_GET,
8988 .doit = devlink_nl_cmd_linecard_get_doit,
25573968 8989 .dumpit = devlink_nl_instance_iter_dump,
c246f9b5
JP
8990 .internal_flags = DEVLINK_NL_FLAG_NEED_LINECARD,
8991 /* can be retrieved by unprivileged users */
8992 },
fcdc8ce2
JP
8993 {
8994 .cmd = DEVLINK_CMD_LINECARD_SET,
8995 .doit = devlink_nl_cmd_linecard_set_doit,
8996 .flags = GENL_ADMIN_PERM,
8997 .internal_flags = DEVLINK_NL_FLAG_NEED_LINECARD,
8998 },
bf797471
JP
8999 {
9000 .cmd = DEVLINK_CMD_SB_GET,
ef6243ac 9001 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bf797471 9002 .doit = devlink_nl_cmd_sb_get_doit,
5ce76d78 9003 .dumpit = devlink_nl_instance_iter_dump,
bf797471
JP
9004 /* can be retrieved by unprivileged users */
9005 },
9006 {
9007 .cmd = DEVLINK_CMD_SB_POOL_GET,
ef6243ac 9008 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bf797471 9009 .doit = devlink_nl_cmd_sb_pool_get_doit,
5ce76d78 9010 .dumpit = devlink_nl_instance_iter_dump,
bf797471
JP
9011 /* can be retrieved by unprivileged users */
9012 },
9013 {
9014 .cmd = DEVLINK_CMD_SB_POOL_SET,
ef6243ac 9015 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bf797471 9016 .doit = devlink_nl_cmd_sb_pool_set_doit,
bf797471 9017 .flags = GENL_ADMIN_PERM,
bf797471
JP
9018 },
9019 {
9020 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET,
ef6243ac 9021 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bf797471 9022 .doit = devlink_nl_cmd_sb_port_pool_get_doit,
5ce76d78 9023 .dumpit = devlink_nl_instance_iter_dump,
637989b5 9024 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
bf797471
JP
9025 /* can be retrieved by unprivileged users */
9026 },
9027 {
9028 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET,
ef6243ac 9029 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bf797471 9030 .doit = devlink_nl_cmd_sb_port_pool_set_doit,
bf797471 9031 .flags = GENL_ADMIN_PERM,
637989b5 9032 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
bf797471
JP
9033 },
9034 {
9035 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET,
ef6243ac 9036 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bf797471 9037 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit,
5ce76d78 9038 .dumpit = devlink_nl_instance_iter_dump,
637989b5 9039 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
bf797471
JP
9040 /* can be retrieved by unprivileged users */
9041 },
9042 {
9043 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET,
ef6243ac 9044 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
bf797471 9045 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit,
bf797471 9046 .flags = GENL_ADMIN_PERM,
637989b5 9047 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
bf797471 9048 },
df38dafd
JP
9049 {
9050 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT,
ef6243ac 9051 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
df38dafd 9052 .doit = devlink_nl_cmd_sb_occ_snapshot_doit,
df38dafd 9053 .flags = GENL_ADMIN_PERM,
df38dafd
JP
9054 },
9055 {
9056 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR,
ef6243ac 9057 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
df38dafd 9058 .doit = devlink_nl_cmd_sb_occ_max_clear_doit,
df38dafd 9059 .flags = GENL_ADMIN_PERM,
df38dafd 9060 },
08f4b591 9061 {
adf200f3 9062 .cmd = DEVLINK_CMD_ESWITCH_GET,
ef6243ac 9063 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
adf200f3 9064 .doit = devlink_nl_cmd_eswitch_get_doit,
08f4b591 9065 .flags = GENL_ADMIN_PERM,
08f4b591
OG
9066 },
9067 {
adf200f3 9068 .cmd = DEVLINK_CMD_ESWITCH_SET,
ef6243ac 9069 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
adf200f3 9070 .doit = devlink_nl_cmd_eswitch_set_doit,
08f4b591 9071 .flags = GENL_ADMIN_PERM,
08f4b591 9072 },
1555d204
AS
9073 {
9074 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET,
ef6243ac 9075 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1555d204 9076 .doit = devlink_nl_cmd_dpipe_table_get,
67ae686b 9077 /* can be retrieved by unprivileged users */
1555d204
AS
9078 },
9079 {
9080 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET,
ef6243ac 9081 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1555d204 9082 .doit = devlink_nl_cmd_dpipe_entries_get,
67ae686b 9083 /* can be retrieved by unprivileged users */
1555d204
AS
9084 },
9085 {
9086 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET,
ef6243ac 9087 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1555d204 9088 .doit = devlink_nl_cmd_dpipe_headers_get,
67ae686b 9089 /* can be retrieved by unprivileged users */
1555d204
AS
9090 },
9091 {
9092 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET,
ef6243ac 9093 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
1555d204 9094 .doit = devlink_nl_cmd_dpipe_table_counters_set,
1555d204 9095 .flags = GENL_ADMIN_PERM,
1555d204 9096 },
d9f9b9a4
AS
9097 {
9098 .cmd = DEVLINK_CMD_RESOURCE_SET,
ef6243ac 9099 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
d9f9b9a4 9100 .doit = devlink_nl_cmd_resource_set,
d9f9b9a4 9101 .flags = GENL_ADMIN_PERM,
d9f9b9a4
AS
9102 },
9103 {
9104 .cmd = DEVLINK_CMD_RESOURCE_DUMP,
ef6243ac 9105 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
d9f9b9a4 9106 .doit = devlink_nl_cmd_resource_dump,
67ae686b 9107 /* can be retrieved by unprivileged users */
d9f9b9a4 9108 },
2d8dc5bb
AS
9109 {
9110 .cmd = DEVLINK_CMD_RELOAD,
ef6243ac 9111 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
2d8dc5bb 9112 .doit = devlink_nl_cmd_reload,
2d8dc5bb 9113 .flags = GENL_ADMIN_PERM,
2d8dc5bb 9114 },
45f05def
MS
9115 {
9116 .cmd = DEVLINK_CMD_PARAM_GET,
ef6243ac 9117 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
45f05def 9118 .doit = devlink_nl_cmd_param_get_doit,
5ce76d78 9119 .dumpit = devlink_nl_instance_iter_dump,
45f05def
MS
9120 /* can be retrieved by unprivileged users */
9121 },
e3b7ca18
MS
9122 {
9123 .cmd = DEVLINK_CMD_PARAM_SET,
ef6243ac 9124 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
e3b7ca18 9125 .doit = devlink_nl_cmd_param_set_doit,
e3b7ca18 9126 .flags = GENL_ADMIN_PERM,
e3b7ca18 9127 },
f4601dee
VV
9128 {
9129 .cmd = DEVLINK_CMD_PORT_PARAM_GET,
ef6243ac 9130 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f4601dee
VV
9131 .doit = devlink_nl_cmd_port_param_get_doit,
9132 .dumpit = devlink_nl_cmd_port_param_get_dumpit,
f4601dee
VV
9133 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
9134 /* can be retrieved by unprivileged users */
9135 },
9c54873b
VV
9136 {
9137 .cmd = DEVLINK_CMD_PORT_PARAM_SET,
ef6243ac 9138 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9c54873b 9139 .doit = devlink_nl_cmd_port_param_set_doit,
9c54873b
VV
9140 .flags = GENL_ADMIN_PERM,
9141 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
9142 },
d8db7ea5
AV
9143 {
9144 .cmd = DEVLINK_CMD_REGION_GET,
ef6243ac 9145 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
d8db7ea5 9146 .doit = devlink_nl_cmd_region_get_doit,
5ce76d78 9147 .dumpit = devlink_nl_instance_iter_dump,
d8db7ea5 9148 .flags = GENL_ADMIN_PERM,
d8db7ea5 9149 },
b9a17abf
JK
9150 {
9151 .cmd = DEVLINK_CMD_REGION_NEW,
9152 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9153 .doit = devlink_nl_cmd_region_new,
9154 .flags = GENL_ADMIN_PERM,
b9a17abf 9155 },
866319bb
AV
9156 {
9157 .cmd = DEVLINK_CMD_REGION_DEL,
ef6243ac 9158 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
866319bb 9159 .doit = devlink_nl_cmd_region_del,
866319bb 9160 .flags = GENL_ADMIN_PERM,
866319bb 9161 },
4e54795a
AV
9162 {
9163 .cmd = DEVLINK_CMD_REGION_READ,
ee85da53
JP
9164 .validate = GENL_DONT_VALIDATE_STRICT |
9165 GENL_DONT_VALIDATE_DUMP_STRICT,
4e54795a 9166 .dumpit = devlink_nl_cmd_region_read_dumpit,
4e54795a 9167 .flags = GENL_ADMIN_PERM,
4e54795a 9168 },
f9cf2288
JK
9169 {
9170 .cmd = DEVLINK_CMD_INFO_GET,
ef6243ac 9171 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
f9cf2288 9172 .doit = devlink_nl_cmd_info_get_doit,
5ce76d78 9173 .dumpit = devlink_nl_instance_iter_dump,
f9cf2288
JK
9174 /* can be retrieved by unprivileged users */
9175 },
7afe335a
EBE
9176 {
9177 .cmd = DEVLINK_CMD_HEALTH_REPORTER_GET,
ef6243ac 9178 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
7afe335a 9179 .doit = devlink_nl_cmd_health_reporter_get_doit,
19be51a9 9180 .dumpit = devlink_nl_instance_iter_dump,
c90005b5 9181 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
7afe335a
EBE
9182 /* can be retrieved by unprivileged users */
9183 },
a1e55ec0
EBE
9184 {
9185 .cmd = DEVLINK_CMD_HEALTH_REPORTER_SET,
ef6243ac 9186 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
a1e55ec0 9187 .doit = devlink_nl_cmd_health_reporter_set_doit,
a1e55ec0 9188 .flags = GENL_ADMIN_PERM,
c90005b5 9189 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
a1e55ec0 9190 },
20a0943a
EBE
9191 {
9192 .cmd = DEVLINK_CMD_HEALTH_REPORTER_RECOVER,
ef6243ac 9193 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
20a0943a 9194 .doit = devlink_nl_cmd_health_reporter_recover_doit,
20a0943a 9195 .flags = GENL_ADMIN_PERM,
c90005b5 9196 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
20a0943a 9197 },
fca42a27
EBE
9198 {
9199 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE,
ef6243ac 9200 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
fca42a27 9201 .doit = devlink_nl_cmd_health_reporter_diagnose_doit,
fca42a27 9202 .flags = GENL_ADMIN_PERM,
c90005b5 9203 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
fca42a27 9204 },
35455e23
EBE
9205 {
9206 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET,
82a843de
JP
9207 .validate = GENL_DONT_VALIDATE_STRICT |
9208 GENL_DONT_VALIDATE_DUMP_STRICT,
e44ef4e4 9209 .dumpit = devlink_nl_cmd_health_reporter_dump_get_dumpit,
35455e23 9210 .flags = GENL_ADMIN_PERM,
35455e23
EBE
9211 },
9212 {
9213 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR,
ef6243ac 9214 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
35455e23 9215 .doit = devlink_nl_cmd_health_reporter_dump_clear_doit,
35455e23 9216 .flags = GENL_ADMIN_PERM,
c90005b5 9217 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
35455e23 9218 },
e2ce94dc
JP
9219 {
9220 .cmd = DEVLINK_CMD_HEALTH_REPORTER_TEST,
9221 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
9222 .doit = devlink_nl_cmd_health_reporter_test_doit,
9223 .flags = GENL_ADMIN_PERM,
c90005b5 9224 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT,
e2ce94dc 9225 },
76726ccb
JK
9226 {
9227 .cmd = DEVLINK_CMD_FLASH_UPDATE,
ef6243ac 9228 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
76726ccb 9229 .doit = devlink_nl_cmd_flash_update,
76726ccb 9230 .flags = GENL_ADMIN_PERM,
76726ccb 9231 },
0f420b6c
IS
9232 {
9233 .cmd = DEVLINK_CMD_TRAP_GET,
9234 .doit = devlink_nl_cmd_trap_get_doit,
5ce76d78 9235 .dumpit = devlink_nl_instance_iter_dump,
0f420b6c
IS
9236 /* can be retrieved by unprivileged users */
9237 },
9238 {
9239 .cmd = DEVLINK_CMD_TRAP_SET,
9240 .doit = devlink_nl_cmd_trap_set_doit,
9241 .flags = GENL_ADMIN_PERM,
0f420b6c
IS
9242 },
9243 {
9244 .cmd = DEVLINK_CMD_TRAP_GROUP_GET,
9245 .doit = devlink_nl_cmd_trap_group_get_doit,
5ce76d78 9246 .dumpit = devlink_nl_instance_iter_dump,
0f420b6c
IS
9247 /* can be retrieved by unprivileged users */
9248 },
9249 {
9250 .cmd = DEVLINK_CMD_TRAP_GROUP_SET,
9251 .doit = devlink_nl_cmd_trap_group_set_doit,
9252 .flags = GENL_ADMIN_PERM,
0f420b6c 9253 },
1e8c6619
IS
9254 {
9255 .cmd = DEVLINK_CMD_TRAP_POLICER_GET,
9256 .doit = devlink_nl_cmd_trap_policer_get_doit,
5ce76d78 9257 .dumpit = devlink_nl_instance_iter_dump,
1e8c6619
IS
9258 /* can be retrieved by unprivileged users */
9259 },
9260 {
9261 .cmd = DEVLINK_CMD_TRAP_POLICER_SET,
9262 .doit = devlink_nl_cmd_trap_policer_set_doit,
9263 .flags = GENL_ADMIN_PERM,
1e8c6619 9264 },
08f588fa
VG
9265 {
9266 .cmd = DEVLINK_CMD_SELFTESTS_GET,
9267 .doit = devlink_nl_cmd_selftests_get_doit,
5ce76d78 9268 .dumpit = devlink_nl_instance_iter_dump,
08f588fa
VG
9269 /* can be retrieved by unprivileged users */
9270 },
9271 {
9272 .cmd = DEVLINK_CMD_SELFTESTS_RUN,
9273 .doit = devlink_nl_cmd_selftests_run,
9274 .flags = GENL_ADMIN_PERM,
9275 },
623cd13b 9276 /* -- No new ops here! Use split ops going forward! -- */
489111e5
JB
9277};
9278
687125b5 9279bool devlink_reload_actions_valid(const struct devlink_ops *ops)
ccdf0721 9280{
dc64cc7c
MS
9281 const struct devlink_reload_combination *comb;
9282 int i;
9283
ccdf0721
MS
9284 if (!devlink_reload_supported(ops)) {
9285 if (WARN_ON(ops->reload_actions))
9286 return false;
9287 return true;
9288 }
9289
9290 if (WARN_ON(!ops->reload_actions ||
9291 ops->reload_actions & BIT(DEVLINK_RELOAD_ACTION_UNSPEC) ||
9292 ops->reload_actions >= BIT(__DEVLINK_RELOAD_ACTION_MAX)))
9293 return false;
dc64cc7c
MS
9294
9295 if (WARN_ON(ops->reload_limits & BIT(DEVLINK_RELOAD_LIMIT_UNSPEC) ||
9296 ops->reload_limits >= BIT(__DEVLINK_RELOAD_LIMIT_MAX)))
9297 return false;
9298
9299 for (i = 0; i < ARRAY_SIZE(devlink_reload_invalid_combinations); i++) {
9300 comb = &devlink_reload_invalid_combinations[i];
9301 if (ops->reload_actions == BIT(comb->action) &&
9302 ops->reload_limits == BIT(comb->limit))
9303 return false;
9304 }
ccdf0721
MS
9305 return true;
9306}
9307
cf530217
LR
9308static void
9309devlink_trap_policer_notify(struct devlink *devlink,
9310 const struct devlink_trap_policer_item *policer_item,
9311 enum devlink_command cmd);
9312static void
9313devlink_trap_group_notify(struct devlink *devlink,
9314 const struct devlink_trap_group_item *group_item,
9315 enum devlink_command cmd);
9316static void devlink_trap_notify(struct devlink *devlink,
9317 const struct devlink_trap_item *trap_item,
9318 enum devlink_command cmd);
9319
687125b5 9320void devlink_notify_register(struct devlink *devlink)
cf530217
LR
9321{
9322 struct devlink_trap_policer_item *policer_item;
9323 struct devlink_trap_group_item *group_item;
99ad92ef 9324 struct devlink_param_item *param_item;
cf530217
LR
9325 struct devlink_trap_item *trap_item;
9326 struct devlink_port *devlink_port;
c246f9b5 9327 struct devlink_linecard *linecard;
ef91abfb
LR
9328 struct devlink_rate *rate_node;
9329 struct devlink_region *region;
47b438cc 9330 unsigned long port_index;
cf530217
LR
9331
9332 devlink_notify(devlink, DEVLINK_CMD_NEW);
c246f9b5
JP
9333 list_for_each_entry(linecard, &devlink->linecard_list, list)
9334 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
9335
47b438cc 9336 xa_for_each(&devlink->ports, port_index, devlink_port)
cf530217
LR
9337 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
9338
9339 list_for_each_entry(policer_item, &devlink->trap_policer_list, list)
9340 devlink_trap_policer_notify(devlink, policer_item,
9341 DEVLINK_CMD_TRAP_POLICER_NEW);
9342
9343 list_for_each_entry(group_item, &devlink->trap_group_list, list)
9344 devlink_trap_group_notify(devlink, group_item,
9345 DEVLINK_CMD_TRAP_GROUP_NEW);
9346
9347 list_for_each_entry(trap_item, &devlink->trap_list, list)
9348 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW);
9349
ef91abfb
LR
9350 list_for_each_entry(rate_node, &devlink->rate_list, list)
9351 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW);
9352
9353 list_for_each_entry(region, &devlink->region_list, list)
9354 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
9355
99ad92ef
LR
9356 list_for_each_entry(param_item, &devlink->param_list, list)
9357 devlink_param_notify(devlink, 0, param_item,
9358 DEVLINK_CMD_PARAM_NEW);
cf530217
LR
9359}
9360
687125b5 9361void devlink_notify_unregister(struct devlink *devlink)
cf530217
LR
9362{
9363 struct devlink_trap_policer_item *policer_item;
9364 struct devlink_trap_group_item *group_item;
99ad92ef 9365 struct devlink_param_item *param_item;
cf530217
LR
9366 struct devlink_trap_item *trap_item;
9367 struct devlink_port *devlink_port;
ef91abfb
LR
9368 struct devlink_rate *rate_node;
9369 struct devlink_region *region;
47b438cc 9370 unsigned long port_index;
cf530217 9371
99ad92ef
LR
9372 list_for_each_entry_reverse(param_item, &devlink->param_list, list)
9373 devlink_param_notify(devlink, 0, param_item,
9374 DEVLINK_CMD_PARAM_DEL);
cf530217 9375
ef91abfb
LR
9376 list_for_each_entry_reverse(region, &devlink->region_list, list)
9377 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
9378
9379 list_for_each_entry_reverse(rate_node, &devlink->rate_list, list)
9380 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_DEL);
9381
cf530217
LR
9382 list_for_each_entry_reverse(trap_item, &devlink->trap_list, list)
9383 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL);
9384
9385 list_for_each_entry_reverse(group_item, &devlink->trap_group_list, list)
9386 devlink_trap_group_notify(devlink, group_item,
9387 DEVLINK_CMD_TRAP_GROUP_DEL);
9388 list_for_each_entry_reverse(policer_item, &devlink->trap_policer_list,
9389 list)
9390 devlink_trap_policer_notify(devlink, policer_item,
9391 DEVLINK_CMD_TRAP_POLICER_DEL);
9392
47b438cc 9393 xa_for_each(&devlink->ports, port_index, devlink_port)
cf530217
LR
9394 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
9395 devlink_notify(devlink, DEVLINK_CMD_DEL);
9396}
9397
136bf27f
JP
9398static void devlink_port_type_warn(struct work_struct *work)
9399{
9400 WARN(true, "Type was not set for devlink port.");
9401}
9402
9403static bool devlink_port_type_should_warn(struct devlink_port *devlink_port)
9404{
9405 /* Ignore CPU and DSA flavours. */
9406 return devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_CPU &&
cf116634
AL
9407 devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_DSA &&
9408 devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_UNUSED;
136bf27f
JP
9409}
9410
4c582234 9411#define DEVLINK_PORT_TYPE_WARN_TIMEOUT (HZ * 3600)
136bf27f
JP
9412
9413static void devlink_port_type_warn_schedule(struct devlink_port *devlink_port)
9414{
9415 if (!devlink_port_type_should_warn(devlink_port))
9416 return;
9417 /* Schedule a work to WARN in case driver does not set port
9418 * type within timeout.
9419 */
9420 schedule_delayed_work(&devlink_port->type_warn_dw,
9421 DEVLINK_PORT_TYPE_WARN_TIMEOUT);
9422}
9423
9424static void devlink_port_type_warn_cancel(struct devlink_port *devlink_port)
9425{
9426 if (!devlink_port_type_should_warn(devlink_port))
9427 return;
9428 cancel_delayed_work_sync(&devlink_port->type_warn_dw);
9429}
9430
ae3bbc04
JP
9431/**
9432 * devlink_port_init() - Init devlink port
9433 *
9434 * @devlink: devlink
9435 * @devlink_port: devlink port
9436 *
9437 * Initialize essencial stuff that is needed for functions
9438 * that may be called before devlink port registration.
9439 * Call to this function is optional and not needed
9440 * in case the driver does not use such functions.
9441 */
9442void devlink_port_init(struct devlink *devlink,
9443 struct devlink_port *devlink_port)
9444{
9445 if (devlink_port->initialized)
9446 return;
9447 devlink_port->devlink = devlink;
9448 INIT_LIST_HEAD(&devlink_port->region_list);
9449 devlink_port->initialized = true;
9450}
9451EXPORT_SYMBOL_GPL(devlink_port_init);
9452
9453/**
9454 * devlink_port_fini() - Deinitialize devlink port
9455 *
9456 * @devlink_port: devlink port
9457 *
9458 * Deinitialize essencial stuff that is in use for functions
9459 * that may be called after devlink port unregistration.
9460 * Call to this function is optional and not needed
9461 * in case the driver does not use such functions.
9462 */
9463void devlink_port_fini(struct devlink_port *devlink_port)
9464{
9465 WARN_ON(!list_empty(&devlink_port->region_list));
9466}
9467EXPORT_SYMBOL_GPL(devlink_port_fini);
9468
1abfb265
JP
9469/**
9470 * devl_port_register() - Register devlink port
9471 *
9472 * @devlink: devlink
9473 * @devlink_port: devlink port
9474 * @port_index: driver-specific numerical identifier of the port
9475 *
9476 * Register devlink port with provided port index. User can use
9477 * any indexing, even hw-related one. devlink_port structure
9478 * is convenient to be embedded inside user driver private structure.
9479 * Note that the caller should take care of zeroing the devlink_port
9480 * structure.
9481 */
2cb7b489
JK
9482int devl_port_register(struct devlink *devlink,
9483 struct devlink_port *devlink_port,
9484 unsigned int port_index)
9485{
47b438cc 9486 int err;
2cb7b489 9487
47b438cc 9488 devl_assert_locked(devlink);
2cb7b489 9489
3fcb698d
JP
9490 ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port);
9491
ae3bbc04 9492 devlink_port_init(devlink, devlink_port);
081adcfe 9493 devlink_port->registered = true;
2cb7b489
JK
9494 devlink_port->index = port_index;
9495 spin_lock_init(&devlink_port->type_lock);
9496 INIT_LIST_HEAD(&devlink_port->reporter_list);
47b438cc 9497 err = xa_insert(&devlink->ports, port_index, devlink_port, GFP_KERNEL);
1dea3b4e 9498 if (err)
47b438cc 9499 return err;
2cb7b489
JK
9500
9501 INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn);
9502 devlink_port_type_warn_schedule(devlink_port);
9503 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
9504 return 0;
9505}
9506EXPORT_SYMBOL_GPL(devl_port_register);
9507
bfcd3a46
JP
9508/**
9509 * devlink_port_register - Register devlink port
9510 *
9511 * @devlink: devlink
9512 * @devlink_port: devlink port
eeaadd82 9513 * @port_index: driver-specific numerical identifier of the port
bfcd3a46
JP
9514 *
9515 * Register devlink port with provided port index. User can use
9516 * any indexing, even hw-related one. devlink_port structure
9517 * is convenient to be embedded inside user driver private structure.
9518 * Note that the caller should take care of zeroing the devlink_port
9519 * structure.
1abfb265
JP
9520 *
9521 * Context: Takes and release devlink->lock <mutex>.
bfcd3a46
JP
9522 */
9523int devlink_port_register(struct devlink *devlink,
9524 struct devlink_port *devlink_port,
9525 unsigned int port_index)
9526{
2cb7b489 9527 int err;
d7907a2b 9528
7715023a 9529 devl_lock(devlink);
2cb7b489 9530 err = devl_port_register(devlink, devlink_port, port_index);
7715023a 9531 devl_unlock(devlink);
2cb7b489 9532 return err;
bfcd3a46
JP
9533}
9534EXPORT_SYMBOL_GPL(devlink_port_register);
9535
1abfb265
JP
9536/**
9537 * devl_port_unregister() - Unregister devlink port
9538 *
9539 * @devlink_port: devlink port
9540 */
2cb7b489
JK
9541void devl_port_unregister(struct devlink_port *devlink_port)
9542{
9543 lockdep_assert_held(&devlink_port->devlink->lock);
e705a621 9544 WARN_ON(devlink_port->type != DEVLINK_PORT_TYPE_NOTSET);
2cb7b489
JK
9545
9546 devlink_port_type_warn_cancel(devlink_port);
9547 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
47b438cc 9548 xa_erase(&devlink_port->devlink->ports, devlink_port->index);
2cb7b489 9549 WARN_ON(!list_empty(&devlink_port->reporter_list));
081adcfe 9550 devlink_port->registered = false;
2cb7b489
JK
9551}
9552EXPORT_SYMBOL_GPL(devl_port_unregister);
9553
bfcd3a46
JP
9554/**
9555 * devlink_port_unregister - Unregister devlink port
9556 *
9557 * @devlink_port: devlink port
1abfb265
JP
9558 *
9559 * Context: Takes and release devlink->lock <mutex>.
bfcd3a46
JP
9560 */
9561void devlink_port_unregister(struct devlink_port *devlink_port)
9562{
2406e7e5
AS
9563 struct devlink *devlink = devlink_port->devlink;
9564
7715023a 9565 devl_lock(devlink);
2cb7b489 9566 devl_port_unregister(devlink_port);
7715023a 9567 devl_unlock(devlink);
bfcd3a46
JP
9568}
9569EXPORT_SYMBOL_GPL(devlink_port_unregister);
9570
3ea87ca7
JK
9571static void devlink_port_type_netdev_checks(struct devlink_port *devlink_port,
9572 struct net_device *netdev)
bfcd3a46 9573{
119c0b57
JP
9574 const struct net_device_ops *ops = netdev->netdev_ops;
9575
746364f2
JP
9576 /* If driver registers devlink port, it should set devlink port
9577 * attributes accordingly so the compat functions are called
9578 * and the original ops are not used.
9579 */
119c0b57 9580 if (ops->ndo_get_phys_port_name) {
746364f2
JP
9581 /* Some drivers use the same set of ndos for netdevs
9582 * that have devlink_port registered and also for
9583 * those who don't. Make sure that ndo_get_phys_port_name
9584 * returns -EOPNOTSUPP here in case it is defined.
9585 * Warn if not.
9586 */
746364f2
JP
9587 char name[IFNAMSIZ];
9588 int err;
9589
9590 err = ops->ndo_get_phys_port_name(netdev, name, sizeof(name));
9591 WARN_ON(err != -EOPNOTSUPP);
9592 }
119c0b57
JP
9593 if (ops->ndo_get_port_parent_id) {
9594 /* Some drivers use the same set of ndos for netdevs
9595 * that have devlink_port registered and also for
9596 * those who don't. Make sure that ndo_get_port_parent_id
9597 * returns -EOPNOTSUPP here in case it is defined.
9598 * Warn if not.
9599 */
9600 struct netdev_phys_item_id ppid;
9601 int err;
9602
9603 err = ops->ndo_get_port_parent_id(netdev, &ppid);
9604 WARN_ON(err != -EOPNOTSUPP);
9605 }
3ea87ca7
JK
9606}
9607
45791e0d
JP
9608static void __devlink_port_type_set(struct devlink_port *devlink_port,
9609 enum devlink_port_type type,
31265c1e 9610 void *type_dev)
45791e0d
JP
9611{
9612 struct net_device *netdev = type_dev;
9613
9614 ASSERT_DEVLINK_PORT_REGISTERED(devlink_port);
9615
9616 if (type == DEVLINK_PORT_TYPE_NOTSET) {
9617 devlink_port_type_warn_schedule(devlink_port);
9618 } else {
9619 devlink_port_type_warn_cancel(devlink_port);
9620 if (type == DEVLINK_PORT_TYPE_ETH && netdev)
9621 devlink_port_type_netdev_checks(devlink_port, netdev);
9622 }
9623
9624 spin_lock_bh(&devlink_port->type_lock);
9625 devlink_port->type = type;
9626 switch (type) {
9627 case DEVLINK_PORT_TYPE_ETH:
9628 devlink_port->type_eth.netdev = netdev;
31265c1e
JP
9629 if (netdev) {
9630 ASSERT_RTNL();
9631 devlink_port->type_eth.ifindex = netdev->ifindex;
9632 BUILD_BUG_ON(sizeof(devlink_port->type_eth.ifname) !=
9633 sizeof(netdev->name));
9634 strcpy(devlink_port->type_eth.ifname, netdev->name);
9635 }
45791e0d
JP
9636 break;
9637 case DEVLINK_PORT_TYPE_IB:
9638 devlink_port->type_ib.ibdev = type_dev;
9639 break;
9640 default:
9641 break;
9642 }
9643 spin_unlock_bh(&devlink_port->type_lock);
31265c1e 9644 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
45791e0d
JP
9645}
9646
3ea87ca7
JK
9647/**
9648 * devlink_port_type_eth_set - Set port type to Ethernet
9649 *
9650 * @devlink_port: devlink port
c8096578
JP
9651 *
9652 * If driver is calling this, most likely it is doing something wrong.
3ea87ca7 9653 */
c8096578 9654void devlink_port_type_eth_set(struct devlink_port *devlink_port)
3ea87ca7 9655{
c8096578
JP
9656 dev_warn(devlink_port->devlink->dev,
9657 "devlink port type for port %d set to Ethernet without a software interface reference, device type not supported by the kernel?\n",
9658 devlink_port->index);
31265c1e 9659 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, NULL);
bfcd3a46
JP
9660}
9661EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
9662
9663/**
9664 * devlink_port_type_ib_set - Set port type to InfiniBand
9665 *
9666 * @devlink_port: devlink port
9667 * @ibdev: related IB device
9668 */
9669void devlink_port_type_ib_set(struct devlink_port *devlink_port,
9670 struct ib_device *ibdev)
9671{
31265c1e 9672 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_IB, ibdev);
bfcd3a46
JP
9673}
9674EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
9675
9676/**
9677 * devlink_port_type_clear - Clear port type
9678 *
9679 * @devlink_port: devlink port
c8096578
JP
9680 *
9681 * If driver is calling this for clearing Ethernet type, most likely
9682 * it is doing something wrong.
bfcd3a46
JP
9683 */
9684void devlink_port_type_clear(struct devlink_port *devlink_port)
9685{
c8096578
JP
9686 if (devlink_port->type == DEVLINK_PORT_TYPE_ETH)
9687 dev_warn(devlink_port->devlink->dev,
9688 "devlink port type for port %d cleared without a software interface reference, device type not supported by the kernel?\n",
9689 devlink_port->index);
31265c1e 9690 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL);
bfcd3a46
JP
9691}
9692EXPORT_SYMBOL_GPL(devlink_port_type_clear);
9693
687125b5
JK
9694int devlink_port_netdevice_event(struct notifier_block *nb,
9695 unsigned long event, void *ptr)
02a68a47
JP
9696{
9697 struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
9698 struct devlink_port *devlink_port = netdev->devlink_port;
9699 struct devlink *devlink;
9700
9701 devlink = container_of(nb, struct devlink, netdevice_nb);
9702
9703 if (!devlink_port || devlink_port->devlink != devlink)
9704 return NOTIFY_OK;
9705
9706 switch (event) {
9707 case NETDEV_POST_INIT:
9708 /* Set the type but not netdev pointer. It is going to be set
9709 * later on by NETDEV_REGISTER event. Happens once during
9710 * netdevice register
9711 */
9712 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH,
31265c1e 9713 NULL);
02a68a47
JP
9714 break;
9715 case NETDEV_REGISTER:
31265c1e 9716 case NETDEV_CHANGENAME:
02a68a47
JP
9717 /* Set the netdev on top of previously set type. Note this
9718 * event happens also during net namespace change so here
9719 * we take into account netdev pointer appearing in this
9720 * namespace.
9721 */
1fb22ed6 9722 __devlink_port_type_set(devlink_port, devlink_port->type,
31265c1e 9723 netdev);
02a68a47
JP
9724 break;
9725 case NETDEV_UNREGISTER:
9726 /* Clear netdev pointer, but not the type. This event happens
9727 * also during net namespace change so we need to clear
9728 * pointer to netdev that is going to another net namespace.
9729 */
1fb22ed6 9730 __devlink_port_type_set(devlink_port, devlink_port->type,
31265c1e 9731 NULL);
02a68a47
JP
9732 break;
9733 case NETDEV_PRE_UNINIT:
9734 /* Clear the type and the netdev pointer. Happens one during
9735 * netdevice unregister.
9736 */
9737 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET,
31265c1e 9738 NULL);
02a68a47
JP
9739 break;
9740 }
9741
9742 return NOTIFY_OK;
9743}
9744
378ef01b 9745static int __devlink_port_attrs_set(struct devlink_port *devlink_port,
71ad8d55 9746 enum devlink_port_flavour flavour)
378ef01b
PP
9747{
9748 struct devlink_port_attrs *attrs = &devlink_port->attrs;
9749
10a429ba 9750 devlink_port->attrs_set = true;
378ef01b 9751 attrs->flavour = flavour;
71ad8d55 9752 if (attrs->switch_id.id_len) {
46737a19 9753 devlink_port->switch_port = true;
71ad8d55
DR
9754 if (WARN_ON(attrs->switch_id.id_len > MAX_PHYS_ITEM_ID_LEN))
9755 attrs->switch_id.id_len = MAX_PHYS_ITEM_ID_LEN;
378ef01b 9756 } else {
46737a19 9757 devlink_port->switch_port = false;
378ef01b
PP
9758 }
9759 return 0;
9760}
9761
bfcd3a46 9762/**
b9ffcbaf 9763 * devlink_port_attrs_set - Set port attributes
bfcd3a46
JP
9764 *
9765 * @devlink_port: devlink port
71ad8d55 9766 * @attrs: devlink port attrs
bfcd3a46 9767 */
b9ffcbaf 9768void devlink_port_attrs_set(struct devlink_port *devlink_port,
71ad8d55 9769 struct devlink_port_attrs *attrs)
bfcd3a46 9770{
378ef01b 9771 int ret;
b9ffcbaf 9772
3fcb698d
JP
9773 ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port);
9774
71ad8d55
DR
9775 devlink_port->attrs = *attrs;
9776 ret = __devlink_port_attrs_set(devlink_port, attrs->flavour);
378ef01b 9777 if (ret)
45b86112 9778 return;
a0f49b54 9779 WARN_ON(attrs->splittable && attrs->split);
bfcd3a46 9780}
b9ffcbaf 9781EXPORT_SYMBOL_GPL(devlink_port_attrs_set);
bfcd3a46 9782
98fd2d65
PP
9783/**
9784 * devlink_port_attrs_pci_pf_set - Set PCI PF port attributes
9785 *
9786 * @devlink_port: devlink port
3a2d9588 9787 * @controller: associated controller number for the devlink port instance
98fd2d65 9788 * @pf: associated PF for the devlink port instance
05b595e9 9789 * @external: indicates if the port is for an external controller
98fd2d65 9790 */
3a2d9588
PP
9791void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u32 controller,
9792 u16 pf, bool external)
98fd2d65
PP
9793{
9794 struct devlink_port_attrs *attrs = &devlink_port->attrs;
9795 int ret;
9796
3fcb698d
JP
9797 ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port);
9798
98fd2d65 9799 ret = __devlink_port_attrs_set(devlink_port,
71ad8d55 9800 DEVLINK_PORT_FLAVOUR_PCI_PF);
98fd2d65
PP
9801 if (ret)
9802 return;
3a2d9588 9803 attrs->pci_pf.controller = controller;
98fd2d65 9804 attrs->pci_pf.pf = pf;
05b595e9 9805 attrs->pci_pf.external = external;
98fd2d65
PP
9806}
9807EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_pf_set);
9808
e41b6bf3
PP
9809/**
9810 * devlink_port_attrs_pci_vf_set - Set PCI VF port attributes
9811 *
9812 * @devlink_port: devlink port
3a2d9588 9813 * @controller: associated controller number for the devlink port instance
e41b6bf3
PP
9814 * @pf: associated PF for the devlink port instance
9815 * @vf: associated VF of a PF for the devlink port instance
05b595e9 9816 * @external: indicates if the port is for an external controller
e41b6bf3 9817 */
3a2d9588 9818void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, u32 controller,
05b595e9 9819 u16 pf, u16 vf, bool external)
e41b6bf3
PP
9820{
9821 struct devlink_port_attrs *attrs = &devlink_port->attrs;
9822 int ret;
9823
3fcb698d
JP
9824 ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port);
9825
e41b6bf3 9826 ret = __devlink_port_attrs_set(devlink_port,
71ad8d55 9827 DEVLINK_PORT_FLAVOUR_PCI_VF);
e41b6bf3
PP
9828 if (ret)
9829 return;
3a2d9588 9830 attrs->pci_vf.controller = controller;
e41b6bf3
PP
9831 attrs->pci_vf.pf = pf;
9832 attrs->pci_vf.vf = vf;
05b595e9 9833 attrs->pci_vf.external = external;
e41b6bf3
PP
9834}
9835EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_vf_set);
9836
b8288837
PP
9837/**
9838 * devlink_port_attrs_pci_sf_set - Set PCI SF port attributes
9839 *
9840 * @devlink_port: devlink port
9841 * @controller: associated controller number for the devlink port instance
9842 * @pf: associated PF for the devlink port instance
9843 * @sf: associated SF of a PF for the devlink port instance
a1ab3e45 9844 * @external: indicates if the port is for an external controller
b8288837
PP
9845 */
9846void devlink_port_attrs_pci_sf_set(struct devlink_port *devlink_port, u32 controller,
a1ab3e45 9847 u16 pf, u32 sf, bool external)
b8288837
PP
9848{
9849 struct devlink_port_attrs *attrs = &devlink_port->attrs;
9850 int ret;
9851
3fcb698d
JP
9852 ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port);
9853
b8288837
PP
9854 ret = __devlink_port_attrs_set(devlink_port,
9855 DEVLINK_PORT_FLAVOUR_PCI_SF);
9856 if (ret)
9857 return;
9858 attrs->pci_sf.controller = controller;
9859 attrs->pci_sf.pf = pf;
9860 attrs->pci_sf.sf = sf;
a1ab3e45 9861 attrs->pci_sf.external = external;
b8288837
PP
9862}
9863EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_sf_set);
9864
caba177d
MW
9865/**
9866 * devl_rate_node_create - create devlink rate node
9867 * @devlink: devlink instance
9868 * @priv: driver private data
9869 * @node_name: name of the resulting node
9870 * @parent: parent devlink_rate struct
9871 *
9872 * Create devlink rate object of type node
9873 */
9874struct devlink_rate *
9875devl_rate_node_create(struct devlink *devlink, void *priv, char *node_name,
9876 struct devlink_rate *parent)
9877{
9878 struct devlink_rate *rate_node;
9879
9880 rate_node = devlink_rate_node_get_by_name(devlink, node_name);
9881 if (!IS_ERR(rate_node))
9882 return ERR_PTR(-EEXIST);
9883
9884 rate_node = kzalloc(sizeof(*rate_node), GFP_KERNEL);
9885 if (!rate_node)
9886 return ERR_PTR(-ENOMEM);
9887
9888 if (parent) {
9889 rate_node->parent = parent;
9890 refcount_inc(&rate_node->parent->refcnt);
9891 }
9892
9893 rate_node->type = DEVLINK_RATE_TYPE_NODE;
9894 rate_node->devlink = devlink;
9895 rate_node->priv = priv;
9896
9897 rate_node->name = kstrdup(node_name, GFP_KERNEL);
9898 if (!rate_node->name) {
9899 kfree(rate_node);
9900 return ERR_PTR(-ENOMEM);
9901 }
9902
9903 refcount_set(&rate_node->refcnt, 1);
9904 list_add(&rate_node->list, &devlink->rate_list);
9905 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW);
9906 return rate_node;
9907}
9908EXPORT_SYMBOL_GPL(devl_rate_node_create);
9909
4677efc4 9910/**
8879b32a 9911 * devl_rate_leaf_create - create devlink rate leaf
4677efc4
DL
9912 * @devlink_port: devlink port object to create rate object on
9913 * @priv: driver private data
f2fc15e2 9914 * @parent: parent devlink_rate struct
4677efc4
DL
9915 *
9916 * Create devlink rate object of type leaf on provided @devlink_port.
4677efc4 9917 */
f2fc15e2
MW
9918int devl_rate_leaf_create(struct devlink_port *devlink_port, void *priv,
9919 struct devlink_rate *parent)
4677efc4
DL
9920{
9921 struct devlink *devlink = devlink_port->devlink;
9922 struct devlink_rate *devlink_rate;
9923
8879b32a
JK
9924 devl_assert_locked(devlink_port->devlink);
9925
9926 if (WARN_ON(devlink_port->devlink_rate))
9927 return -EBUSY;
9928
4677efc4
DL
9929 devlink_rate = kzalloc(sizeof(*devlink_rate), GFP_KERNEL);
9930 if (!devlink_rate)
9931 return -ENOMEM;
9932
f2fc15e2
MW
9933 if (parent) {
9934 devlink_rate->parent = parent;
9935 refcount_inc(&devlink_rate->parent->refcnt);
9936 }
9937
4677efc4
DL
9938 devlink_rate->type = DEVLINK_RATE_TYPE_LEAF;
9939 devlink_rate->devlink = devlink;
9940 devlink_rate->devlink_port = devlink_port;
9941 devlink_rate->priv = priv;
9942 list_add_tail(&devlink_rate->list, &devlink->rate_list);
9943 devlink_port->devlink_rate = devlink_rate;
9944 devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_NEW);
4677efc4
DL
9945
9946 return 0;
9947}
8879b32a
JK
9948EXPORT_SYMBOL_GPL(devl_rate_leaf_create);
9949
df539fc6
MS
9950/**
9951 * devl_rate_leaf_destroy - destroy devlink rate leaf
9952 *
9953 * @devlink_port: devlink port linked to the rate object
9954 *
9955 * Destroy the devlink rate object of type leaf on provided @devlink_port.
9956 */
8879b32a
JK
9957void devl_rate_leaf_destroy(struct devlink_port *devlink_port)
9958{
9959 struct devlink_rate *devlink_rate = devlink_port->devlink_rate;
9960
9961 devl_assert_locked(devlink_port->devlink);
9962 if (!devlink_rate)
9963 return;
9964
9965 devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_DEL);
9966 if (devlink_rate->parent)
9967 refcount_dec(&devlink_rate->parent->refcnt);
9968 list_del(&devlink_rate->list);
9969 devlink_port->devlink_rate = NULL;
9970 kfree(devlink_rate);
9971}
9972EXPORT_SYMBOL_GPL(devl_rate_leaf_destroy);
9973
a8ecb93e 9974/**
8879b32a 9975 * devl_rate_nodes_destroy - destroy all devlink rate nodes on device
a8ecb93e
DL
9976 * @devlink: devlink instance
9977 *
d7555984
DL
9978 * Unset parent for all rate objects and destroy all rate nodes
9979 * on specified device.
a8ecb93e 9980 */
8879b32a 9981void devl_rate_nodes_destroy(struct devlink *devlink)
a8ecb93e
DL
9982{
9983 static struct devlink_rate *devlink_rate, *tmp;
9984 const struct devlink_ops *ops = devlink->ops;
9985
8879b32a
JK
9986 devl_assert_locked(devlink);
9987
d7555984
DL
9988 list_for_each_entry(devlink_rate, &devlink->rate_list, list) {
9989 if (!devlink_rate->parent)
9990 continue;
9991
9992 refcount_dec(&devlink_rate->parent->refcnt);
9993 if (devlink_rate_is_leaf(devlink_rate))
9994 ops->rate_leaf_parent_set(devlink_rate, NULL, devlink_rate->priv,
9995 NULL, NULL);
9996 else if (devlink_rate_is_node(devlink_rate))
9997 ops->rate_node_parent_set(devlink_rate, NULL, devlink_rate->priv,
9998 NULL, NULL);
9999 }
a8ecb93e
DL
10000 list_for_each_entry_safe(devlink_rate, tmp, &devlink->rate_list, list) {
10001 if (devlink_rate_is_node(devlink_rate)) {
10002 ops->rate_node_del(devlink_rate, devlink_rate->priv, NULL);
10003 list_del(&devlink_rate->list);
10004 kfree(devlink_rate->name);
10005 kfree(devlink_rate);
10006 }
10007 }
8879b32a
JK
10008}
10009EXPORT_SYMBOL_GPL(devl_rate_nodes_destroy);
10010
b8375859
JP
10011/**
10012 * devlink_port_linecard_set - Link port with a linecard
10013 *
10014 * @devlink_port: devlink port
10015 * @linecard: devlink linecard
10016 */
10017void devlink_port_linecard_set(struct devlink_port *devlink_port,
10018 struct devlink_linecard *linecard)
10019{
3fcb698d
JP
10020 ASSERT_DEVLINK_PORT_NOT_REGISTERED(devlink_port);
10021
b8375859
JP
10022 devlink_port->linecard = linecard;
10023}
10024EXPORT_SYMBOL_GPL(devlink_port_linecard_set);
10025
af3836df
JP
10026static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port,
10027 char *name, size_t len)
08474c1a
JP
10028{
10029 struct devlink_port_attrs *attrs = &devlink_port->attrs;
10030 int n = 0;
10031
10a429ba 10032 if (!devlink_port->attrs_set)
08474c1a
JP
10033 return -EOPNOTSUPP;
10034
10035 switch (attrs->flavour) {
10036 case DEVLINK_PORT_FLAVOUR_PHYSICAL:
b8375859
JP
10037 if (devlink_port->linecard)
10038 n = snprintf(name, len, "l%u",
10039 devlink_port->linecard->index);
10040 if (n < len)
10041 n += snprintf(name + n, len - n, "p%u",
10042 attrs->phys.port_number);
f285f37c
JP
10043 if (n < len && attrs->split)
10044 n += snprintf(name + n, len - n, "s%u",
10045 attrs->phys.split_subport_number);
08474c1a
JP
10046 break;
10047 case DEVLINK_PORT_FLAVOUR_CPU:
10048 case DEVLINK_PORT_FLAVOUR_DSA:
cf116634 10049 case DEVLINK_PORT_FLAVOUR_UNUSED:
08474c1a
JP
10050 /* As CPU and DSA ports do not have a netdevice associated
10051 * case should not ever happen.
10052 */
10053 WARN_ON(1);
10054 return -EINVAL;
98fd2d65 10055 case DEVLINK_PORT_FLAVOUR_PCI_PF:
66b17082
PP
10056 if (attrs->pci_pf.external) {
10057 n = snprintf(name, len, "c%u", attrs->pci_pf.controller);
10058 if (n >= len)
10059 return -EINVAL;
10060 len -= n;
10061 name += n;
10062 }
98fd2d65
PP
10063 n = snprintf(name, len, "pf%u", attrs->pci_pf.pf);
10064 break;
e41b6bf3 10065 case DEVLINK_PORT_FLAVOUR_PCI_VF:
66b17082
PP
10066 if (attrs->pci_vf.external) {
10067 n = snprintf(name, len, "c%u", attrs->pci_vf.controller);
10068 if (n >= len)
10069 return -EINVAL;
10070 len -= n;
10071 name += n;
10072 }
e41b6bf3
PP
10073 n = snprintf(name, len, "pf%uvf%u",
10074 attrs->pci_vf.pf, attrs->pci_vf.vf);
10075 break;
b8288837 10076 case DEVLINK_PORT_FLAVOUR_PCI_SF:
a1ab3e45
PP
10077 if (attrs->pci_sf.external) {
10078 n = snprintf(name, len, "c%u", attrs->pci_sf.controller);
10079 if (n >= len)
10080 return -EINVAL;
10081 len -= n;
10082 name += n;
10083 }
b8288837
PP
10084 n = snprintf(name, len, "pf%usf%u", attrs->pci_sf.pf,
10085 attrs->pci_sf.sf);
10086 break;
149ea30f
PP
10087 case DEVLINK_PORT_FLAVOUR_VIRTUAL:
10088 return -EOPNOTSUPP;
08474c1a
JP
10089 }
10090
10091 if (n >= len)
10092 return -EINVAL;
10093
10094 return 0;
10095}
af3836df 10096
fcdc8ce2
JP
10097static int devlink_linecard_types_init(struct devlink_linecard *linecard)
10098{
10099 struct devlink_linecard_type *linecard_type;
10100 unsigned int count;
10101 int i;
10102
10103 count = linecard->ops->types_count(linecard, linecard->priv);
10104 linecard->types = kmalloc_array(count, sizeof(*linecard_type),
10105 GFP_KERNEL);
10106 if (!linecard->types)
10107 return -ENOMEM;
10108 linecard->types_count = count;
10109
10110 for (i = 0; i < count; i++) {
10111 linecard_type = &linecard->types[i];
10112 linecard->ops->types_get(linecard, linecard->priv, i,
10113 &linecard_type->type,
10114 &linecard_type->priv);
10115 }
10116 return 0;
10117}
10118
10119static void devlink_linecard_types_fini(struct devlink_linecard *linecard)
10120{
10121 kfree(linecard->types);
10122}
10123
c246f9b5 10124/**
5cc9049c 10125 * devl_linecard_create - Create devlink linecard
c246f9b5
JP
10126 *
10127 * @devlink: devlink
10128 * @linecard_index: driver-specific numerical identifier of the linecard
fcdc8ce2
JP
10129 * @ops: linecards ops
10130 * @priv: user priv pointer
c246f9b5
JP
10131 *
10132 * Create devlink linecard instance with provided linecard index.
10133 * Caller can use any indexing, even hw-related one.
fcdc8ce2
JP
10134 *
10135 * Return: Line card structure or an ERR_PTR() encoded error code.
c246f9b5 10136 */
fcdc8ce2 10137struct devlink_linecard *
5cc9049c
JP
10138devl_linecard_create(struct devlink *devlink, unsigned int linecard_index,
10139 const struct devlink_linecard_ops *ops, void *priv)
c246f9b5
JP
10140{
10141 struct devlink_linecard *linecard;
fcdc8ce2
JP
10142 int err;
10143
10144 if (WARN_ON(!ops || !ops->provision || !ops->unprovision ||
10145 !ops->types_count || !ops->types_get))
10146 return ERR_PTR(-EINVAL);
c246f9b5 10147
5cc9049c 10148 if (devlink_linecard_index_exists(devlink, linecard_index))
c246f9b5 10149 return ERR_PTR(-EEXIST);
c246f9b5
JP
10150
10151 linecard = kzalloc(sizeof(*linecard), GFP_KERNEL);
5cc9049c 10152 if (!linecard)
c246f9b5 10153 return ERR_PTR(-ENOMEM);
c246f9b5
JP
10154
10155 linecard->devlink = devlink;
10156 linecard->index = linecard_index;
fcdc8ce2
JP
10157 linecard->ops = ops;
10158 linecard->priv = priv;
10159 linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED;
10160 mutex_init(&linecard->state_lock);
10161
10162 err = devlink_linecard_types_init(linecard);
10163 if (err) {
10164 mutex_destroy(&linecard->state_lock);
10165 kfree(linecard);
fcdc8ce2
JP
10166 return ERR_PTR(err);
10167 }
10168
c246f9b5 10169 list_add_tail(&linecard->list, &devlink->linecard_list);
c246f9b5
JP
10170 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
10171 return linecard;
10172}
5cc9049c 10173EXPORT_SYMBOL_GPL(devl_linecard_create);
c246f9b5
JP
10174
10175/**
5cc9049c 10176 * devl_linecard_destroy - Destroy devlink linecard
c246f9b5
JP
10177 *
10178 * @linecard: devlink linecard
10179 */
5cc9049c 10180void devl_linecard_destroy(struct devlink_linecard *linecard)
c246f9b5 10181{
c246f9b5 10182 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_DEL);
c246f9b5 10183 list_del(&linecard->list);
fcdc8ce2 10184 devlink_linecard_types_fini(linecard);
3a10173f
JP
10185 mutex_destroy(&linecard->state_lock);
10186 kfree(linecard);
c246f9b5 10187}
5cc9049c 10188EXPORT_SYMBOL_GPL(devl_linecard_destroy);
c246f9b5 10189
fcdc8ce2
JP
10190/**
10191 * devlink_linecard_provision_set - Set provisioning on linecard
10192 *
10193 * @linecard: devlink linecard
10194 * @type: linecard type
10195 *
10196 * This is either called directly from the provision() op call or
10197 * as a result of the provision() op call asynchronously.
10198 */
10199void devlink_linecard_provision_set(struct devlink_linecard *linecard,
10200 const char *type)
10201{
10202 mutex_lock(&linecard->state_lock);
10203 WARN_ON(linecard->type && strcmp(linecard->type, type));
10204 linecard->state = DEVLINK_LINECARD_STATE_PROVISIONED;
10205 linecard->type = type;
10206 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
10207 mutex_unlock(&linecard->state_lock);
10208}
10209EXPORT_SYMBOL_GPL(devlink_linecard_provision_set);
10210
10211/**
10212 * devlink_linecard_provision_clear - Clear provisioning on linecard
10213 *
10214 * @linecard: devlink linecard
10215 *
10216 * This is either called directly from the unprovision() op call or
10217 * as a result of the unprovision() op call asynchronously.
10218 */
10219void devlink_linecard_provision_clear(struct devlink_linecard *linecard)
10220{
10221 mutex_lock(&linecard->state_lock);
7b2d9a1a 10222 WARN_ON(linecard->nested_devlink);
fcdc8ce2
JP
10223 linecard->state = DEVLINK_LINECARD_STATE_UNPROVISIONED;
10224 linecard->type = NULL;
10225 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
10226 mutex_unlock(&linecard->state_lock);
10227}
10228EXPORT_SYMBOL_GPL(devlink_linecard_provision_clear);
10229
10230/**
10231 * devlink_linecard_provision_fail - Fail provisioning on linecard
10232 *
10233 * @linecard: devlink linecard
10234 *
10235 * This is either called directly from the provision() op call or
10236 * as a result of the provision() op call asynchronously.
10237 */
10238void devlink_linecard_provision_fail(struct devlink_linecard *linecard)
10239{
10240 mutex_lock(&linecard->state_lock);
7b2d9a1a 10241 WARN_ON(linecard->nested_devlink);
fcdc8ce2
JP
10242 linecard->state = DEVLINK_LINECARD_STATE_PROVISIONING_FAILED;
10243 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
10244 mutex_unlock(&linecard->state_lock);
10245}
10246EXPORT_SYMBOL_GPL(devlink_linecard_provision_fail);
10247
fc9f50d5
JP
10248/**
10249 * devlink_linecard_activate - Set linecard active
10250 *
10251 * @linecard: devlink linecard
10252 */
10253void devlink_linecard_activate(struct devlink_linecard *linecard)
10254{
10255 mutex_lock(&linecard->state_lock);
10256 WARN_ON(linecard->state != DEVLINK_LINECARD_STATE_PROVISIONED);
10257 linecard->state = DEVLINK_LINECARD_STATE_ACTIVE;
10258 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
10259 mutex_unlock(&linecard->state_lock);
10260}
10261EXPORT_SYMBOL_GPL(devlink_linecard_activate);
10262
10263/**
10264 * devlink_linecard_deactivate - Set linecard inactive
10265 *
10266 * @linecard: devlink linecard
10267 */
10268void devlink_linecard_deactivate(struct devlink_linecard *linecard)
10269{
10270 mutex_lock(&linecard->state_lock);
10271 switch (linecard->state) {
10272 case DEVLINK_LINECARD_STATE_ACTIVE:
10273 linecard->state = DEVLINK_LINECARD_STATE_PROVISIONED;
10274 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
10275 break;
10276 case DEVLINK_LINECARD_STATE_UNPROVISIONING:
10277 /* Line card is being deactivated as part
10278 * of unprovisioning flow.
10279 */
10280 break;
10281 default:
10282 WARN_ON(1);
10283 break;
10284 }
10285 mutex_unlock(&linecard->state_lock);
10286}
10287EXPORT_SYMBOL_GPL(devlink_linecard_deactivate);
10288
7b2d9a1a
JP
10289/**
10290 * devlink_linecard_nested_dl_set - Attach/detach nested devlink
10291 * instance to linecard.
10292 *
10293 * @linecard: devlink linecard
10294 * @nested_devlink: devlink instance to attach or NULL to detach
10295 */
10296void devlink_linecard_nested_dl_set(struct devlink_linecard *linecard,
10297 struct devlink *nested_devlink)
10298{
10299 mutex_lock(&linecard->state_lock);
10300 linecard->nested_devlink = nested_devlink;
10301 devlink_linecard_notify(linecard, DEVLINK_CMD_LINECARD_NEW);
10302 mutex_unlock(&linecard->state_lock);
10303}
10304EXPORT_SYMBOL_GPL(devlink_linecard_nested_dl_set);
10305
755cfa69
JP
10306int devl_sb_register(struct devlink *devlink, unsigned int sb_index,
10307 u32 size, u16 ingress_pools_count,
10308 u16 egress_pools_count, u16 ingress_tc_count,
10309 u16 egress_tc_count)
bf797471
JP
10310{
10311 struct devlink_sb *devlink_sb;
bf797471 10312
755cfa69
JP
10313 lockdep_assert_held(&devlink->lock);
10314
10315 if (devlink_sb_index_exists(devlink, sb_index))
10316 return -EEXIST;
bf797471
JP
10317
10318 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL);
755cfa69
JP
10319 if (!devlink_sb)
10320 return -ENOMEM;
bf797471
JP
10321 devlink_sb->index = sb_index;
10322 devlink_sb->size = size;
10323 devlink_sb->ingress_pools_count = ingress_pools_count;
10324 devlink_sb->egress_pools_count = egress_pools_count;
10325 devlink_sb->ingress_tc_count = ingress_tc_count;
10326 devlink_sb->egress_tc_count = egress_tc_count;
10327 list_add_tail(&devlink_sb->list, &devlink->sb_list);
755cfa69
JP
10328 return 0;
10329}
10330EXPORT_SYMBOL_GPL(devl_sb_register);
10331
10332int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
10333 u32 size, u16 ingress_pools_count,
10334 u16 egress_pools_count, u16 ingress_tc_count,
10335 u16 egress_tc_count)
10336{
10337 int err;
10338
10339 devl_lock(devlink);
10340 err = devl_sb_register(devlink, sb_index, size, ingress_pools_count,
10341 egress_pools_count, ingress_tc_count,
10342 egress_tc_count);
7715023a 10343 devl_unlock(devlink);
bf797471
JP
10344 return err;
10345}
10346EXPORT_SYMBOL_GPL(devlink_sb_register);
10347
755cfa69 10348void devl_sb_unregister(struct devlink *devlink, unsigned int sb_index)
bf797471
JP
10349{
10350 struct devlink_sb *devlink_sb;
10351
755cfa69
JP
10352 lockdep_assert_held(&devlink->lock);
10353
bf797471
JP
10354 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
10355 WARN_ON(!devlink_sb);
10356 list_del(&devlink_sb->list);
bf797471
JP
10357 kfree(devlink_sb);
10358}
755cfa69
JP
10359EXPORT_SYMBOL_GPL(devl_sb_unregister);
10360
10361void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index)
10362{
10363 devl_lock(devlink);
10364 devl_sb_unregister(devlink, sb_index);
10365 devl_unlock(devlink);
10366}
bf797471
JP
10367EXPORT_SYMBOL_GPL(devlink_sb_unregister);
10368
70a2ff89
JP
10369/**
10370 * devl_dpipe_headers_register - register dpipe headers
10371 *
10372 * @devlink: devlink
10373 * @dpipe_headers: dpipe header array
10374 *
10375 * Register the headers supported by hardware.
10376 */
10377void devl_dpipe_headers_register(struct devlink *devlink,
10378 struct devlink_dpipe_headers *dpipe_headers)
10379{
10380 lockdep_assert_held(&devlink->lock);
10381
10382 devlink->dpipe_headers = dpipe_headers;
10383}
10384EXPORT_SYMBOL_GPL(devl_dpipe_headers_register);
10385
70a2ff89
JP
10386/**
10387 * devl_dpipe_headers_unregister - unregister dpipe headers
10388 *
10389 * @devlink: devlink
10390 *
10391 * Unregister the headers supported by hardware.
10392 */
10393void devl_dpipe_headers_unregister(struct devlink *devlink)
10394{
10395 lockdep_assert_held(&devlink->lock);
10396
10397 devlink->dpipe_headers = NULL;
10398}
10399EXPORT_SYMBOL_GPL(devl_dpipe_headers_unregister);
10400
1555d204
AS
10401/**
10402 * devlink_dpipe_table_counter_enabled - check if counter allocation
10403 * required
10404 * @devlink: devlink
10405 * @table_name: tables name
10406 *
10407 * Used by driver to check if counter allocation is required.
10408 * After counter allocation is turned on the table entries
10409 * are updated to include counter statistics.
10410 *
10411 * After that point on the driver must respect the counter
10412 * state so that each entry added to the table is added
10413 * with a counter.
10414 */
10415bool devlink_dpipe_table_counter_enabled(struct devlink *devlink,
10416 const char *table_name)
10417{
10418 struct devlink_dpipe_table *table;
10419 bool enabled;
10420
10421 rcu_read_lock();
10422 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2eb51c75 10423 table_name, devlink);
1555d204
AS
10424 enabled = false;
10425 if (table)
10426 enabled = table->counters_enabled;
10427 rcu_read_unlock();
10428 return enabled;
10429}
10430EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled);
10431
10432/**
70a2ff89 10433 * devl_dpipe_table_register - register dpipe table
1555d204 10434 *
70a2ff89
JP
10435 * @devlink: devlink
10436 * @table_name: table name
10437 * @table_ops: table ops
10438 * @priv: priv
10439 * @counter_control_extern: external control for counters
1555d204 10440 */
70a2ff89
JP
10441int devl_dpipe_table_register(struct devlink *devlink,
10442 const char *table_name,
10443 struct devlink_dpipe_table_ops *table_ops,
10444 void *priv, bool counter_control_extern)
1555d204
AS
10445{
10446 struct devlink_dpipe_table *table;
70a2ff89
JP
10447
10448 lockdep_assert_held(&devlink->lock);
1555d204 10449
ffd3cdcc
AS
10450 if (WARN_ON(!table_ops->size_get))
10451 return -EINVAL;
10452
2eb51c75 10453 if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name,
70a2ff89
JP
10454 devlink))
10455 return -EEXIST;
6132c1d9 10456
1555d204 10457 table = kzalloc(sizeof(*table), GFP_KERNEL);
70a2ff89
JP
10458 if (!table)
10459 return -ENOMEM;
1555d204
AS
10460
10461 table->name = table_name;
10462 table->table_ops = table_ops;
10463 table->priv = priv;
1555d204
AS
10464 table->counter_control_extern = counter_control_extern;
10465
1555d204 10466 list_add_tail_rcu(&table->list, &devlink->dpipe_table_list);
70a2ff89
JP
10467
10468 return 0;
10469}
10470EXPORT_SYMBOL_GPL(devl_dpipe_table_register);
10471
1555d204 10472/**
70a2ff89 10473 * devl_dpipe_table_unregister - unregister dpipe table
1555d204 10474 *
70a2ff89
JP
10475 * @devlink: devlink
10476 * @table_name: table name
1555d204 10477 */
70a2ff89
JP
10478void devl_dpipe_table_unregister(struct devlink *devlink,
10479 const char *table_name)
1555d204
AS
10480{
10481 struct devlink_dpipe_table *table;
10482
70a2ff89
JP
10483 lockdep_assert_held(&devlink->lock);
10484
1555d204 10485 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2eb51c75 10486 table_name, devlink);
1555d204 10487 if (!table)
70a2ff89 10488 return;
1555d204 10489 list_del_rcu(&table->list);
1555d204 10490 kfree_rcu(table, rcu);
70a2ff89
JP
10491}
10492EXPORT_SYMBOL_GPL(devl_dpipe_table_unregister);
10493
d9f9b9a4 10494/**
c223d6a4 10495 * devl_resource_register - devlink resource register
d9f9b9a4 10496 *
c223d6a4
JP
10497 * @devlink: devlink
10498 * @resource_name: resource's name
10499 * @resource_size: resource's size
10500 * @resource_id: resource's id
10501 * @parent_resource_id: resource's parent id
10502 * @size_params: size parameters
321f7ab0 10503 *
c223d6a4
JP
10504 * Generic resources should reuse the same names across drivers.
10505 * Please see the generic resources list at:
10506 * Documentation/networking/devlink/devlink-resource.rst
d9f9b9a4 10507 */
c223d6a4
JP
10508int devl_resource_register(struct devlink *devlink,
10509 const char *resource_name,
10510 u64 resource_size,
10511 u64 resource_id,
10512 u64 parent_resource_id,
10513 const struct devlink_resource_size_params *size_params)
d9f9b9a4
AS
10514{
10515 struct devlink_resource *resource;
10516 struct list_head *resource_list;
14530746 10517 bool top_hierarchy;
c223d6a4
JP
10518
10519 lockdep_assert_held(&devlink->lock);
d9f9b9a4 10520
14530746
DA
10521 top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP;
10522
d9f9b9a4 10523 resource = devlink_resource_find(devlink, NULL, resource_id);
c223d6a4
JP
10524 if (resource)
10525 return -EINVAL;
d9f9b9a4
AS
10526
10527 resource = kzalloc(sizeof(*resource), GFP_KERNEL);
c223d6a4
JP
10528 if (!resource)
10529 return -ENOMEM;
d9f9b9a4
AS
10530
10531 if (top_hierarchy) {
10532 resource_list = &devlink->resource_list;
10533 } else {
10534 struct devlink_resource *parent_resource;
10535
10536 parent_resource = devlink_resource_find(devlink, NULL,
10537 parent_resource_id);
10538 if (parent_resource) {
10539 resource_list = &parent_resource->resource_list;
10540 resource->parent = parent_resource;
10541 } else {
b75703de 10542 kfree(resource);
c223d6a4 10543 return -EINVAL;
d9f9b9a4
AS
10544 }
10545 }
10546
10547 resource->name = resource_name;
10548 resource->size = resource_size;
10549 resource->size_new = resource_size;
10550 resource->id = resource_id;
d9f9b9a4 10551 resource->size_valid = true;
77d27096
JP
10552 memcpy(&resource->size_params, size_params,
10553 sizeof(resource->size_params));
d9f9b9a4
AS
10554 INIT_LIST_HEAD(&resource->resource_list);
10555 list_add_tail(&resource->list, resource_list);
c223d6a4
JP
10556
10557 return 0;
10558}
10559EXPORT_SYMBOL_GPL(devl_resource_register);
10560
10561/**
10562 * devlink_resource_register - devlink resource register
10563 *
10564 * @devlink: devlink
10565 * @resource_name: resource's name
10566 * @resource_size: resource's size
10567 * @resource_id: resource's id
10568 * @parent_resource_id: resource's parent id
10569 * @size_params: size parameters
10570 *
10571 * Generic resources should reuse the same names across drivers.
10572 * Please see the generic resources list at:
10573 * Documentation/networking/devlink/devlink-resource.rst
10574 *
10575 * Context: Takes and release devlink->lock <mutex>.
10576 */
10577int devlink_resource_register(struct devlink *devlink,
10578 const char *resource_name,
10579 u64 resource_size,
10580 u64 resource_id,
10581 u64 parent_resource_id,
10582 const struct devlink_resource_size_params *size_params)
10583{
10584 int err;
10585
10586 devl_lock(devlink);
10587 err = devl_resource_register(devlink, resource_name, resource_size,
10588 resource_id, parent_resource_id, size_params);
7715023a 10589 devl_unlock(devlink);
d9f9b9a4
AS
10590 return err;
10591}
10592EXPORT_SYMBOL_GPL(devlink_resource_register);
10593
4c897cfc
LR
10594static void devlink_resource_unregister(struct devlink *devlink,
10595 struct devlink_resource *resource)
10596{
10597 struct devlink_resource *tmp, *child_resource;
10598
10599 list_for_each_entry_safe(child_resource, tmp, &resource->resource_list,
10600 list) {
10601 devlink_resource_unregister(devlink, child_resource);
10602 list_del(&child_resource->list);
10603 kfree(child_resource);
10604 }
10605}
10606
d9f9b9a4 10607/**
c223d6a4 10608 * devl_resources_unregister - free all resources
d9f9b9a4 10609 *
c223d6a4 10610 * @devlink: devlink
d9f9b9a4 10611 */
c223d6a4 10612void devl_resources_unregister(struct devlink *devlink)
d9f9b9a4
AS
10613{
10614 struct devlink_resource *tmp, *child_resource;
d9f9b9a4 10615
c223d6a4 10616 lockdep_assert_held(&devlink->lock);
d9f9b9a4 10617
4c897cfc
LR
10618 list_for_each_entry_safe(child_resource, tmp, &devlink->resource_list,
10619 list) {
10620 devlink_resource_unregister(devlink, child_resource);
d9f9b9a4
AS
10621 list_del(&child_resource->list);
10622 kfree(child_resource);
10623 }
c223d6a4
JP
10624}
10625EXPORT_SYMBOL_GPL(devl_resources_unregister);
d9f9b9a4 10626
c223d6a4
JP
10627/**
10628 * devlink_resources_unregister - free all resources
10629 *
10630 * @devlink: devlink
10631 *
10632 * Context: Takes and release devlink->lock <mutex>.
10633 */
10634void devlink_resources_unregister(struct devlink *devlink)
10635{
10636 devl_lock(devlink);
10637 devl_resources_unregister(devlink);
7715023a 10638 devl_unlock(devlink);
d9f9b9a4
AS
10639}
10640EXPORT_SYMBOL_GPL(devlink_resources_unregister);
10641
c223d6a4
JP
10642/**
10643 * devl_resource_size_get - get and update size
10644 *
10645 * @devlink: devlink
10646 * @resource_id: the requested resource id
10647 * @p_resource_size: ptr to update
10648 */
10649int devl_resource_size_get(struct devlink *devlink,
10650 u64 resource_id,
10651 u64 *p_resource_size)
10652{
10653 struct devlink_resource *resource;
10654
10655 lockdep_assert_held(&devlink->lock);
10656
10657 resource = devlink_resource_find(devlink, NULL, resource_id);
10658 if (!resource)
10659 return -EINVAL;
10660 *p_resource_size = resource->size_new;
10661 resource->size = resource->size_new;
10662 return 0;
10663}
10664EXPORT_SYMBOL_GPL(devl_resource_size_get);
10665
70a2ff89
JP
10666/**
10667 * devl_dpipe_table_resource_set - set the resource id
10668 *
10669 * @devlink: devlink
10670 * @table_name: table name
10671 * @resource_id: resource id
10672 * @resource_units: number of resource's units consumed per table's entry
10673 */
10674int devl_dpipe_table_resource_set(struct devlink *devlink,
10675 const char *table_name, u64 resource_id,
10676 u64 resource_units)
10677{
10678 struct devlink_dpipe_table *table;
10679
10680 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
10681 table_name, devlink);
10682 if (!table)
10683 return -EINVAL;
10684
10685 table->resource_id = resource_id;
10686 table->resource_units = resource_units;
10687 table->resource_valid = true;
10688 return 0;
10689}
10690EXPORT_SYMBOL_GPL(devl_dpipe_table_resource_set);
10691
c223d6a4
JP
10692/**
10693 * devl_resource_occ_get_register - register occupancy getter
10694 *
10695 * @devlink: devlink
10696 * @resource_id: resource id
10697 * @occ_get: occupancy getter callback
10698 * @occ_get_priv: occupancy getter callback priv
10699 */
10700void devl_resource_occ_get_register(struct devlink *devlink,
10701 u64 resource_id,
10702 devlink_resource_occ_get_t *occ_get,
10703 void *occ_get_priv)
10704{
10705 struct devlink_resource *resource;
10706
10707 lockdep_assert_held(&devlink->lock);
10708
10709 resource = devlink_resource_find(devlink, NULL, resource_id);
10710 if (WARN_ON(!resource))
10711 return;
10712 WARN_ON(resource->occ_get);
10713
10714 resource->occ_get = occ_get;
10715 resource->occ_get_priv = occ_get_priv;
10716}
10717EXPORT_SYMBOL_GPL(devl_resource_occ_get_register);
10718
fc56be47
JP
10719/**
10720 * devlink_resource_occ_get_register - register occupancy getter
10721 *
10722 * @devlink: devlink
10723 * @resource_id: resource id
10724 * @occ_get: occupancy getter callback
10725 * @occ_get_priv: occupancy getter callback priv
c223d6a4
JP
10726 *
10727 * Context: Takes and release devlink->lock <mutex>.
fc56be47
JP
10728 */
10729void devlink_resource_occ_get_register(struct devlink *devlink,
10730 u64 resource_id,
10731 devlink_resource_occ_get_t *occ_get,
10732 void *occ_get_priv)
10733{
7715023a 10734 devl_lock(devlink);
c223d6a4
JP
10735 devl_resource_occ_get_register(devlink, resource_id,
10736 occ_get, occ_get_priv);
7715023a 10737 devl_unlock(devlink);
fc56be47
JP
10738}
10739EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register);
10740
10741/**
c223d6a4 10742 * devl_resource_occ_get_unregister - unregister occupancy getter
fc56be47 10743 *
c223d6a4
JP
10744 * @devlink: devlink
10745 * @resource_id: resource id
fc56be47 10746 */
c223d6a4
JP
10747void devl_resource_occ_get_unregister(struct devlink *devlink,
10748 u64 resource_id)
fc56be47
JP
10749{
10750 struct devlink_resource *resource;
10751
c223d6a4
JP
10752 lockdep_assert_held(&devlink->lock);
10753
fc56be47
JP
10754 resource = devlink_resource_find(devlink, NULL, resource_id);
10755 if (WARN_ON(!resource))
c223d6a4 10756 return;
fc56be47
JP
10757 WARN_ON(!resource->occ_get);
10758
10759 resource->occ_get = NULL;
10760 resource->occ_get_priv = NULL;
c223d6a4
JP
10761}
10762EXPORT_SYMBOL_GPL(devl_resource_occ_get_unregister);
10763
10764/**
10765 * devlink_resource_occ_get_unregister - unregister occupancy getter
10766 *
10767 * @devlink: devlink
10768 * @resource_id: resource id
10769 *
10770 * Context: Takes and release devlink->lock <mutex>.
10771 */
10772void devlink_resource_occ_get_unregister(struct devlink *devlink,
10773 u64 resource_id)
10774{
10775 devl_lock(devlink);
10776 devl_resource_occ_get_unregister(devlink, resource_id);
7715023a 10777 devl_unlock(devlink);
fc56be47
JP
10778}
10779EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister);
10780
39e6160e
VV
10781static int devlink_param_verify(const struct devlink_param *param)
10782{
10783 if (!param || !param->name || !param->supported_cmodes)
10784 return -EINVAL;
10785 if (param->generic)
10786 return devlink_param_generic_verify(param);
10787 else
10788 return devlink_param_driver_verify(param);
10789}
10790
020dd127
JP
10791static int devlink_param_register(struct devlink *devlink,
10792 const struct devlink_param *param)
10793{
10794 struct devlink_param_item *param_item;
10795
10796 WARN_ON(devlink_param_verify(param));
10797 WARN_ON(devlink_param_find_by_name(&devlink->param_list, param->name));
10798
10799 if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
10800 WARN_ON(param->get || param->set);
10801 else
10802 WARN_ON(!param->get || !param->set);
10803
10804 param_item = kzalloc(sizeof(*param_item), GFP_KERNEL);
10805 if (!param_item)
10806 return -ENOMEM;
10807
10808 param_item->param = param;
10809
10810 list_add_tail(&param_item->list, &devlink->param_list);
10811 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
10812 return 0;
10813}
10814
10815static void devlink_param_unregister(struct devlink *devlink,
10816 const struct devlink_param *param)
10817{
10818 struct devlink_param_item *param_item;
10819
10820 param_item =
10821 devlink_param_find_by_name(&devlink->param_list, param->name);
bb9bb6bf
JP
10822 if (WARN_ON(!param_item))
10823 return;
020dd127
JP
10824 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_DEL);
10825 list_del(&param_item->list);
10826 kfree(param_item);
10827}
10828
39e6160e 10829/**
075935f0 10830 * devl_params_register - register configuration parameters
39e6160e
VV
10831 *
10832 * @devlink: devlink
10833 * @params: configuration parameters array
10834 * @params_count: number of parameters provided
10835 *
10836 * Register the configuration parameters supported by the driver.
10837 */
075935f0
JP
10838int devl_params_register(struct devlink *devlink,
10839 const struct devlink_param *params,
10840 size_t params_count)
39e6160e 10841{
ee775b56
LR
10842 const struct devlink_param *param = params;
10843 int i, err;
10844
075935f0
JP
10845 lockdep_assert_held(&devlink->lock);
10846
ee775b56
LR
10847 for (i = 0; i < params_count; i++, param++) {
10848 err = devlink_param_register(devlink, param);
10849 if (err)
10850 goto rollback;
10851 }
10852 return 0;
10853
10854rollback:
10855 if (!i)
10856 return err;
10857
10858 for (param--; i > 0; i--, param--)
10859 devlink_param_unregister(devlink, param);
10860 return err;
39e6160e 10861}
075935f0
JP
10862EXPORT_SYMBOL_GPL(devl_params_register);
10863
10864int devlink_params_register(struct devlink *devlink,
10865 const struct devlink_param *params,
10866 size_t params_count)
10867{
10868 int err;
10869
10870 devl_lock(devlink);
10871 err = devl_params_register(devlink, params, params_count);
10872 devl_unlock(devlink);
10873 return err;
10874}
eabaef18
MS
10875EXPORT_SYMBOL_GPL(devlink_params_register);
10876
10877/**
075935f0 10878 * devl_params_unregister - unregister configuration parameters
eabaef18
MS
10879 * @devlink: devlink
10880 * @params: configuration parameters to unregister
10881 * @params_count: number of parameters provided
10882 */
075935f0
JP
10883void devl_params_unregister(struct devlink *devlink,
10884 const struct devlink_param *params,
10885 size_t params_count)
eabaef18 10886{
ee775b56
LR
10887 const struct devlink_param *param = params;
10888 int i;
10889
075935f0
JP
10890 lockdep_assert_held(&devlink->lock);
10891
ee775b56
LR
10892 for (i = 0; i < params_count; i++, param++)
10893 devlink_param_unregister(devlink, param);
eabaef18 10894}
075935f0
JP
10895EXPORT_SYMBOL_GPL(devl_params_unregister);
10896
10897void devlink_params_unregister(struct devlink *devlink,
10898 const struct devlink_param *params,
10899 size_t params_count)
10900{
10901 devl_lock(devlink);
10902 devl_params_unregister(devlink, params, params_count);
10903 devl_unlock(devlink);
10904}
eabaef18
MS
10905EXPORT_SYMBOL_GPL(devlink_params_unregister);
10906
8ba024df 10907/**
075935f0
JP
10908 * devl_param_driverinit_value_get - get configuration parameter
10909 * value for driver initializing
8ba024df
LR
10910 *
10911 * @devlink: devlink
10912 * @param_id: parameter ID
10913 * @init_val: value of parameter in driverinit configuration mode
10914 *
10915 * This function should be used by the driver to get driverinit
10916 * configuration for initialization after reload command.
10917 */
075935f0
JP
10918int devl_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
10919 union devlink_param_value *init_val)
ec01aeb1
MS
10920{
10921 struct devlink_param_item *param_item;
10922
075935f0
JP
10923 lockdep_assert_held(&devlink->lock);
10924
3f716a62 10925 if (WARN_ON(!devlink_reload_supported(devlink->ops)))
8ba024df
LR
10926 return -EOPNOTSUPP;
10927
10928 param_item = devlink_param_find_by_id(&devlink->param_list, param_id);
ec01aeb1
MS
10929 if (!param_item)
10930 return -EINVAL;
10931
3f716a62
JP
10932 if (!param_item->driverinit_value_valid)
10933 return -EOPNOTSUPP;
10934
10935 if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param,
10936 DEVLINK_PARAM_CMODE_DRIVERINIT)))
ec01aeb1
MS
10937 return -EOPNOTSUPP;
10938
1276534c
MS
10939 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
10940 strcpy(init_val->vstr, param_item->driverinit_value.vstr);
10941 else
10942 *init_val = param_item->driverinit_value;
ec01aeb1
MS
10943
10944 return 0;
10945}
075935f0 10946EXPORT_SYMBOL_GPL(devl_param_driverinit_value_get);
ffd19b9a 10947
8ba024df 10948/**
075935f0
JP
10949 * devl_param_driverinit_value_set - set value of configuration
10950 * parameter for driverinit
10951 * configuration mode
8ba024df
LR
10952 *
10953 * @devlink: devlink
10954 * @param_id: parameter ID
10955 * @init_val: value of parameter to set for driverinit configuration mode
10956 *
10957 * This function should be used by the driver to set driverinit
10958 * configuration mode default value.
10959 */
075935f0
JP
10960void devl_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
10961 union devlink_param_value init_val)
5473a7bd
VV
10962{
10963 struct devlink_param_item *param_item;
10964
8ba024df 10965 param_item = devlink_param_find_by_id(&devlink->param_list, param_id);
85fe0b32
JP
10966 if (WARN_ON(!param_item))
10967 return;
5473a7bd 10968
85fe0b32
JP
10969 if (WARN_ON(!devlink_param_cmode_is_supported(param_item->param,
10970 DEVLINK_PARAM_CMODE_DRIVERINIT)))
10971 return;
5473a7bd
VV
10972
10973 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
10974 strcpy(param_item->driverinit_value.vstr, init_val.vstr);
10975 else
10976 param_item->driverinit_value = init_val;
10977 param_item->driverinit_value_valid = true;
1d18bb1a
JK
10978
10979 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
5473a7bd 10980}
075935f0 10981EXPORT_SYMBOL_GPL(devl_param_driverinit_value_set);
ec01aeb1 10982
ea601e17 10983/**
075935f0
JP
10984 * devl_param_value_changed - notify devlink on a parameter's value
10985 * change. Should be called by the driver
10986 * right after the change.
ea601e17
MS
10987 *
10988 * @devlink: devlink
10989 * @param_id: parameter ID
10990 *
10991 * This function should be used by the driver to notify devlink on value
10992 * change, excluding driverinit configuration mode.
10993 * For driverinit configuration mode driver should use the function
ea601e17 10994 */
075935f0 10995void devl_param_value_changed(struct devlink *devlink, u32 param_id)
ea601e17
MS
10996{
10997 struct devlink_param_item *param_item;
10998
10999 param_item = devlink_param_find_by_id(&devlink->param_list, param_id);
11000 WARN_ON(!param_item);
11001
c1e5786d 11002 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
ea601e17 11003}
075935f0 11004EXPORT_SYMBOL_GPL(devl_param_value_changed);
ea601e17 11005
b16ebe92 11006/**
eb0e9fa2 11007 * devl_region_create - create a new address region
b16ebe92 11008 *
eb0e9fa2
JP
11009 * @devlink: devlink
11010 * @ops: region operations and name
11011 * @region_max_snapshots: Maximum supported number of snapshots for region
11012 * @region_size: size of region
b16ebe92 11013 */
eb0e9fa2
JP
11014struct devlink_region *devl_region_create(struct devlink *devlink,
11015 const struct devlink_region_ops *ops,
11016 u32 region_max_snapshots,
11017 u64 region_size)
b16ebe92
AV
11018{
11019 struct devlink_region *region;
eb0e9fa2
JP
11020
11021 devl_assert_locked(devlink);
b16ebe92 11022
a0a09f6b
JK
11023 if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
11024 return ERR_PTR(-EINVAL);
11025
eb0e9fa2
JP
11026 if (devlink_region_get_by_name(devlink, ops->name))
11027 return ERR_PTR(-EEXIST);
b16ebe92
AV
11028
11029 region = kzalloc(sizeof(*region), GFP_KERNEL);
eb0e9fa2
JP
11030 if (!region)
11031 return ERR_PTR(-ENOMEM);
b16ebe92
AV
11032
11033 region->devlink = devlink;
11034 region->max_snapshots = region_max_snapshots;
e8937681 11035 region->ops = ops;
b16ebe92
AV
11036 region->size = region_size;
11037 INIT_LIST_HEAD(&region->snapshot_list);
2dec18ad 11038 mutex_init(&region->snapshot_lock);
b16ebe92 11039 list_add_tail(&region->list, &devlink->region_list);
866319bb 11040 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
b16ebe92 11041
b16ebe92 11042 return region;
eb0e9fa2
JP
11043}
11044EXPORT_SYMBOL_GPL(devl_region_create);
b16ebe92 11045
eb0e9fa2
JP
11046/**
11047 * devlink_region_create - create a new address region
11048 *
11049 * @devlink: devlink
11050 * @ops: region operations and name
11051 * @region_max_snapshots: Maximum supported number of snapshots for region
11052 * @region_size: size of region
11053 *
11054 * Context: Takes and release devlink->lock <mutex>.
11055 */
11056struct devlink_region *
11057devlink_region_create(struct devlink *devlink,
11058 const struct devlink_region_ops *ops,
11059 u32 region_max_snapshots, u64 region_size)
11060{
11061 struct devlink_region *region;
11062
11063 devl_lock(devlink);
11064 region = devl_region_create(devlink, ops, region_max_snapshots,
11065 region_size);
7715023a 11066 devl_unlock(devlink);
eb0e9fa2 11067 return region;
b16ebe92
AV
11068}
11069EXPORT_SYMBOL_GPL(devlink_region_create);
11070
544e7c33
AL
11071/**
11072 * devlink_port_region_create - create a new address region for a port
11073 *
11074 * @port: devlink port
11075 * @ops: region operations and name
11076 * @region_max_snapshots: Maximum supported number of snapshots for region
11077 * @region_size: size of region
eb0e9fa2
JP
11078 *
11079 * Context: Takes and release devlink->lock <mutex>.
544e7c33
AL
11080 */
11081struct devlink_region *
11082devlink_port_region_create(struct devlink_port *port,
11083 const struct devlink_port_region_ops *ops,
11084 u32 region_max_snapshots, u64 region_size)
11085{
11086 struct devlink *devlink = port->devlink;
11087 struct devlink_region *region;
11088 int err = 0;
11089
ae3bbc04
JP
11090 ASSERT_DEVLINK_PORT_INITIALIZED(port);
11091
544e7c33
AL
11092 if (WARN_ON(!ops) || WARN_ON(!ops->destructor))
11093 return ERR_PTR(-EINVAL);
11094
7715023a 11095 devl_lock(devlink);
544e7c33
AL
11096
11097 if (devlink_port_region_get_by_name(port, ops->name)) {
11098 err = -EEXIST;
11099 goto unlock;
11100 }
11101
11102 region = kzalloc(sizeof(*region), GFP_KERNEL);
11103 if (!region) {
11104 err = -ENOMEM;
11105 goto unlock;
11106 }
11107
11108 region->devlink = devlink;
11109 region->port = port;
11110 region->max_snapshots = region_max_snapshots;
11111 region->port_ops = ops;
11112 region->size = region_size;
11113 INIT_LIST_HEAD(&region->snapshot_list);
2dec18ad 11114 mutex_init(&region->snapshot_lock);
544e7c33
AL
11115 list_add_tail(&region->list, &port->region_list);
11116 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
11117
7715023a 11118 devl_unlock(devlink);
544e7c33
AL
11119 return region;
11120
11121unlock:
7715023a 11122 devl_unlock(devlink);
544e7c33
AL
11123 return ERR_PTR(err);
11124}
11125EXPORT_SYMBOL_GPL(devlink_port_region_create);
11126
b16ebe92 11127/**
eb0e9fa2 11128 * devl_region_destroy - destroy address region
b16ebe92 11129 *
eb0e9fa2 11130 * @region: devlink region to destroy
b16ebe92 11131 */
eb0e9fa2 11132void devl_region_destroy(struct devlink_region *region)
b16ebe92
AV
11133{
11134 struct devlink *devlink = region->devlink;
d7e52722 11135 struct devlink_snapshot *snapshot, *ts;
b16ebe92 11136
eb0e9fa2 11137 devl_assert_locked(devlink);
d7e52722
AV
11138
11139 /* Free all snapshots of region */
b4cafb3d 11140 mutex_lock(&region->snapshot_lock);
d7e52722 11141 list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list)
92b49822 11142 devlink_region_snapshot_del(region, snapshot);
b4cafb3d 11143 mutex_unlock(&region->snapshot_lock);
d7e52722 11144
b16ebe92 11145 list_del(&region->list);
2dec18ad 11146 mutex_destroy(&region->snapshot_lock);
866319bb
AV
11147
11148 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
b16ebe92
AV
11149 kfree(region);
11150}
eb0e9fa2
JP
11151EXPORT_SYMBOL_GPL(devl_region_destroy);
11152
11153/**
11154 * devlink_region_destroy - destroy address region
11155 *
11156 * @region: devlink region to destroy
11157 *
11158 * Context: Takes and release devlink->lock <mutex>.
11159 */
11160void devlink_region_destroy(struct devlink_region *region)
11161{
11162 struct devlink *devlink = region->devlink;
11163
11164 devl_lock(devlink);
11165 devl_region_destroy(region);
11166 devl_unlock(devlink);
11167}
b16ebe92
AV
11168EXPORT_SYMBOL_GPL(devlink_region_destroy);
11169
ccadfa44 11170/**
b0efcae5 11171 * devlink_region_snapshot_id_get - get snapshot ID
ccadfa44
AV
11172 *
11173 * This callback should be called when adding a new snapshot,
11174 * Driver should use the same id for multiple snapshots taken
11175 * on multiple regions at the same time/by the same trigger.
11176 *
12102436
JK
11177 * The caller of this function must use devlink_region_snapshot_id_put
11178 * when finished creating regions using this id.
11179 *
7ef19d3b
JK
11180 * Returns zero on success, or a negative error code on failure.
11181 *
ccadfa44 11182 * @devlink: devlink
7ef19d3b 11183 * @id: storage to return id
ccadfa44 11184 */
7ef19d3b 11185int devlink_region_snapshot_id_get(struct devlink *devlink, u32 *id)
ccadfa44 11186{
5502e871 11187 return __devlink_region_snapshot_id_get(devlink, id);
ccadfa44 11188}
b0efcae5 11189EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get);
ccadfa44 11190
12102436
JK
11191/**
11192 * devlink_region_snapshot_id_put - put snapshot ID reference
11193 *
11194 * This should be called by a driver after finishing creating snapshots
11195 * with an id. Doing so ensures that the ID can later be released in the
11196 * event that all snapshots using it have been destroyed.
11197 *
11198 * @devlink: devlink
11199 * @id: id to release reference on
11200 */
11201void devlink_region_snapshot_id_put(struct devlink *devlink, u32 id)
11202{
12102436 11203 __devlink_snapshot_id_decrement(devlink, id);
12102436
JK
11204}
11205EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_put);
11206
d7e52722
AV
11207/**
11208 * devlink_region_snapshot_create - create a new snapshot
11209 * This will add a new snapshot of a region. The snapshot
11210 * will be stored on the region struct and can be accessed
6d82f67e 11211 * from devlink. This is useful for future analyses of snapshots.
d7e52722
AV
11212 * Multiple snapshots can be created on a region.
11213 * The @snapshot_id should be obtained using the getter function.
11214 *
eeaadd82 11215 * @region: devlink region of the snapshot
d7e52722
AV
11216 * @data: snapshot data
11217 * @snapshot_id: snapshot id to be created
d7e52722 11218 */
3a5e5234 11219int devlink_region_snapshot_create(struct devlink_region *region,
a0a09f6b 11220 u8 *data, u32 snapshot_id)
d7e52722 11221{
d7e52722
AV
11222 int err;
11223
2dec18ad 11224 mutex_lock(&region->snapshot_lock);
cf80faee 11225 err = __devlink_region_snapshot_create(region, data, snapshot_id);
2dec18ad 11226 mutex_unlock(&region->snapshot_lock);
d7e52722
AV
11227 return err;
11228}
11229EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);
11230
0f420b6c
IS
11231#define DEVLINK_TRAP(_id, _type) \
11232 { \
11233 .type = DEVLINK_TRAP_TYPE_##_type, \
11234 .id = DEVLINK_TRAP_GENERIC_ID_##_id, \
11235 .name = DEVLINK_TRAP_GENERIC_NAME_##_id, \
11236 }
11237
11238static const struct devlink_trap devlink_trap_generic[] = {
391203ab
IS
11239 DEVLINK_TRAP(SMAC_MC, DROP),
11240 DEVLINK_TRAP(VLAN_TAG_MISMATCH, DROP),
11241 DEVLINK_TRAP(INGRESS_VLAN_FILTER, DROP),
11242 DEVLINK_TRAP(INGRESS_STP_FILTER, DROP),
11243 DEVLINK_TRAP(EMPTY_TX_LIST, DROP),
11244 DEVLINK_TRAP(PORT_LOOPBACK_FILTER, DROP),
11245 DEVLINK_TRAP(BLACKHOLE_ROUTE, DROP),
11246 DEVLINK_TRAP(TTL_ERROR, EXCEPTION),
11247 DEVLINK_TRAP(TAIL_DROP, DROP),
6896cc4d
AC
11248 DEVLINK_TRAP(NON_IP_PACKET, DROP),
11249 DEVLINK_TRAP(UC_DIP_MC_DMAC, DROP),
11250 DEVLINK_TRAP(DIP_LB, DROP),
11251 DEVLINK_TRAP(SIP_MC, DROP),
11252 DEVLINK_TRAP(SIP_LB, DROP),
11253 DEVLINK_TRAP(CORRUPTED_IP_HDR, DROP),
11254 DEVLINK_TRAP(IPV4_SIP_BC, DROP),
11255 DEVLINK_TRAP(IPV6_MC_DIP_RESERVED_SCOPE, DROP),
11256 DEVLINK_TRAP(IPV6_MC_DIP_INTERFACE_LOCAL_SCOPE, DROP),
3b063ae5
AC
11257 DEVLINK_TRAP(MTU_ERROR, EXCEPTION),
11258 DEVLINK_TRAP(UNRESOLVED_NEIGH, EXCEPTION),
11259 DEVLINK_TRAP(RPF, EXCEPTION),
11260 DEVLINK_TRAP(REJECT_ROUTE, EXCEPTION),
11261 DEVLINK_TRAP(IPV4_LPM_UNICAST_MISS, EXCEPTION),
11262 DEVLINK_TRAP(IPV6_LPM_UNICAST_MISS, EXCEPTION),
95f0ead8 11263 DEVLINK_TRAP(NON_ROUTABLE, DROP),
13c056ec 11264 DEVLINK_TRAP(DECAP_ERROR, EXCEPTION),
c3cae491 11265 DEVLINK_TRAP(OVERLAY_SMAC_MC, DROP),
ecd942a0
JP
11266 DEVLINK_TRAP(INGRESS_FLOW_ACTION_DROP, DROP),
11267 DEVLINK_TRAP(EGRESS_FLOW_ACTION_DROP, DROP),
515eac67
IS
11268 DEVLINK_TRAP(STP, CONTROL),
11269 DEVLINK_TRAP(LACP, CONTROL),
11270 DEVLINK_TRAP(LLDP, CONTROL),
11271 DEVLINK_TRAP(IGMP_QUERY, CONTROL),
11272 DEVLINK_TRAP(IGMP_V1_REPORT, CONTROL),
11273 DEVLINK_TRAP(IGMP_V2_REPORT, CONTROL),
11274 DEVLINK_TRAP(IGMP_V3_REPORT, CONTROL),
11275 DEVLINK_TRAP(IGMP_V2_LEAVE, CONTROL),
11276 DEVLINK_TRAP(MLD_QUERY, CONTROL),
11277 DEVLINK_TRAP(MLD_V1_REPORT, CONTROL),
11278 DEVLINK_TRAP(MLD_V2_REPORT, CONTROL),
11279 DEVLINK_TRAP(MLD_V1_DONE, CONTROL),
d77cfd16
IS
11280 DEVLINK_TRAP(IPV4_DHCP, CONTROL),
11281 DEVLINK_TRAP(IPV6_DHCP, CONTROL),
11282 DEVLINK_TRAP(ARP_REQUEST, CONTROL),
11283 DEVLINK_TRAP(ARP_RESPONSE, CONTROL),
11284 DEVLINK_TRAP(ARP_OVERLAY, CONTROL),
11285 DEVLINK_TRAP(IPV6_NEIGH_SOLICIT, CONTROL),
11286 DEVLINK_TRAP(IPV6_NEIGH_ADVERT, CONTROL),
11287 DEVLINK_TRAP(IPV4_BFD, CONTROL),
11288 DEVLINK_TRAP(IPV6_BFD, CONTROL),
11289 DEVLINK_TRAP(IPV4_OSPF, CONTROL),
11290 DEVLINK_TRAP(IPV6_OSPF, CONTROL),
11291 DEVLINK_TRAP(IPV4_BGP, CONTROL),
11292 DEVLINK_TRAP(IPV6_BGP, CONTROL),
11293 DEVLINK_TRAP(IPV4_VRRP, CONTROL),
11294 DEVLINK_TRAP(IPV6_VRRP, CONTROL),
11295 DEVLINK_TRAP(IPV4_PIM, CONTROL),
11296 DEVLINK_TRAP(IPV6_PIM, CONTROL),
11297 DEVLINK_TRAP(UC_LB, CONTROL),
11298 DEVLINK_TRAP(LOCAL_ROUTE, CONTROL),
11299 DEVLINK_TRAP(EXTERNAL_ROUTE, CONTROL),
11300 DEVLINK_TRAP(IPV6_UC_DIP_LINK_LOCAL_SCOPE, CONTROL),
11301 DEVLINK_TRAP(IPV6_DIP_ALL_NODES, CONTROL),
11302 DEVLINK_TRAP(IPV6_DIP_ALL_ROUTERS, CONTROL),
11303 DEVLINK_TRAP(IPV6_ROUTER_SOLICIT, CONTROL),
11304 DEVLINK_TRAP(IPV6_ROUTER_ADVERT, CONTROL),
11305 DEVLINK_TRAP(IPV6_REDIRECT, CONTROL),
11306 DEVLINK_TRAP(IPV4_ROUTER_ALERT, CONTROL),
11307 DEVLINK_TRAP(IPV6_ROUTER_ALERT, CONTROL),
11308 DEVLINK_TRAP(PTP_EVENT, CONTROL),
11309 DEVLINK_TRAP(PTP_GENERAL, CONTROL),
5eb18a2b
IS
11310 DEVLINK_TRAP(FLOW_ACTION_SAMPLE, CONTROL),
11311 DEVLINK_TRAP(FLOW_ACTION_TRAP, CONTROL),
08e335f6 11312 DEVLINK_TRAP(EARLY_DROP, DROP),
10c24eb2
IC
11313 DEVLINK_TRAP(VXLAN_PARSING, DROP),
11314 DEVLINK_TRAP(LLC_SNAP_PARSING, DROP),
11315 DEVLINK_TRAP(VLAN_PARSING, DROP),
11316 DEVLINK_TRAP(PPPOE_PPP_PARSING, DROP),
11317 DEVLINK_TRAP(MPLS_PARSING, DROP),
11318 DEVLINK_TRAP(ARP_PARSING, DROP),
11319 DEVLINK_TRAP(IP_1_PARSING, DROP),
11320 DEVLINK_TRAP(IP_N_PARSING, DROP),
11321 DEVLINK_TRAP(GRE_PARSING, DROP),
11322 DEVLINK_TRAP(UDP_PARSING, DROP),
11323 DEVLINK_TRAP(TCP_PARSING, DROP),
11324 DEVLINK_TRAP(IPSEC_PARSING, DROP),
11325 DEVLINK_TRAP(SCTP_PARSING, DROP),
11326 DEVLINK_TRAP(DCCP_PARSING, DROP),
11327 DEVLINK_TRAP(GTP_PARSING, DROP),
11328 DEVLINK_TRAP(ESP_PARSING, DROP),
f0a5013e 11329 DEVLINK_TRAP(BLACKHOLE_NEXTHOP, DROP),
e78ab164 11330 DEVLINK_TRAP(DMAC_FILTER, DROP),
2640a82b
IS
11331 DEVLINK_TRAP(EAPOL, CONTROL),
11332 DEVLINK_TRAP(LOCKED_PORT, DROP),
0f420b6c
IS
11333};
11334
11335#define DEVLINK_TRAP_GROUP(_id) \
11336 { \
11337 .id = DEVLINK_TRAP_GROUP_GENERIC_ID_##_id, \
11338 .name = DEVLINK_TRAP_GROUP_GENERIC_NAME_##_id, \
11339 }
11340
11341static const struct devlink_trap_group devlink_trap_group_generic[] = {
391203ab
IS
11342 DEVLINK_TRAP_GROUP(L2_DROPS),
11343 DEVLINK_TRAP_GROUP(L3_DROPS),
678eb199 11344 DEVLINK_TRAP_GROUP(L3_EXCEPTIONS),
391203ab 11345 DEVLINK_TRAP_GROUP(BUFFER_DROPS),
13c056ec 11346 DEVLINK_TRAP_GROUP(TUNNEL_DROPS),
ecd942a0 11347 DEVLINK_TRAP_GROUP(ACL_DROPS),
515eac67
IS
11348 DEVLINK_TRAP_GROUP(STP),
11349 DEVLINK_TRAP_GROUP(LACP),
11350 DEVLINK_TRAP_GROUP(LLDP),
11351 DEVLINK_TRAP_GROUP(MC_SNOOPING),
d77cfd16
IS
11352 DEVLINK_TRAP_GROUP(DHCP),
11353 DEVLINK_TRAP_GROUP(NEIGH_DISCOVERY),
11354 DEVLINK_TRAP_GROUP(BFD),
11355 DEVLINK_TRAP_GROUP(OSPF),
11356 DEVLINK_TRAP_GROUP(BGP),
11357 DEVLINK_TRAP_GROUP(VRRP),
11358 DEVLINK_TRAP_GROUP(PIM),
11359 DEVLINK_TRAP_GROUP(UC_LB),
11360 DEVLINK_TRAP_GROUP(LOCAL_DELIVERY),
ec4f5b36 11361 DEVLINK_TRAP_GROUP(EXTERNAL_DELIVERY),
d77cfd16
IS
11362 DEVLINK_TRAP_GROUP(IPV6),
11363 DEVLINK_TRAP_GROUP(PTP_EVENT),
11364 DEVLINK_TRAP_GROUP(PTP_GENERAL),
5eb18a2b
IS
11365 DEVLINK_TRAP_GROUP(ACL_SAMPLE),
11366 DEVLINK_TRAP_GROUP(ACL_TRAP),
10c24eb2 11367 DEVLINK_TRAP_GROUP(PARSER_ERROR_DROPS),
2640a82b 11368 DEVLINK_TRAP_GROUP(EAPOL),
0f420b6c
IS
11369};
11370
11371static int devlink_trap_generic_verify(const struct devlink_trap *trap)
11372{
11373 if (trap->id > DEVLINK_TRAP_GENERIC_ID_MAX)
11374 return -EINVAL;
11375
11376 if (strcmp(trap->name, devlink_trap_generic[trap->id].name))
11377 return -EINVAL;
11378
11379 if (trap->type != devlink_trap_generic[trap->id].type)
11380 return -EINVAL;
11381
11382 return 0;
11383}
11384
11385static int devlink_trap_driver_verify(const struct devlink_trap *trap)
11386{
11387 int i;
11388
11389 if (trap->id <= DEVLINK_TRAP_GENERIC_ID_MAX)
11390 return -EINVAL;
11391
11392 for (i = 0; i < ARRAY_SIZE(devlink_trap_generic); i++) {
11393 if (!strcmp(trap->name, devlink_trap_generic[i].name))
11394 return -EEXIST;
11395 }
11396
11397 return 0;
11398}
11399
11400static int devlink_trap_verify(const struct devlink_trap *trap)
11401{
107f1678 11402 if (!trap || !trap->name)
0f420b6c
IS
11403 return -EINVAL;
11404
11405 if (trap->generic)
11406 return devlink_trap_generic_verify(trap);
11407 else
11408 return devlink_trap_driver_verify(trap);
11409}
11410
11411static int
11412devlink_trap_group_generic_verify(const struct devlink_trap_group *group)
11413{
11414 if (group->id > DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
11415 return -EINVAL;
11416
11417 if (strcmp(group->name, devlink_trap_group_generic[group->id].name))
11418 return -EINVAL;
11419
11420 return 0;
11421}
11422
11423static int
11424devlink_trap_group_driver_verify(const struct devlink_trap_group *group)
11425{
11426 int i;
11427
11428 if (group->id <= DEVLINK_TRAP_GROUP_GENERIC_ID_MAX)
11429 return -EINVAL;
11430
11431 for (i = 0; i < ARRAY_SIZE(devlink_trap_group_generic); i++) {
11432 if (!strcmp(group->name, devlink_trap_group_generic[i].name))
11433 return -EEXIST;
11434 }
11435
11436 return 0;
11437}
11438
11439static int devlink_trap_group_verify(const struct devlink_trap_group *group)
11440{
11441 if (group->generic)
11442 return devlink_trap_group_generic_verify(group);
11443 else
11444 return devlink_trap_group_driver_verify(group);
11445}
11446
11447static void
11448devlink_trap_group_notify(struct devlink *devlink,
11449 const struct devlink_trap_group_item *group_item,
11450 enum devlink_command cmd)
11451{
11452 struct sk_buff *msg;
11453 int err;
11454
11455 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_GROUP_NEW &&
11456 cmd != DEVLINK_CMD_TRAP_GROUP_DEL);
fb9d19c2
LR
11457 if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED))
11458 return;
0f420b6c
IS
11459
11460 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
11461 if (!msg)
11462 return;
11463
11464 err = devlink_nl_trap_group_fill(msg, devlink, group_item, cmd, 0, 0,
11465 0);
11466 if (err) {
11467 nlmsg_free(msg);
11468 return;
11469 }
11470
11471 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
11472 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
11473}
11474
0f420b6c
IS
11475static int
11476devlink_trap_item_group_link(struct devlink *devlink,
11477 struct devlink_trap_item *trap_item)
11478{
107f1678 11479 u16 group_id = trap_item->trap->init_group_id;
0f420b6c
IS
11480 struct devlink_trap_group_item *group_item;
11481
107f1678 11482 group_item = devlink_trap_group_item_lookup_by_id(devlink, group_id);
a09b37fc
IS
11483 if (WARN_ON_ONCE(!group_item))
11484 return -EINVAL;
0f420b6c
IS
11485
11486 trap_item->group_item = group_item;
11487
11488 return 0;
11489}
11490
0f420b6c
IS
11491static void devlink_trap_notify(struct devlink *devlink,
11492 const struct devlink_trap_item *trap_item,
11493 enum devlink_command cmd)
11494{
11495 struct sk_buff *msg;
11496 int err;
11497
11498 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_NEW &&
11499 cmd != DEVLINK_CMD_TRAP_DEL);
cf530217
LR
11500 if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED))
11501 return;
0f420b6c
IS
11502
11503 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
11504 if (!msg)
11505 return;
11506
11507 err = devlink_nl_trap_fill(msg, devlink, trap_item, cmd, 0, 0, 0);
11508 if (err) {
11509 nlmsg_free(msg);
11510 return;
11511 }
11512
11513 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
11514 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
11515}
11516
11517static int
11518devlink_trap_register(struct devlink *devlink,
11519 const struct devlink_trap *trap, void *priv)
11520{
11521 struct devlink_trap_item *trap_item;
11522 int err;
11523
11524 if (devlink_trap_item_lookup(devlink, trap->name))
11525 return -EEXIST;
11526
11527 trap_item = kzalloc(sizeof(*trap_item), GFP_KERNEL);
11528 if (!trap_item)
11529 return -ENOMEM;
11530
11531 trap_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
11532 if (!trap_item->stats) {
11533 err = -ENOMEM;
11534 goto err_stats_alloc;
11535 }
11536
11537 trap_item->trap = trap;
11538 trap_item->action = trap->init_action;
11539 trap_item->priv = priv;
11540
11541 err = devlink_trap_item_group_link(devlink, trap_item);
11542 if (err)
11543 goto err_group_link;
11544
11545 err = devlink->ops->trap_init(devlink, trap, trap_item);
11546 if (err)
11547 goto err_trap_init;
11548
11549 list_add_tail(&trap_item->list, &devlink->trap_list);
11550 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_NEW);
11551
11552 return 0;
11553
11554err_trap_init:
0f420b6c
IS
11555err_group_link:
11556 free_percpu(trap_item->stats);
11557err_stats_alloc:
11558 kfree(trap_item);
11559 return err;
11560}
11561
11562static void devlink_trap_unregister(struct devlink *devlink,
11563 const struct devlink_trap *trap)
11564{
11565 struct devlink_trap_item *trap_item;
11566
11567 trap_item = devlink_trap_item_lookup(devlink, trap->name);
11568 if (WARN_ON_ONCE(!trap_item))
11569 return;
11570
11571 devlink_trap_notify(devlink, trap_item, DEVLINK_CMD_TRAP_DEL);
11572 list_del(&trap_item->list);
11573 if (devlink->ops->trap_fini)
11574 devlink->ops->trap_fini(devlink, trap, trap_item);
0f420b6c
IS
11575 free_percpu(trap_item->stats);
11576 kfree(trap_item);
11577}
11578
11579static void devlink_trap_disable(struct devlink *devlink,
11580 const struct devlink_trap *trap)
11581{
11582 struct devlink_trap_item *trap_item;
11583
11584 trap_item = devlink_trap_item_lookup(devlink, trap->name);
11585 if (WARN_ON_ONCE(!trap_item))
11586 return;
11587
c88e11e0
IS
11588 devlink->ops->trap_action_set(devlink, trap, DEVLINK_TRAP_ACTION_DROP,
11589 NULL);
0f420b6c
IS
11590 trap_item->action = DEVLINK_TRAP_ACTION_DROP;
11591}
11592
11593/**
852e85a7 11594 * devl_traps_register - Register packet traps with devlink.
0f420b6c
IS
11595 * @devlink: devlink.
11596 * @traps: Packet traps.
11597 * @traps_count: Count of provided packet traps.
11598 * @priv: Driver private information.
11599 *
11600 * Return: Non-zero value on failure.
11601 */
852e85a7
JP
11602int devl_traps_register(struct devlink *devlink,
11603 const struct devlink_trap *traps,
11604 size_t traps_count, void *priv)
0f420b6c
IS
11605{
11606 int i, err;
11607
11608 if (!devlink->ops->trap_init || !devlink->ops->trap_action_set)
11609 return -EINVAL;
11610
852e85a7 11611 devl_assert_locked(devlink);
0f420b6c
IS
11612 for (i = 0; i < traps_count; i++) {
11613 const struct devlink_trap *trap = &traps[i];
11614
11615 err = devlink_trap_verify(trap);
11616 if (err)
11617 goto err_trap_verify;
11618
11619 err = devlink_trap_register(devlink, trap, priv);
11620 if (err)
11621 goto err_trap_register;
11622 }
0f420b6c
IS
11623
11624 return 0;
11625
11626err_trap_register:
11627err_trap_verify:
11628 for (i--; i >= 0; i--)
11629 devlink_trap_unregister(devlink, &traps[i]);
852e85a7
JP
11630 return err;
11631}
11632EXPORT_SYMBOL_GPL(devl_traps_register);
11633
11634/**
11635 * devlink_traps_register - Register packet traps with devlink.
11636 * @devlink: devlink.
11637 * @traps: Packet traps.
11638 * @traps_count: Count of provided packet traps.
11639 * @priv: Driver private information.
11640 *
11641 * Context: Takes and release devlink->lock <mutex>.
11642 *
11643 * Return: Non-zero value on failure.
11644 */
11645int devlink_traps_register(struct devlink *devlink,
11646 const struct devlink_trap *traps,
11647 size_t traps_count, void *priv)
11648{
11649 int err;
11650
11651 devl_lock(devlink);
11652 err = devl_traps_register(devlink, traps, traps_count, priv);
7715023a 11653 devl_unlock(devlink);
0f420b6c
IS
11654 return err;
11655}
11656EXPORT_SYMBOL_GPL(devlink_traps_register);
11657
11658/**
852e85a7 11659 * devl_traps_unregister - Unregister packet traps from devlink.
0f420b6c
IS
11660 * @devlink: devlink.
11661 * @traps: Packet traps.
11662 * @traps_count: Count of provided packet traps.
11663 */
852e85a7
JP
11664void devl_traps_unregister(struct devlink *devlink,
11665 const struct devlink_trap *traps,
11666 size_t traps_count)
0f420b6c
IS
11667{
11668 int i;
11669
852e85a7 11670 devl_assert_locked(devlink);
0f420b6c
IS
11671 /* Make sure we do not have any packets in-flight while unregistering
11672 * traps by disabling all of them and waiting for a grace period.
11673 */
11674 for (i = traps_count - 1; i >= 0; i--)
11675 devlink_trap_disable(devlink, &traps[i]);
11676 synchronize_rcu();
11677 for (i = traps_count - 1; i >= 0; i--)
11678 devlink_trap_unregister(devlink, &traps[i]);
852e85a7
JP
11679}
11680EXPORT_SYMBOL_GPL(devl_traps_unregister);
11681
11682/**
11683 * devlink_traps_unregister - Unregister packet traps from devlink.
11684 * @devlink: devlink.
11685 * @traps: Packet traps.
11686 * @traps_count: Count of provided packet traps.
11687 *
11688 * Context: Takes and release devlink->lock <mutex>.
11689 */
11690void devlink_traps_unregister(struct devlink *devlink,
11691 const struct devlink_trap *traps,
11692 size_t traps_count)
11693{
11694 devl_lock(devlink);
11695 devl_traps_unregister(devlink, traps, traps_count);
7715023a 11696 devl_unlock(devlink);
0f420b6c
IS
11697}
11698EXPORT_SYMBOL_GPL(devlink_traps_unregister);
11699
11700static void
11701devlink_trap_stats_update(struct devlink_stats __percpu *trap_stats,
11702 size_t skb_len)
11703{
11704 struct devlink_stats *stats;
11705
11706 stats = this_cpu_ptr(trap_stats);
11707 u64_stats_update_begin(&stats->syncp);
958751e0
ED
11708 u64_stats_add(&stats->rx_bytes, skb_len);
11709 u64_stats_inc(&stats->rx_packets);
0f420b6c
IS
11710 u64_stats_update_end(&stats->syncp);
11711}
11712
5b88823b
IS
11713static void
11714devlink_trap_report_metadata_set(struct devlink_trap_metadata *metadata,
11715 const struct devlink_trap_item *trap_item,
11716 struct devlink_port *in_devlink_port,
11717 const struct flow_action_cookie *fa_cookie)
11718{
11719 metadata->trap_name = trap_item->trap->name;
11720 metadata->trap_group_name = trap_item->group_item->group->name;
11721 metadata->fa_cookie = fa_cookie;
93e15596 11722 metadata->trap_type = trap_item->trap->type;
5b88823b
IS
11723
11724 spin_lock(&in_devlink_port->type_lock);
11725 if (in_devlink_port->type == DEVLINK_PORT_TYPE_ETH)
3830c571 11726 metadata->input_dev = in_devlink_port->type_eth.netdev;
5b88823b
IS
11727 spin_unlock(&in_devlink_port->type_lock);
11728}
11729
0f420b6c
IS
11730/**
11731 * devlink_trap_report - Report trapped packet to drop monitor.
11732 * @devlink: devlink.
11733 * @skb: Trapped packet.
11734 * @trap_ctx: Trap context.
11735 * @in_devlink_port: Input devlink port.
5a2e106c 11736 * @fa_cookie: Flow action cookie. Could be NULL.
0f420b6c
IS
11737 */
11738void devlink_trap_report(struct devlink *devlink, struct sk_buff *skb,
5a2e106c
JP
11739 void *trap_ctx, struct devlink_port *in_devlink_port,
11740 const struct flow_action_cookie *fa_cookie)
11741
0f420b6c
IS
11742{
11743 struct devlink_trap_item *trap_item = trap_ctx;
0f420b6c
IS
11744
11745 devlink_trap_stats_update(trap_item->stats, skb->len);
11746 devlink_trap_stats_update(trap_item->group_item->stats, skb->len);
11747
5b88823b
IS
11748 if (trace_devlink_trap_report_enabled()) {
11749 struct devlink_trap_metadata metadata = {};
11750
11751 devlink_trap_report_metadata_set(&metadata, trap_item,
11752 in_devlink_port, fa_cookie);
11753 trace_devlink_trap_report(devlink, skb, &metadata);
11754 }
0f420b6c
IS
11755}
11756EXPORT_SYMBOL_GPL(devlink_trap_report);
11757
11758/**
11759 * devlink_trap_ctx_priv - Trap context to driver private information.
11760 * @trap_ctx: Trap context.
11761 *
11762 * Return: Driver private information passed during registration.
11763 */
11764void *devlink_trap_ctx_priv(void *trap_ctx)
11765{
11766 struct devlink_trap_item *trap_item = trap_ctx;
11767
11768 return trap_item->priv;
11769}
11770EXPORT_SYMBOL_GPL(devlink_trap_ctx_priv);
11771
f9f54392
IS
11772static int
11773devlink_trap_group_item_policer_link(struct devlink *devlink,
11774 struct devlink_trap_group_item *group_item)
11775{
11776 u32 policer_id = group_item->group->init_policer_id;
11777 struct devlink_trap_policer_item *policer_item;
11778
11779 if (policer_id == 0)
11780 return 0;
11781
11782 policer_item = devlink_trap_policer_item_lookup(devlink, policer_id);
11783 if (WARN_ON_ONCE(!policer_item))
11784 return -EINVAL;
11785
11786 group_item->policer_item = policer_item;
11787
11788 return 0;
11789}
11790
95ad9555
IS
11791static int
11792devlink_trap_group_register(struct devlink *devlink,
11793 const struct devlink_trap_group *group)
11794{
11795 struct devlink_trap_group_item *group_item;
11796 int err;
11797
11798 if (devlink_trap_group_item_lookup(devlink, group->name))
11799 return -EEXIST;
11800
11801 group_item = kzalloc(sizeof(*group_item), GFP_KERNEL);
11802 if (!group_item)
11803 return -ENOMEM;
11804
11805 group_item->stats = netdev_alloc_pcpu_stats(struct devlink_stats);
11806 if (!group_item->stats) {
11807 err = -ENOMEM;
11808 goto err_stats_alloc;
11809 }
11810
11811 group_item->group = group;
95ad9555 11812
f9f54392
IS
11813 err = devlink_trap_group_item_policer_link(devlink, group_item);
11814 if (err)
11815 goto err_policer_link;
11816
95ad9555
IS
11817 if (devlink->ops->trap_group_init) {
11818 err = devlink->ops->trap_group_init(devlink, group);
11819 if (err)
11820 goto err_group_init;
11821 }
11822
11823 list_add_tail(&group_item->list, &devlink->trap_group_list);
fb9d19c2
LR
11824 devlink_trap_group_notify(devlink, group_item,
11825 DEVLINK_CMD_TRAP_GROUP_NEW);
11826
95ad9555
IS
11827 return 0;
11828
11829err_group_init:
f9f54392 11830err_policer_link:
95ad9555
IS
11831 free_percpu(group_item->stats);
11832err_stats_alloc:
11833 kfree(group_item);
11834 return err;
11835}
11836
11837static void
11838devlink_trap_group_unregister(struct devlink *devlink,
11839 const struct devlink_trap_group *group)
11840{
11841 struct devlink_trap_group_item *group_item;
11842
11843 group_item = devlink_trap_group_item_lookup(devlink, group->name);
11844 if (WARN_ON_ONCE(!group_item))
11845 return;
11846
fb9d19c2
LR
11847 devlink_trap_group_notify(devlink, group_item,
11848 DEVLINK_CMD_TRAP_GROUP_DEL);
95ad9555
IS
11849 list_del(&group_item->list);
11850 free_percpu(group_item->stats);
11851 kfree(group_item);
11852}
11853
11854/**
852e85a7 11855 * devl_trap_groups_register - Register packet trap groups with devlink.
95ad9555
IS
11856 * @devlink: devlink.
11857 * @groups: Packet trap groups.
11858 * @groups_count: Count of provided packet trap groups.
11859 *
11860 * Return: Non-zero value on failure.
11861 */
852e85a7
JP
11862int devl_trap_groups_register(struct devlink *devlink,
11863 const struct devlink_trap_group *groups,
11864 size_t groups_count)
95ad9555
IS
11865{
11866 int i, err;
11867
852e85a7 11868 devl_assert_locked(devlink);
95ad9555
IS
11869 for (i = 0; i < groups_count; i++) {
11870 const struct devlink_trap_group *group = &groups[i];
11871
11872 err = devlink_trap_group_verify(group);
11873 if (err)
11874 goto err_trap_group_verify;
11875
11876 err = devlink_trap_group_register(devlink, group);
11877 if (err)
11878 goto err_trap_group_register;
11879 }
95ad9555
IS
11880
11881 return 0;
11882
11883err_trap_group_register:
11884err_trap_group_verify:
11885 for (i--; i >= 0; i--)
11886 devlink_trap_group_unregister(devlink, &groups[i]);
852e85a7
JP
11887 return err;
11888}
11889EXPORT_SYMBOL_GPL(devl_trap_groups_register);
11890
11891/**
11892 * devlink_trap_groups_register - Register packet trap groups with devlink.
11893 * @devlink: devlink.
11894 * @groups: Packet trap groups.
11895 * @groups_count: Count of provided packet trap groups.
11896 *
11897 * Context: Takes and release devlink->lock <mutex>.
11898 *
11899 * Return: Non-zero value on failure.
11900 */
11901int devlink_trap_groups_register(struct devlink *devlink,
11902 const struct devlink_trap_group *groups,
11903 size_t groups_count)
11904{
11905 int err;
11906
11907 devl_lock(devlink);
11908 err = devl_trap_groups_register(devlink, groups, groups_count);
7715023a 11909 devl_unlock(devlink);
95ad9555
IS
11910 return err;
11911}
11912EXPORT_SYMBOL_GPL(devlink_trap_groups_register);
11913
852e85a7
JP
11914/**
11915 * devl_trap_groups_unregister - Unregister packet trap groups from devlink.
11916 * @devlink: devlink.
11917 * @groups: Packet trap groups.
11918 * @groups_count: Count of provided packet trap groups.
11919 */
11920void devl_trap_groups_unregister(struct devlink *devlink,
11921 const struct devlink_trap_group *groups,
11922 size_t groups_count)
11923{
11924 int i;
11925
11926 devl_assert_locked(devlink);
11927 for (i = groups_count - 1; i >= 0; i--)
11928 devlink_trap_group_unregister(devlink, &groups[i]);
11929}
11930EXPORT_SYMBOL_GPL(devl_trap_groups_unregister);
11931
95ad9555
IS
11932/**
11933 * devlink_trap_groups_unregister - Unregister packet trap groups from devlink.
11934 * @devlink: devlink.
11935 * @groups: Packet trap groups.
11936 * @groups_count: Count of provided packet trap groups.
852e85a7
JP
11937 *
11938 * Context: Takes and release devlink->lock <mutex>.
95ad9555
IS
11939 */
11940void devlink_trap_groups_unregister(struct devlink *devlink,
11941 const struct devlink_trap_group *groups,
11942 size_t groups_count)
11943{
7715023a 11944 devl_lock(devlink);
852e85a7 11945 devl_trap_groups_unregister(devlink, groups, groups_count);
7715023a 11946 devl_unlock(devlink);
95ad9555
IS
11947}
11948EXPORT_SYMBOL_GPL(devlink_trap_groups_unregister);
11949
1e8c6619
IS
11950static void
11951devlink_trap_policer_notify(struct devlink *devlink,
11952 const struct devlink_trap_policer_item *policer_item,
11953 enum devlink_command cmd)
11954{
11955 struct sk_buff *msg;
11956 int err;
11957
11958 WARN_ON_ONCE(cmd != DEVLINK_CMD_TRAP_POLICER_NEW &&
11959 cmd != DEVLINK_CMD_TRAP_POLICER_DEL);
c5e0321e
LR
11960 if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED))
11961 return;
1e8c6619
IS
11962
11963 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
11964 if (!msg)
11965 return;
11966
11967 err = devlink_nl_trap_policer_fill(msg, devlink, policer_item, cmd, 0,
11968 0, 0);
11969 if (err) {
11970 nlmsg_free(msg);
11971 return;
11972 }
11973
11974 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
11975 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
11976}
11977
11978static int
11979devlink_trap_policer_register(struct devlink *devlink,
11980 const struct devlink_trap_policer *policer)
11981{
11982 struct devlink_trap_policer_item *policer_item;
11983 int err;
11984
11985 if (devlink_trap_policer_item_lookup(devlink, policer->id))
11986 return -EEXIST;
11987
11988 policer_item = kzalloc(sizeof(*policer_item), GFP_KERNEL);
11989 if (!policer_item)
11990 return -ENOMEM;
11991
11992 policer_item->policer = policer;
11993 policer_item->rate = policer->init_rate;
11994 policer_item->burst = policer->init_burst;
11995
11996 if (devlink->ops->trap_policer_init) {
11997 err = devlink->ops->trap_policer_init(devlink, policer);
11998 if (err)
11999 goto err_policer_init;
12000 }
12001
12002 list_add_tail(&policer_item->list, &devlink->trap_policer_list);
c5e0321e
LR
12003 devlink_trap_policer_notify(devlink, policer_item,
12004 DEVLINK_CMD_TRAP_POLICER_NEW);
12005
1e8c6619
IS
12006 return 0;
12007
12008err_policer_init:
12009 kfree(policer_item);
12010 return err;
12011}
12012
12013static void
12014devlink_trap_policer_unregister(struct devlink *devlink,
12015 const struct devlink_trap_policer *policer)
12016{
12017 struct devlink_trap_policer_item *policer_item;
12018
12019 policer_item = devlink_trap_policer_item_lookup(devlink, policer->id);
12020 if (WARN_ON_ONCE(!policer_item))
12021 return;
12022
c5e0321e
LR
12023 devlink_trap_policer_notify(devlink, policer_item,
12024 DEVLINK_CMD_TRAP_POLICER_DEL);
1e8c6619
IS
12025 list_del(&policer_item->list);
12026 if (devlink->ops->trap_policer_fini)
12027 devlink->ops->trap_policer_fini(devlink, policer);
12028 kfree(policer_item);
12029}
12030
12031/**
852e85a7 12032 * devl_trap_policers_register - Register packet trap policers with devlink.
1e8c6619
IS
12033 * @devlink: devlink.
12034 * @policers: Packet trap policers.
12035 * @policers_count: Count of provided packet trap policers.
12036 *
12037 * Return: Non-zero value on failure.
12038 */
12039int
852e85a7
JP
12040devl_trap_policers_register(struct devlink *devlink,
12041 const struct devlink_trap_policer *policers,
12042 size_t policers_count)
1e8c6619
IS
12043{
12044 int i, err;
12045
852e85a7 12046 devl_assert_locked(devlink);
1e8c6619
IS
12047 for (i = 0; i < policers_count; i++) {
12048 const struct devlink_trap_policer *policer = &policers[i];
12049
12050 if (WARN_ON(policer->id == 0 ||
12051 policer->max_rate < policer->min_rate ||
12052 policer->max_burst < policer->min_burst)) {
12053 err = -EINVAL;
12054 goto err_trap_policer_verify;
12055 }
12056
12057 err = devlink_trap_policer_register(devlink, policer);
12058 if (err)
12059 goto err_trap_policer_register;
12060 }
1e8c6619
IS
12061 return 0;
12062
12063err_trap_policer_register:
12064err_trap_policer_verify:
12065 for (i--; i >= 0; i--)
12066 devlink_trap_policer_unregister(devlink, &policers[i]);
852e85a7
JP
12067 return err;
12068}
12069EXPORT_SYMBOL_GPL(devl_trap_policers_register);
12070
852e85a7
JP
12071/**
12072 * devl_trap_policers_unregister - Unregister packet trap policers from devlink.
12073 * @devlink: devlink.
12074 * @policers: Packet trap policers.
12075 * @policers_count: Count of provided packet trap policers.
12076 */
12077void
12078devl_trap_policers_unregister(struct devlink *devlink,
12079 const struct devlink_trap_policer *policers,
12080 size_t policers_count)
12081{
12082 int i;
12083
12084 devl_assert_locked(devlink);
12085 for (i = policers_count - 1; i >= 0; i--)
12086 devlink_trap_policer_unregister(devlink, &policers[i]);
12087}
12088EXPORT_SYMBOL_GPL(devl_trap_policers_unregister);
12089
ddb6e99e
JK
12090static void __devlink_compat_running_version(struct devlink *devlink,
12091 char *buf, size_t len)
12092{
f94b6063 12093 struct devlink_info_req req = {};
ddb6e99e 12094 const struct nlattr *nlattr;
ddb6e99e
JK
12095 struct sk_buff *msg;
12096 int rem, err;
12097
ddb6e99e
JK
12098 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
12099 if (!msg)
12100 return;
12101
12102 req.msg = msg;
12103 err = devlink->ops->info_get(devlink, &req, NULL);
12104 if (err)
12105 goto free_msg;
12106
12107 nla_for_each_attr(nlattr, (void *)msg->data, msg->len, rem) {
12108 const struct nlattr *kv;
12109 int rem_kv;
12110
12111 if (nla_type(nlattr) != DEVLINK_ATTR_INFO_VERSION_RUNNING)
12112 continue;
12113
12114 nla_for_each_nested(kv, nlattr, rem_kv) {
12115 if (nla_type(kv) != DEVLINK_ATTR_INFO_VERSION_VALUE)
12116 continue;
12117
12118 strlcat(buf, nla_data(kv), len);
12119 strlcat(buf, " ", len);
12120 }
12121 }
12122free_msg:
12123 nlmsg_free(msg);
12124}
12125
1af0a094 12126void devlink_compat_running_version(struct devlink *devlink,
ddb6e99e
JK
12127 char *buf, size_t len)
12128{
1af0a094
JK
12129 if (!devlink->ops->info_get)
12130 return;
b473b0d2 12131
7715023a 12132 devl_lock(devlink);
ed539ba6
JK
12133 if (devl_is_registered(devlink))
12134 __devlink_compat_running_version(devlink, buf, len);
7715023a 12135 devl_unlock(devlink);
ddb6e99e
JK
12136}
12137
1af0a094 12138int devlink_compat_flash_update(struct devlink *devlink, const char *file_name)
4eceba17 12139{
bc75c054 12140 struct devlink_flash_update_params params = {};
e0dcd386 12141 int ret;
4eceba17 12142
ed539ba6
JK
12143 devl_lock(devlink);
12144 if (!devl_is_registered(devlink)) {
12145 ret = -ENODEV;
12146 goto out_unlock;
12147 }
12148
12149 if (!devlink->ops->flash_update) {
12150 ret = -EOPNOTSUPP;
12151 goto out_unlock;
12152 }
4eceba17 12153
b44cfd4f
JK
12154 ret = request_firmware(&params.fw, file_name, devlink->dev);
12155 if (ret)
ed539ba6 12156 goto out_unlock;
bc75c054 12157
52cc5f3a 12158 devlink_flash_update_begin_notify(devlink);
bc75c054 12159 ret = devlink->ops->flash_update(devlink, &params, NULL);
52cc5f3a 12160 devlink_flash_update_end_notify(devlink);
1b45ff6c 12161
b44cfd4f 12162 release_firmware(params.fw);
ed539ba6
JK
12163out_unlock:
12164 devl_unlock(devlink);
b44cfd4f 12165
b473b0d2 12166 return ret;
4eceba17
JK
12167}
12168
af3836df
JP
12169int devlink_compat_phys_port_name_get(struct net_device *dev,
12170 char *name, size_t len)
12171{
12172 struct devlink_port *devlink_port;
12173
12174 /* RTNL mutex is held here which ensures that devlink_port
12175 * instance cannot disappear in the middle. No need to take
12176 * any devlink lock as only permanent values are accessed.
12177 */
12178 ASSERT_RTNL();
12179
8eba37f7 12180 devlink_port = dev->devlink_port;
af3836df
JP
12181 if (!devlink_port)
12182 return -EOPNOTSUPP;
12183
12184 return __devlink_port_phys_port_name_get(devlink_port, name, len);
12185}
12186
7e1146e8
JP
12187int devlink_compat_switch_id_get(struct net_device *dev,
12188 struct netdev_phys_item_id *ppid)
12189{
12190 struct devlink_port *devlink_port;
12191
043b8413
VB
12192 /* Caller must hold RTNL mutex or reference to dev, which ensures that
12193 * devlink_port instance cannot disappear in the middle. No need to take
7e1146e8
JP
12194 * any devlink lock as only permanent values are accessed.
12195 */
8eba37f7 12196 devlink_port = dev->devlink_port;
46737a19 12197 if (!devlink_port || !devlink_port->switch_port)
7e1146e8
JP
12198 return -EOPNOTSUPP;
12199
12200 memcpy(ppid, &devlink_port->attrs.switch_id, sizeof(*ppid));
12201
12202 return 0;
12203}