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