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