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/kernel.h>
11#include <linux/module.h>
12#include <linux/types.h>
13#include <linux/slab.h>
14#include <linux/gfp.h>
15#include <linux/device.h>
16#include <linux/list.h>
17#include <linux/netdevice.h>
18#include <linux/spinlock.h>
19#include <linux/refcount.h>
20#include <linux/workqueue.h>
21#include <rdma/ib_verbs.h>
22#include <net/netlink.h>
23#include <net/genetlink.h>
24#include <net/rtnetlink.h>
25#include <net/net_namespace.h>
26#include <net/sock.h>
27#include <net/devlink.h>
28#define CREATE_TRACE_POINTS
29#include <trace/events/devlink.h>
30
31static struct devlink_dpipe_field devlink_dpipe_fields_ethernet[] = {
32 {
33 .name = "destination mac",
34 .id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC,
35 .bitwidth = 48,
36 },
37};
38
39struct devlink_dpipe_header devlink_dpipe_header_ethernet = {
40 .name = "ethernet",
41 .id = DEVLINK_DPIPE_HEADER_ETHERNET,
42 .fields = devlink_dpipe_fields_ethernet,
43 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ethernet),
44 .global = true,
45};
46EXPORT_SYMBOL(devlink_dpipe_header_ethernet);
47
48static struct devlink_dpipe_field devlink_dpipe_fields_ipv4[] = {
49 {
50 .name = "destination ip",
51 .id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP,
52 .bitwidth = 32,
53 },
54};
55
56struct devlink_dpipe_header devlink_dpipe_header_ipv4 = {
57 .name = "ipv4",
58 .id = DEVLINK_DPIPE_HEADER_IPV4,
59 .fields = devlink_dpipe_fields_ipv4,
60 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv4),
61 .global = true,
62};
63EXPORT_SYMBOL(devlink_dpipe_header_ipv4);
64
65static struct devlink_dpipe_field devlink_dpipe_fields_ipv6[] = {
66 {
67 .name = "destination ip",
68 .id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP,
69 .bitwidth = 128,
70 },
71};
72
73struct devlink_dpipe_header devlink_dpipe_header_ipv6 = {
74 .name = "ipv6",
75 .id = DEVLINK_DPIPE_HEADER_IPV6,
76 .fields = devlink_dpipe_fields_ipv6,
77 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv6),
78 .global = true,
79};
80EXPORT_SYMBOL(devlink_dpipe_header_ipv6);
81
82EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg);
83EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwerr);
84
85static LIST_HEAD(devlink_list);
86
87/* devlink_mutex
88 *
89 * An overall lock guarding every operation coming from userspace.
90 * It also guards devlink devices list and it is taken when
91 * driver registers/unregisters it.
92 */
93static DEFINE_MUTEX(devlink_mutex);
94
95static struct net *devlink_net(const struct devlink *devlink)
96{
97 return read_pnet(&devlink->_net);
98}
99
100static void devlink_net_set(struct devlink *devlink, struct net *net)
101{
102 write_pnet(&devlink->_net, net);
103}
104
105static struct devlink *devlink_get_from_attrs(struct net *net,
106 struct nlattr **attrs)
107{
108 struct devlink *devlink;
109 char *busname;
110 char *devname;
111
112 if (!attrs[DEVLINK_ATTR_BUS_NAME] || !attrs[DEVLINK_ATTR_DEV_NAME])
113 return ERR_PTR(-EINVAL);
114
115 busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]);
116 devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
117
118 lockdep_assert_held(&devlink_mutex);
119
120 list_for_each_entry(devlink, &devlink_list, list) {
121 if (strcmp(devlink->dev->bus->name, busname) == 0 &&
122 strcmp(dev_name(devlink->dev), devname) == 0 &&
123 net_eq(devlink_net(devlink), net))
124 return devlink;
125 }
126
127 return ERR_PTR(-ENODEV);
128}
129
130static struct devlink *devlink_get_from_info(struct genl_info *info)
131{
132 return devlink_get_from_attrs(genl_info_net(info), info->attrs);
133}
134
135static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink,
136 int port_index)
137{
138 struct devlink_port *devlink_port;
139
140 list_for_each_entry(devlink_port, &devlink->port_list, list) {
141 if (devlink_port->index == port_index)
142 return devlink_port;
143 }
144 return NULL;
145}
146
147static bool devlink_port_index_exists(struct devlink *devlink, int port_index)
148{
149 return devlink_port_get_by_index(devlink, port_index);
150}
151
152static struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink,
153 struct nlattr **attrs)
154{
155 if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
156 u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
157 struct devlink_port *devlink_port;
158
159 devlink_port = devlink_port_get_by_index(devlink, port_index);
160 if (!devlink_port)
161 return ERR_PTR(-ENODEV);
162 return devlink_port;
163 }
164 return ERR_PTR(-EINVAL);
165}
166
167static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink,
168 struct genl_info *info)
169{
170 return devlink_port_get_from_attrs(devlink, info->attrs);
171}
172
173struct devlink_sb {
174 struct list_head list;
175 unsigned int index;
176 u32 size;
177 u16 ingress_pools_count;
178 u16 egress_pools_count;
179 u16 ingress_tc_count;
180 u16 egress_tc_count;
181};
182
183static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb)
184{
185 return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count;
186}
187
188static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink,
189 unsigned int sb_index)
190{
191 struct devlink_sb *devlink_sb;
192
193 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
194 if (devlink_sb->index == sb_index)
195 return devlink_sb;
196 }
197 return NULL;
198}
199
200static bool devlink_sb_index_exists(struct devlink *devlink,
201 unsigned int sb_index)
202{
203 return devlink_sb_get_by_index(devlink, sb_index);
204}
205
206static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink,
207 struct nlattr **attrs)
208{
209 if (attrs[DEVLINK_ATTR_SB_INDEX]) {
210 u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]);
211 struct devlink_sb *devlink_sb;
212
213 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
214 if (!devlink_sb)
215 return ERR_PTR(-ENODEV);
216 return devlink_sb;
217 }
218 return ERR_PTR(-EINVAL);
219}
220
221static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink,
222 struct genl_info *info)
223{
224 return devlink_sb_get_from_attrs(devlink, info->attrs);
225}
226
227static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb,
228 struct nlattr **attrs,
229 u16 *p_pool_index)
230{
231 u16 val;
232
233 if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX])
234 return -EINVAL;
235
236 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]);
237 if (val >= devlink_sb_pool_count(devlink_sb))
238 return -EINVAL;
239 *p_pool_index = val;
240 return 0;
241}
242
243static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb,
244 struct genl_info *info,
245 u16 *p_pool_index)
246{
247 return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs,
248 p_pool_index);
249}
250
251static int
252devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs,
253 enum devlink_sb_pool_type *p_pool_type)
254{
255 u8 val;
256
257 if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE])
258 return -EINVAL;
259
260 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]);
261 if (val != DEVLINK_SB_POOL_TYPE_INGRESS &&
262 val != DEVLINK_SB_POOL_TYPE_EGRESS)
263 return -EINVAL;
264 *p_pool_type = val;
265 return 0;
266}
267
268static int
269devlink_sb_pool_type_get_from_info(struct genl_info *info,
270 enum devlink_sb_pool_type *p_pool_type)
271{
272 return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type);
273}
274
275static int
276devlink_sb_th_type_get_from_attrs(struct nlattr **attrs,
277 enum devlink_sb_threshold_type *p_th_type)
278{
279 u8 val;
280
281 if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE])
282 return -EINVAL;
283
284 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]);
285 if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC &&
286 val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC)
287 return -EINVAL;
288 *p_th_type = val;
289 return 0;
290}
291
292static int
293devlink_sb_th_type_get_from_info(struct genl_info *info,
294 enum devlink_sb_threshold_type *p_th_type)
295{
296 return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type);
297}
298
299static int
300devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb,
301 struct nlattr **attrs,
302 enum devlink_sb_pool_type pool_type,
303 u16 *p_tc_index)
304{
305 u16 val;
306
307 if (!attrs[DEVLINK_ATTR_SB_TC_INDEX])
308 return -EINVAL;
309
310 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]);
311 if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS &&
312 val >= devlink_sb->ingress_tc_count)
313 return -EINVAL;
314 if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS &&
315 val >= devlink_sb->egress_tc_count)
316 return -EINVAL;
317 *p_tc_index = val;
318 return 0;
319}
320
321static int
322devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb,
323 struct genl_info *info,
324 enum devlink_sb_pool_type pool_type,
325 u16 *p_tc_index)
326{
327 return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs,
328 pool_type, p_tc_index);
329}
330
331struct devlink_region {
332 struct devlink *devlink;
333 struct list_head list;
334 const char *name;
335 struct list_head snapshot_list;
336 u32 max_snapshots;
337 u32 cur_snapshots;
338 u64 size;
339};
340
341struct devlink_snapshot {
342 struct list_head list;
343 struct devlink_region *region;
344 devlink_snapshot_data_dest_t *data_destructor;
345 u64 data_len;
346 u8 *data;
347 u32 id;
348};
349
350static struct devlink_region *
351devlink_region_get_by_name(struct devlink *devlink, const char *region_name)
352{
353 struct devlink_region *region;
354
355 list_for_each_entry(region, &devlink->region_list, list)
356 if (!strcmp(region->name, region_name))
357 return region;
358
359 return NULL;
360}
361
362static struct devlink_snapshot *
363devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id)
364{
365 struct devlink_snapshot *snapshot;
366
367 list_for_each_entry(snapshot, ®ion->snapshot_list, list)
368 if (snapshot->id == id)
369 return snapshot;
370
371 return NULL;
372}
373
374static void devlink_region_snapshot_del(struct devlink_snapshot *snapshot)
375{
376 snapshot->region->cur_snapshots--;
377 list_del(&snapshot->list);
378 (*snapshot->data_destructor)(snapshot->data);
379 kfree(snapshot);
380}
381
382#define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0)
383#define DEVLINK_NL_FLAG_NEED_PORT BIT(1)
384#define DEVLINK_NL_FLAG_NEED_SB BIT(2)
385
386/* The per devlink instance lock is taken by default in the pre-doit
387 * operation, yet several commands do not require this. The global
388 * devlink lock is taken and protects from disruption by user-calls.
389 */
390#define DEVLINK_NL_FLAG_NO_LOCK BIT(3)
391
392static int devlink_nl_pre_doit(const struct genl_ops *ops,
393 struct sk_buff *skb, struct genl_info *info)
394{
395 struct devlink *devlink;
396 int err;
397
398 mutex_lock(&devlink_mutex);
399 devlink = devlink_get_from_info(info);
400 if (IS_ERR(devlink)) {
401 mutex_unlock(&devlink_mutex);
402 return PTR_ERR(devlink);
403 }
404 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
405 mutex_lock(&devlink->lock);
406 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) {
407 info->user_ptr[0] = devlink;
408 } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) {
409 struct devlink_port *devlink_port;
410
411 devlink_port = devlink_port_get_from_info(devlink, info);
412 if (IS_ERR(devlink_port)) {
413 err = PTR_ERR(devlink_port);
414 goto unlock;
415 }
416 info->user_ptr[0] = devlink_port;
417 }
418 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) {
419 struct devlink_sb *devlink_sb;
420
421 devlink_sb = devlink_sb_get_from_info(devlink, info);
422 if (IS_ERR(devlink_sb)) {
423 err = PTR_ERR(devlink_sb);
424 goto unlock;
425 }
426 info->user_ptr[1] = devlink_sb;
427 }
428 return 0;
429
430unlock:
431 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
432 mutex_unlock(&devlink->lock);
433 mutex_unlock(&devlink_mutex);
434 return err;
435}
436
437static void devlink_nl_post_doit(const struct genl_ops *ops,
438 struct sk_buff *skb, struct genl_info *info)
439{
440 struct devlink *devlink;
441
442 devlink = devlink_get_from_info(info);
443 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK)
444 mutex_unlock(&devlink->lock);
445 mutex_unlock(&devlink_mutex);
446}
447
448static struct genl_family devlink_nl_family;
449
450enum devlink_multicast_groups {
451 DEVLINK_MCGRP_CONFIG,
452};
453
454static const struct genl_multicast_group devlink_nl_mcgrps[] = {
455 [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME },
456};
457
458static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
459{
460 if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
461 return -EMSGSIZE;
462 if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
463 return -EMSGSIZE;
464 return 0;
465}
466
467static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
468 enum devlink_command cmd, u32 portid,
469 u32 seq, int flags)
470{
471 void *hdr;
472
473 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
474 if (!hdr)
475 return -EMSGSIZE;
476
477 if (devlink_nl_put_handle(msg, devlink))
478 goto nla_put_failure;
479
480 genlmsg_end(msg, hdr);
481 return 0;
482
483nla_put_failure:
484 genlmsg_cancel(msg, hdr);
485 return -EMSGSIZE;
486}
487
488static void devlink_notify(struct devlink *devlink, enum devlink_command cmd)
489{
490 struct sk_buff *msg;
491 int err;
492
493 WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL);
494
495 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
496 if (!msg)
497 return;
498
499 err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0);
500 if (err) {
501 nlmsg_free(msg);
502 return;
503 }
504
505 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
506 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
507}
508
509static int devlink_nl_port_attrs_put(struct sk_buff *msg,
510 struct devlink_port *devlink_port)
511{
512 struct devlink_port_attrs *attrs = &devlink_port->attrs;
513
514 if (!attrs->set)
515 return 0;
516 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour))
517 return -EMSGSIZE;
518 if (devlink_port->attrs.flavour == DEVLINK_PORT_FLAVOUR_PCI_PF) {
519 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER,
520 attrs->pci_pf.pf))
521 return -EMSGSIZE;
522 } else if (devlink_port->attrs.flavour == DEVLINK_PORT_FLAVOUR_PCI_VF) {
523 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER,
524 attrs->pci_vf.pf) ||
525 nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_VF_NUMBER,
526 attrs->pci_vf.vf))
527 return -EMSGSIZE;
528 }
529 if (devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PHYSICAL &&
530 devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_CPU &&
531 devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_DSA)
532 return 0;
533 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER,
534 attrs->phys.port_number))
535 return -EMSGSIZE;
536 if (!attrs->split)
537 return 0;
538 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP,
539 attrs->phys.port_number))
540 return -EMSGSIZE;
541 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER,
542 attrs->phys.split_subport_number))
543 return -EMSGSIZE;
544 return 0;
545}
546
547static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
548 struct devlink_port *devlink_port,
549 enum devlink_command cmd, u32 portid,
550 u32 seq, int flags)
551{
552 void *hdr;
553
554 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
555 if (!hdr)
556 return -EMSGSIZE;
557
558 if (devlink_nl_put_handle(msg, devlink))
559 goto nla_put_failure;
560 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
561 goto nla_put_failure;
562
563 spin_lock(&devlink_port->type_lock);
564 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type))
565 goto nla_put_failure_type_locked;
566 if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET &&
567 nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE,
568 devlink_port->desired_type))
569 goto nla_put_failure_type_locked;
570 if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) {
571 struct net_device *netdev = devlink_port->type_dev;
572
573 if (netdev &&
574 (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX,
575 netdev->ifindex) ||
576 nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME,
577 netdev->name)))
578 goto nla_put_failure_type_locked;
579 }
580 if (devlink_port->type == DEVLINK_PORT_TYPE_IB) {
581 struct ib_device *ibdev = devlink_port->type_dev;
582
583 if (ibdev &&
584 nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME,
585 ibdev->name))
586 goto nla_put_failure_type_locked;
587 }
588 spin_unlock(&devlink_port->type_lock);
589 if (devlink_nl_port_attrs_put(msg, devlink_port))
590 goto nla_put_failure;
591
592 genlmsg_end(msg, hdr);
593 return 0;
594
595nla_put_failure_type_locked:
596 spin_unlock(&devlink_port->type_lock);
597nla_put_failure:
598 genlmsg_cancel(msg, hdr);
599 return -EMSGSIZE;
600}
601
602static void devlink_port_notify(struct devlink_port *devlink_port,
603 enum devlink_command cmd)
604{
605 struct devlink *devlink = devlink_port->devlink;
606 struct sk_buff *msg;
607 int err;
608
609 if (!devlink_port->registered)
610 return;
611
612 WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL);
613
614 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
615 if (!msg)
616 return;
617
618 err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0);
619 if (err) {
620 nlmsg_free(msg);
621 return;
622 }
623
624 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
625 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
626}
627
628static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info)
629{
630 struct devlink *devlink = info->user_ptr[0];
631 struct sk_buff *msg;
632 int err;
633
634 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
635 if (!msg)
636 return -ENOMEM;
637
638 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
639 info->snd_portid, info->snd_seq, 0);
640 if (err) {
641 nlmsg_free(msg);
642 return err;
643 }
644
645 return genlmsg_reply(msg, info);
646}
647
648static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg,
649 struct netlink_callback *cb)
650{
651 struct devlink *devlink;
652 int start = cb->args[0];
653 int idx = 0;
654 int err;
655
656 mutex_lock(&devlink_mutex);
657 list_for_each_entry(devlink, &devlink_list, list) {
658 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
659 continue;
660 if (idx < start) {
661 idx++;
662 continue;
663 }
664 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
665 NETLINK_CB(cb->skb).portid,
666 cb->nlh->nlmsg_seq, NLM_F_MULTI);
667 if (err)
668 goto out;
669 idx++;
670 }
671out:
672 mutex_unlock(&devlink_mutex);
673
674 cb->args[0] = idx;
675 return msg->len;
676}
677
678static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb,
679 struct genl_info *info)
680{
681 struct devlink_port *devlink_port = info->user_ptr[0];
682 struct devlink *devlink = devlink_port->devlink;
683 struct sk_buff *msg;
684 int err;
685
686 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
687 if (!msg)
688 return -ENOMEM;
689
690 err = devlink_nl_port_fill(msg, devlink, devlink_port,
691 DEVLINK_CMD_PORT_NEW,
692 info->snd_portid, info->snd_seq, 0);
693 if (err) {
694 nlmsg_free(msg);
695 return err;
696 }
697
698 return genlmsg_reply(msg, info);
699}
700
701static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg,
702 struct netlink_callback *cb)
703{
704 struct devlink *devlink;
705 struct devlink_port *devlink_port;
706 int start = cb->args[0];
707 int idx = 0;
708 int err;
709
710 mutex_lock(&devlink_mutex);
711 list_for_each_entry(devlink, &devlink_list, list) {
712 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
713 continue;
714 mutex_lock(&devlink->lock);
715 list_for_each_entry(devlink_port, &devlink->port_list, list) {
716 if (idx < start) {
717 idx++;
718 continue;
719 }
720 err = devlink_nl_port_fill(msg, devlink, devlink_port,
721 DEVLINK_CMD_NEW,
722 NETLINK_CB(cb->skb).portid,
723 cb->nlh->nlmsg_seq,
724 NLM_F_MULTI);
725 if (err) {
726 mutex_unlock(&devlink->lock);
727 goto out;
728 }
729 idx++;
730 }
731 mutex_unlock(&devlink->lock);
732 }
733out:
734 mutex_unlock(&devlink_mutex);
735
736 cb->args[0] = idx;
737 return msg->len;
738}
739
740static int devlink_port_type_set(struct devlink *devlink,
741 struct devlink_port *devlink_port,
742 enum devlink_port_type port_type)
743
744{
745 int err;
746
747 if (devlink->ops->port_type_set) {
748 if (port_type == DEVLINK_PORT_TYPE_NOTSET)
749 return -EINVAL;
750 if (port_type == devlink_port->type)
751 return 0;
752 err = devlink->ops->port_type_set(devlink_port, port_type);
753 if (err)
754 return err;
755 devlink_port->desired_type = port_type;
756 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
757 return 0;
758 }
759 return -EOPNOTSUPP;
760}
761
762static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb,
763 struct genl_info *info)
764{
765 struct devlink_port *devlink_port = info->user_ptr[0];
766 struct devlink *devlink = devlink_port->devlink;
767 int err;
768
769 if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) {
770 enum devlink_port_type port_type;
771
772 port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]);
773 err = devlink_port_type_set(devlink, devlink_port, port_type);
774 if (err)
775 return err;
776 }
777 return 0;
778}
779
780static int devlink_port_split(struct devlink *devlink, u32 port_index,
781 u32 count, struct netlink_ext_ack *extack)
782
783{
784 if (devlink->ops->port_split)
785 return devlink->ops->port_split(devlink, port_index, count,
786 extack);
787 return -EOPNOTSUPP;
788}
789
790static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb,
791 struct genl_info *info)
792{
793 struct devlink *devlink = info->user_ptr[0];
794 u32 port_index;
795 u32 count;
796
797 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] ||
798 !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT])
799 return -EINVAL;
800
801 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
802 count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]);
803 return devlink_port_split(devlink, port_index, count, info->extack);
804}
805
806static int devlink_port_unsplit(struct devlink *devlink, u32 port_index,
807 struct netlink_ext_ack *extack)
808
809{
810 if (devlink->ops->port_unsplit)
811 return devlink->ops->port_unsplit(devlink, port_index, extack);
812 return -EOPNOTSUPP;
813}
814
815static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb,
816 struct genl_info *info)
817{
818 struct devlink *devlink = info->user_ptr[0];
819 u32 port_index;
820
821 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX])
822 return -EINVAL;
823
824 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
825 return devlink_port_unsplit(devlink, port_index, info->extack);
826}
827
828static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink,
829 struct devlink_sb *devlink_sb,
830 enum devlink_command cmd, u32 portid,
831 u32 seq, int flags)
832{
833 void *hdr;
834
835 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
836 if (!hdr)
837 return -EMSGSIZE;
838
839 if (devlink_nl_put_handle(msg, devlink))
840 goto nla_put_failure;
841 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
842 goto nla_put_failure;
843 if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size))
844 goto nla_put_failure;
845 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT,
846 devlink_sb->ingress_pools_count))
847 goto nla_put_failure;
848 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT,
849 devlink_sb->egress_pools_count))
850 goto nla_put_failure;
851 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT,
852 devlink_sb->ingress_tc_count))
853 goto nla_put_failure;
854 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT,
855 devlink_sb->egress_tc_count))
856 goto nla_put_failure;
857
858 genlmsg_end(msg, hdr);
859 return 0;
860
861nla_put_failure:
862 genlmsg_cancel(msg, hdr);
863 return -EMSGSIZE;
864}
865
866static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb,
867 struct genl_info *info)
868{
869 struct devlink *devlink = info->user_ptr[0];
870 struct devlink_sb *devlink_sb = info->user_ptr[1];
871 struct sk_buff *msg;
872 int err;
873
874 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
875 if (!msg)
876 return -ENOMEM;
877
878 err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
879 DEVLINK_CMD_SB_NEW,
880 info->snd_portid, info->snd_seq, 0);
881 if (err) {
882 nlmsg_free(msg);
883 return err;
884 }
885
886 return genlmsg_reply(msg, info);
887}
888
889static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg,
890 struct netlink_callback *cb)
891{
892 struct devlink *devlink;
893 struct devlink_sb *devlink_sb;
894 int start = cb->args[0];
895 int idx = 0;
896 int err;
897
898 mutex_lock(&devlink_mutex);
899 list_for_each_entry(devlink, &devlink_list, list) {
900 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
901 continue;
902 mutex_lock(&devlink->lock);
903 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
904 if (idx < start) {
905 idx++;
906 continue;
907 }
908 err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
909 DEVLINK_CMD_SB_NEW,
910 NETLINK_CB(cb->skb).portid,
911 cb->nlh->nlmsg_seq,
912 NLM_F_MULTI);
913 if (err) {
914 mutex_unlock(&devlink->lock);
915 goto out;
916 }
917 idx++;
918 }
919 mutex_unlock(&devlink->lock);
920 }
921out:
922 mutex_unlock(&devlink_mutex);
923
924 cb->args[0] = idx;
925 return msg->len;
926}
927
928static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink,
929 struct devlink_sb *devlink_sb,
930 u16 pool_index, enum devlink_command cmd,
931 u32 portid, u32 seq, int flags)
932{
933 struct devlink_sb_pool_info pool_info;
934 void *hdr;
935 int err;
936
937 err = devlink->ops->sb_pool_get(devlink, devlink_sb->index,
938 pool_index, &pool_info);
939 if (err)
940 return err;
941
942 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
943 if (!hdr)
944 return -EMSGSIZE;
945
946 if (devlink_nl_put_handle(msg, devlink))
947 goto nla_put_failure;
948 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
949 goto nla_put_failure;
950 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
951 goto nla_put_failure;
952 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type))
953 goto nla_put_failure;
954 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size))
955 goto nla_put_failure;
956 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE,
957 pool_info.threshold_type))
958 goto nla_put_failure;
959 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_CELL_SIZE,
960 pool_info.cell_size))
961 goto nla_put_failure;
962
963 genlmsg_end(msg, hdr);
964 return 0;
965
966nla_put_failure:
967 genlmsg_cancel(msg, hdr);
968 return -EMSGSIZE;
969}
970
971static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb,
972 struct genl_info *info)
973{
974 struct devlink *devlink = info->user_ptr[0];
975 struct devlink_sb *devlink_sb = info->user_ptr[1];
976 struct sk_buff *msg;
977 u16 pool_index;
978 int err;
979
980 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
981 &pool_index);
982 if (err)
983 return err;
984
985 if (!devlink->ops->sb_pool_get)
986 return -EOPNOTSUPP;
987
988 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
989 if (!msg)
990 return -ENOMEM;
991
992 err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index,
993 DEVLINK_CMD_SB_POOL_NEW,
994 info->snd_portid, info->snd_seq, 0);
995 if (err) {
996 nlmsg_free(msg);
997 return err;
998 }
999
1000 return genlmsg_reply(msg, info);
1001}
1002
1003static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
1004 struct devlink *devlink,
1005 struct devlink_sb *devlink_sb,
1006 u32 portid, u32 seq)
1007{
1008 u16 pool_count = devlink_sb_pool_count(devlink_sb);
1009 u16 pool_index;
1010 int err;
1011
1012 for (pool_index = 0; pool_index < pool_count; pool_index++) {
1013 if (*p_idx < start) {
1014 (*p_idx)++;
1015 continue;
1016 }
1017 err = devlink_nl_sb_pool_fill(msg, devlink,
1018 devlink_sb,
1019 pool_index,
1020 DEVLINK_CMD_SB_POOL_NEW,
1021 portid, seq, NLM_F_MULTI);
1022 if (err)
1023 return err;
1024 (*p_idx)++;
1025 }
1026 return 0;
1027}
1028
1029static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg,
1030 struct netlink_callback *cb)
1031{
1032 struct devlink *devlink;
1033 struct devlink_sb *devlink_sb;
1034 int start = cb->args[0];
1035 int idx = 0;
1036 int err;
1037
1038 mutex_lock(&devlink_mutex);
1039 list_for_each_entry(devlink, &devlink_list, list) {
1040 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1041 !devlink->ops->sb_pool_get)
1042 continue;
1043 mutex_lock(&devlink->lock);
1044 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1045 err = __sb_pool_get_dumpit(msg, start, &idx, devlink,
1046 devlink_sb,
1047 NETLINK_CB(cb->skb).portid,
1048 cb->nlh->nlmsg_seq);
1049 if (err && err != -EOPNOTSUPP) {
1050 mutex_unlock(&devlink->lock);
1051 goto out;
1052 }
1053 }
1054 mutex_unlock(&devlink->lock);
1055 }
1056out:
1057 mutex_unlock(&devlink_mutex);
1058
1059 cb->args[0] = idx;
1060 return msg->len;
1061}
1062
1063static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index,
1064 u16 pool_index, u32 size,
1065 enum devlink_sb_threshold_type threshold_type,
1066 struct netlink_ext_ack *extack)
1067
1068{
1069 const struct devlink_ops *ops = devlink->ops;
1070
1071 if (ops->sb_pool_set)
1072 return ops->sb_pool_set(devlink, sb_index, pool_index,
1073 size, threshold_type, extack);
1074 return -EOPNOTSUPP;
1075}
1076
1077static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb,
1078 struct genl_info *info)
1079{
1080 struct devlink *devlink = info->user_ptr[0];
1081 struct devlink_sb *devlink_sb = info->user_ptr[1];
1082 enum devlink_sb_threshold_type threshold_type;
1083 u16 pool_index;
1084 u32 size;
1085 int err;
1086
1087 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1088 &pool_index);
1089 if (err)
1090 return err;
1091
1092 err = devlink_sb_th_type_get_from_info(info, &threshold_type);
1093 if (err)
1094 return err;
1095
1096 if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE])
1097 return -EINVAL;
1098
1099 size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]);
1100 return devlink_sb_pool_set(devlink, devlink_sb->index,
1101 pool_index, size, threshold_type,
1102 info->extack);
1103}
1104
1105static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
1106 struct devlink *devlink,
1107 struct devlink_port *devlink_port,
1108 struct devlink_sb *devlink_sb,
1109 u16 pool_index,
1110 enum devlink_command cmd,
1111 u32 portid, u32 seq, int flags)
1112{
1113 const struct devlink_ops *ops = devlink->ops;
1114 u32 threshold;
1115 void *hdr;
1116 int err;
1117
1118 err = ops->sb_port_pool_get(devlink_port, devlink_sb->index,
1119 pool_index, &threshold);
1120 if (err)
1121 return err;
1122
1123 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1124 if (!hdr)
1125 return -EMSGSIZE;
1126
1127 if (devlink_nl_put_handle(msg, devlink))
1128 goto nla_put_failure;
1129 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1130 goto nla_put_failure;
1131 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1132 goto nla_put_failure;
1133 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
1134 goto nla_put_failure;
1135 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1136 goto nla_put_failure;
1137
1138 if (ops->sb_occ_port_pool_get) {
1139 u32 cur;
1140 u32 max;
1141
1142 err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index,
1143 pool_index, &cur, &max);
1144 if (err && err != -EOPNOTSUPP)
1145 return err;
1146 if (!err) {
1147 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
1148 goto nla_put_failure;
1149 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
1150 goto nla_put_failure;
1151 }
1152 }
1153
1154 genlmsg_end(msg, hdr);
1155 return 0;
1156
1157nla_put_failure:
1158 genlmsg_cancel(msg, hdr);
1159 return -EMSGSIZE;
1160}
1161
1162static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb,
1163 struct genl_info *info)
1164{
1165 struct devlink_port *devlink_port = info->user_ptr[0];
1166 struct devlink *devlink = devlink_port->devlink;
1167 struct devlink_sb *devlink_sb = info->user_ptr[1];
1168 struct sk_buff *msg;
1169 u16 pool_index;
1170 int err;
1171
1172 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1173 &pool_index);
1174 if (err)
1175 return err;
1176
1177 if (!devlink->ops->sb_port_pool_get)
1178 return -EOPNOTSUPP;
1179
1180 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1181 if (!msg)
1182 return -ENOMEM;
1183
1184 err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port,
1185 devlink_sb, pool_index,
1186 DEVLINK_CMD_SB_PORT_POOL_NEW,
1187 info->snd_portid, info->snd_seq, 0);
1188 if (err) {
1189 nlmsg_free(msg);
1190 return err;
1191 }
1192
1193 return genlmsg_reply(msg, info);
1194}
1195
1196static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
1197 struct devlink *devlink,
1198 struct devlink_sb *devlink_sb,
1199 u32 portid, u32 seq)
1200{
1201 struct devlink_port *devlink_port;
1202 u16 pool_count = devlink_sb_pool_count(devlink_sb);
1203 u16 pool_index;
1204 int err;
1205
1206 list_for_each_entry(devlink_port, &devlink->port_list, list) {
1207 for (pool_index = 0; pool_index < pool_count; pool_index++) {
1208 if (*p_idx < start) {
1209 (*p_idx)++;
1210 continue;
1211 }
1212 err = devlink_nl_sb_port_pool_fill(msg, devlink,
1213 devlink_port,
1214 devlink_sb,
1215 pool_index,
1216 DEVLINK_CMD_SB_PORT_POOL_NEW,
1217 portid, seq,
1218 NLM_F_MULTI);
1219 if (err)
1220 return err;
1221 (*p_idx)++;
1222 }
1223 }
1224 return 0;
1225}
1226
1227static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg,
1228 struct netlink_callback *cb)
1229{
1230 struct devlink *devlink;
1231 struct devlink_sb *devlink_sb;
1232 int start = cb->args[0];
1233 int idx = 0;
1234 int err;
1235
1236 mutex_lock(&devlink_mutex);
1237 list_for_each_entry(devlink, &devlink_list, list) {
1238 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1239 !devlink->ops->sb_port_pool_get)
1240 continue;
1241 mutex_lock(&devlink->lock);
1242 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1243 err = __sb_port_pool_get_dumpit(msg, start, &idx,
1244 devlink, devlink_sb,
1245 NETLINK_CB(cb->skb).portid,
1246 cb->nlh->nlmsg_seq);
1247 if (err && err != -EOPNOTSUPP) {
1248 mutex_unlock(&devlink->lock);
1249 goto out;
1250 }
1251 }
1252 mutex_unlock(&devlink->lock);
1253 }
1254out:
1255 mutex_unlock(&devlink_mutex);
1256
1257 cb->args[0] = idx;
1258 return msg->len;
1259}
1260
1261static int devlink_sb_port_pool_set(struct devlink_port *devlink_port,
1262 unsigned int sb_index, u16 pool_index,
1263 u32 threshold,
1264 struct netlink_ext_ack *extack)
1265
1266{
1267 const struct devlink_ops *ops = devlink_port->devlink->ops;
1268
1269 if (ops->sb_port_pool_set)
1270 return ops->sb_port_pool_set(devlink_port, sb_index,
1271 pool_index, threshold, extack);
1272 return -EOPNOTSUPP;
1273}
1274
1275static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb,
1276 struct genl_info *info)
1277{
1278 struct devlink_port *devlink_port = info->user_ptr[0];
1279 struct devlink_sb *devlink_sb = info->user_ptr[1];
1280 u16 pool_index;
1281 u32 threshold;
1282 int err;
1283
1284 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1285 &pool_index);
1286 if (err)
1287 return err;
1288
1289 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1290 return -EINVAL;
1291
1292 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1293 return devlink_sb_port_pool_set(devlink_port, devlink_sb->index,
1294 pool_index, threshold, info->extack);
1295}
1296
1297static int
1298devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink,
1299 struct devlink_port *devlink_port,
1300 struct devlink_sb *devlink_sb, u16 tc_index,
1301 enum devlink_sb_pool_type pool_type,
1302 enum devlink_command cmd,
1303 u32 portid, u32 seq, int flags)
1304{
1305 const struct devlink_ops *ops = devlink->ops;
1306 u16 pool_index;
1307 u32 threshold;
1308 void *hdr;
1309 int err;
1310
1311 err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index,
1312 tc_index, pool_type,
1313 &pool_index, &threshold);
1314 if (err)
1315 return err;
1316
1317 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1318 if (!hdr)
1319 return -EMSGSIZE;
1320
1321 if (devlink_nl_put_handle(msg, devlink))
1322 goto nla_put_failure;
1323 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1324 goto nla_put_failure;
1325 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1326 goto nla_put_failure;
1327 if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index))
1328 goto nla_put_failure;
1329 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type))
1330 goto nla_put_failure;
1331 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
1332 goto nla_put_failure;
1333 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1334 goto nla_put_failure;
1335
1336 if (ops->sb_occ_tc_port_bind_get) {
1337 u32 cur;
1338 u32 max;
1339
1340 err = ops->sb_occ_tc_port_bind_get(devlink_port,
1341 devlink_sb->index,
1342 tc_index, pool_type,
1343 &cur, &max);
1344 if (err && err != -EOPNOTSUPP)
1345 return err;
1346 if (!err) {
1347 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
1348 goto nla_put_failure;
1349 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
1350 goto nla_put_failure;
1351 }
1352 }
1353
1354 genlmsg_end(msg, hdr);
1355 return 0;
1356
1357nla_put_failure:
1358 genlmsg_cancel(msg, hdr);
1359 return -EMSGSIZE;
1360}
1361
1362static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb,
1363 struct genl_info *info)
1364{
1365 struct devlink_port *devlink_port = info->user_ptr[0];
1366 struct devlink *devlink = devlink_port->devlink;
1367 struct devlink_sb *devlink_sb = info->user_ptr[1];
1368 struct sk_buff *msg;
1369 enum devlink_sb_pool_type pool_type;
1370 u16 tc_index;
1371 int err;
1372
1373 err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1374 if (err)
1375 return err;
1376
1377 err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1378 pool_type, &tc_index);
1379 if (err)
1380 return err;
1381
1382 if (!devlink->ops->sb_tc_pool_bind_get)
1383 return -EOPNOTSUPP;
1384
1385 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1386 if (!msg)
1387 return -ENOMEM;
1388
1389 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port,
1390 devlink_sb, tc_index, pool_type,
1391 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1392 info->snd_portid,
1393 info->snd_seq, 0);
1394 if (err) {
1395 nlmsg_free(msg);
1396 return err;
1397 }
1398
1399 return genlmsg_reply(msg, info);
1400}
1401
1402static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1403 int start, int *p_idx,
1404 struct devlink *devlink,
1405 struct devlink_sb *devlink_sb,
1406 u32 portid, u32 seq)
1407{
1408 struct devlink_port *devlink_port;
1409 u16 tc_index;
1410 int err;
1411
1412 list_for_each_entry(devlink_port, &devlink->port_list, list) {
1413 for (tc_index = 0;
1414 tc_index < devlink_sb->ingress_tc_count; tc_index++) {
1415 if (*p_idx < start) {
1416 (*p_idx)++;
1417 continue;
1418 }
1419 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1420 devlink_port,
1421 devlink_sb,
1422 tc_index,
1423 DEVLINK_SB_POOL_TYPE_INGRESS,
1424 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1425 portid, seq,
1426 NLM_F_MULTI);
1427 if (err)
1428 return err;
1429 (*p_idx)++;
1430 }
1431 for (tc_index = 0;
1432 tc_index < devlink_sb->egress_tc_count; tc_index++) {
1433 if (*p_idx < start) {
1434 (*p_idx)++;
1435 continue;
1436 }
1437 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1438 devlink_port,
1439 devlink_sb,
1440 tc_index,
1441 DEVLINK_SB_POOL_TYPE_EGRESS,
1442 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1443 portid, seq,
1444 NLM_F_MULTI);
1445 if (err)
1446 return err;
1447 (*p_idx)++;
1448 }
1449 }
1450 return 0;
1451}
1452
1453static int
1454devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1455 struct netlink_callback *cb)
1456{
1457 struct devlink *devlink;
1458 struct devlink_sb *devlink_sb;
1459 int start = cb->args[0];
1460 int idx = 0;
1461 int err;
1462
1463 mutex_lock(&devlink_mutex);
1464 list_for_each_entry(devlink, &devlink_list, list) {
1465 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1466 !devlink->ops->sb_tc_pool_bind_get)
1467 continue;
1468
1469 mutex_lock(&devlink->lock);
1470 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1471 err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx,
1472 devlink,
1473 devlink_sb,
1474 NETLINK_CB(cb->skb).portid,
1475 cb->nlh->nlmsg_seq);
1476 if (err && err != -EOPNOTSUPP) {
1477 mutex_unlock(&devlink->lock);
1478 goto out;
1479 }
1480 }
1481 mutex_unlock(&devlink->lock);
1482 }
1483out:
1484 mutex_unlock(&devlink_mutex);
1485
1486 cb->args[0] = idx;
1487 return msg->len;
1488}
1489
1490static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
1491 unsigned int sb_index, u16 tc_index,
1492 enum devlink_sb_pool_type pool_type,
1493 u16 pool_index, u32 threshold,
1494 struct netlink_ext_ack *extack)
1495
1496{
1497 const struct devlink_ops *ops = devlink_port->devlink->ops;
1498
1499 if (ops->sb_tc_pool_bind_set)
1500 return ops->sb_tc_pool_bind_set(devlink_port, sb_index,
1501 tc_index, pool_type,
1502 pool_index, threshold, extack);
1503 return -EOPNOTSUPP;
1504}
1505
1506static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb,
1507 struct genl_info *info)
1508{
1509 struct devlink_port *devlink_port = info->user_ptr[0];
1510 struct devlink_sb *devlink_sb = info->user_ptr[1];
1511 enum devlink_sb_pool_type pool_type;
1512 u16 tc_index;
1513 u16 pool_index;
1514 u32 threshold;
1515 int err;
1516
1517 err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1518 if (err)
1519 return err;
1520
1521 err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1522 pool_type, &tc_index);
1523 if (err)
1524 return err;
1525
1526 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1527 &pool_index);
1528 if (err)
1529 return err;
1530
1531 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1532 return -EINVAL;
1533
1534 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1535 return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index,
1536 tc_index, pool_type,
1537 pool_index, threshold, info->extack);
1538}
1539
1540static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb,
1541 struct genl_info *info)
1542{
1543 struct devlink *devlink = info->user_ptr[0];
1544 struct devlink_sb *devlink_sb = info->user_ptr[1];
1545 const struct devlink_ops *ops = devlink->ops;
1546
1547 if (ops->sb_occ_snapshot)
1548 return ops->sb_occ_snapshot(devlink, devlink_sb->index);
1549 return -EOPNOTSUPP;
1550}
1551
1552static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb,
1553 struct genl_info *info)
1554{
1555 struct devlink *devlink = info->user_ptr[0];
1556 struct devlink_sb *devlink_sb = info->user_ptr[1];
1557 const struct devlink_ops *ops = devlink->ops;
1558
1559 if (ops->sb_occ_max_clear)
1560 return ops->sb_occ_max_clear(devlink, devlink_sb->index);
1561 return -EOPNOTSUPP;
1562}
1563
1564static int devlink_nl_eswitch_fill(struct sk_buff *msg, struct devlink *devlink,
1565 enum devlink_command cmd, u32 portid,
1566 u32 seq, int flags)
1567{
1568 const struct devlink_ops *ops = devlink->ops;
1569 enum devlink_eswitch_encap_mode encap_mode;
1570 u8 inline_mode;
1571 void *hdr;
1572 int err = 0;
1573 u16 mode;
1574
1575 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1576 if (!hdr)
1577 return -EMSGSIZE;
1578
1579 err = devlink_nl_put_handle(msg, devlink);
1580 if (err)
1581 goto nla_put_failure;
1582
1583 if (ops->eswitch_mode_get) {
1584 err = ops->eswitch_mode_get(devlink, &mode);
1585 if (err)
1586 goto nla_put_failure;
1587 err = nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode);
1588 if (err)
1589 goto nla_put_failure;
1590 }
1591
1592 if (ops->eswitch_inline_mode_get) {
1593 err = ops->eswitch_inline_mode_get(devlink, &inline_mode);
1594 if (err)
1595 goto nla_put_failure;
1596 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE,
1597 inline_mode);
1598 if (err)
1599 goto nla_put_failure;
1600 }
1601
1602 if (ops->eswitch_encap_mode_get) {
1603 err = ops->eswitch_encap_mode_get(devlink, &encap_mode);
1604 if (err)
1605 goto nla_put_failure;
1606 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, encap_mode);
1607 if (err)
1608 goto nla_put_failure;
1609 }
1610
1611 genlmsg_end(msg, hdr);
1612 return 0;
1613
1614nla_put_failure:
1615 genlmsg_cancel(msg, hdr);
1616 return err;
1617}
1618
1619static int devlink_nl_cmd_eswitch_get_doit(struct sk_buff *skb,
1620 struct genl_info *info)
1621{
1622 struct devlink *devlink = info->user_ptr[0];
1623 struct sk_buff *msg;
1624 int err;
1625
1626 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1627 if (!msg)
1628 return -ENOMEM;
1629
1630 err = devlink_nl_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_GET,
1631 info->snd_portid, info->snd_seq, 0);
1632
1633 if (err) {
1634 nlmsg_free(msg);
1635 return err;
1636 }
1637
1638 return genlmsg_reply(msg, info);
1639}
1640
1641static int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb,
1642 struct genl_info *info)
1643{
1644 struct devlink *devlink = info->user_ptr[0];
1645 const struct devlink_ops *ops = devlink->ops;
1646 enum devlink_eswitch_encap_mode encap_mode;
1647 u8 inline_mode;
1648 int err = 0;
1649 u16 mode;
1650
1651 if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) {
1652 if (!ops->eswitch_mode_set)
1653 return -EOPNOTSUPP;
1654 mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]);
1655 err = ops->eswitch_mode_set(devlink, mode, info->extack);
1656 if (err)
1657 return err;
1658 }
1659
1660 if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) {
1661 if (!ops->eswitch_inline_mode_set)
1662 return -EOPNOTSUPP;
1663 inline_mode = nla_get_u8(
1664 info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]);
1665 err = ops->eswitch_inline_mode_set(devlink, inline_mode,
1666 info->extack);
1667 if (err)
1668 return err;
1669 }
1670
1671 if (info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]) {
1672 if (!ops->eswitch_encap_mode_set)
1673 return -EOPNOTSUPP;
1674 encap_mode = nla_get_u8(info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]);
1675 err = ops->eswitch_encap_mode_set(devlink, encap_mode,
1676 info->extack);
1677 if (err)
1678 return err;
1679 }
1680
1681 return 0;
1682}
1683
1684int devlink_dpipe_match_put(struct sk_buff *skb,
1685 struct devlink_dpipe_match *match)
1686{
1687 struct devlink_dpipe_header *header = match->header;
1688 struct devlink_dpipe_field *field = &header->fields[match->field_id];
1689 struct nlattr *match_attr;
1690
1691 match_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_MATCH);
1692 if (!match_attr)
1693 return -EMSGSIZE;
1694
1695 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_MATCH_TYPE, match->type) ||
1696 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, match->header_index) ||
1697 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
1698 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
1699 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
1700 goto nla_put_failure;
1701
1702 nla_nest_end(skb, match_attr);
1703 return 0;
1704
1705nla_put_failure:
1706 nla_nest_cancel(skb, match_attr);
1707 return -EMSGSIZE;
1708}
1709EXPORT_SYMBOL_GPL(devlink_dpipe_match_put);
1710
1711static int devlink_dpipe_matches_put(struct devlink_dpipe_table *table,
1712 struct sk_buff *skb)
1713{
1714 struct nlattr *matches_attr;
1715
1716 matches_attr = nla_nest_start_noflag(skb,
1717 DEVLINK_ATTR_DPIPE_TABLE_MATCHES);
1718 if (!matches_attr)
1719 return -EMSGSIZE;
1720
1721 if (table->table_ops->matches_dump(table->priv, skb))
1722 goto nla_put_failure;
1723
1724 nla_nest_end(skb, matches_attr);
1725 return 0;
1726
1727nla_put_failure:
1728 nla_nest_cancel(skb, matches_attr);
1729 return -EMSGSIZE;
1730}
1731
1732int devlink_dpipe_action_put(struct sk_buff *skb,
1733 struct devlink_dpipe_action *action)
1734{
1735 struct devlink_dpipe_header *header = action->header;
1736 struct devlink_dpipe_field *field = &header->fields[action->field_id];
1737 struct nlattr *action_attr;
1738
1739 action_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ACTION);
1740 if (!action_attr)
1741 return -EMSGSIZE;
1742
1743 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_ACTION_TYPE, action->type) ||
1744 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, action->header_index) ||
1745 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
1746 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
1747 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
1748 goto nla_put_failure;
1749
1750 nla_nest_end(skb, action_attr);
1751 return 0;
1752
1753nla_put_failure:
1754 nla_nest_cancel(skb, action_attr);
1755 return -EMSGSIZE;
1756}
1757EXPORT_SYMBOL_GPL(devlink_dpipe_action_put);
1758
1759static int devlink_dpipe_actions_put(struct devlink_dpipe_table *table,
1760 struct sk_buff *skb)
1761{
1762 struct nlattr *actions_attr;
1763
1764 actions_attr = nla_nest_start_noflag(skb,
1765 DEVLINK_ATTR_DPIPE_TABLE_ACTIONS);
1766 if (!actions_attr)
1767 return -EMSGSIZE;
1768
1769 if (table->table_ops->actions_dump(table->priv, skb))
1770 goto nla_put_failure;
1771
1772 nla_nest_end(skb, actions_attr);
1773 return 0;
1774
1775nla_put_failure:
1776 nla_nest_cancel(skb, actions_attr);
1777 return -EMSGSIZE;
1778}
1779
1780static int devlink_dpipe_table_put(struct sk_buff *skb,
1781 struct devlink_dpipe_table *table)
1782{
1783 struct nlattr *table_attr;
1784 u64 table_size;
1785
1786 table_size = table->table_ops->size_get(table->priv);
1787 table_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLE);
1788 if (!table_attr)
1789 return -EMSGSIZE;
1790
1791 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) ||
1792 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table_size,
1793 DEVLINK_ATTR_PAD))
1794 goto nla_put_failure;
1795 if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED,
1796 table->counters_enabled))
1797 goto nla_put_failure;
1798
1799 if (table->resource_valid) {
1800 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID,
1801 table->resource_id, DEVLINK_ATTR_PAD) ||
1802 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS,
1803 table->resource_units, DEVLINK_ATTR_PAD))
1804 goto nla_put_failure;
1805 }
1806 if (devlink_dpipe_matches_put(table, skb))
1807 goto nla_put_failure;
1808
1809 if (devlink_dpipe_actions_put(table, skb))
1810 goto nla_put_failure;
1811
1812 nla_nest_end(skb, table_attr);
1813 return 0;
1814
1815nla_put_failure:
1816 nla_nest_cancel(skb, table_attr);
1817 return -EMSGSIZE;
1818}
1819
1820static int devlink_dpipe_send_and_alloc_skb(struct sk_buff **pskb,
1821 struct genl_info *info)
1822{
1823 int err;
1824
1825 if (*pskb) {
1826 err = genlmsg_reply(*pskb, info);
1827 if (err)
1828 return err;
1829 }
1830 *pskb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
1831 if (!*pskb)
1832 return -ENOMEM;
1833 return 0;
1834}
1835
1836static int devlink_dpipe_tables_fill(struct genl_info *info,
1837 enum devlink_command cmd, int flags,
1838 struct list_head *dpipe_tables,
1839 const char *table_name)
1840{
1841 struct devlink *devlink = info->user_ptr[0];
1842 struct devlink_dpipe_table *table;
1843 struct nlattr *tables_attr;
1844 struct sk_buff *skb = NULL;
1845 struct nlmsghdr *nlh;
1846 bool incomplete;
1847 void *hdr;
1848 int i;
1849 int err;
1850
1851 table = list_first_entry(dpipe_tables,
1852 struct devlink_dpipe_table, list);
1853start_again:
1854 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
1855 if (err)
1856 return err;
1857
1858 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
1859 &devlink_nl_family, NLM_F_MULTI, cmd);
1860 if (!hdr) {
1861 nlmsg_free(skb);
1862 return -EMSGSIZE;
1863 }
1864
1865 if (devlink_nl_put_handle(skb, devlink))
1866 goto nla_put_failure;
1867 tables_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLES);
1868 if (!tables_attr)
1869 goto nla_put_failure;
1870
1871 i = 0;
1872 incomplete = false;
1873 list_for_each_entry_from(table, dpipe_tables, list) {
1874 if (!table_name) {
1875 err = devlink_dpipe_table_put(skb, table);
1876 if (err) {
1877 if (!i)
1878 goto err_table_put;
1879 incomplete = true;
1880 break;
1881 }
1882 } else {
1883 if (!strcmp(table->name, table_name)) {
1884 err = devlink_dpipe_table_put(skb, table);
1885 if (err)
1886 break;
1887 }
1888 }
1889 i++;
1890 }
1891
1892 nla_nest_end(skb, tables_attr);
1893 genlmsg_end(skb, hdr);
1894 if (incomplete)
1895 goto start_again;
1896
1897send_done:
1898 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
1899 NLMSG_DONE, 0, flags | NLM_F_MULTI);
1900 if (!nlh) {
1901 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
1902 if (err)
1903 return err;
1904 goto send_done;
1905 }
1906
1907 return genlmsg_reply(skb, info);
1908
1909nla_put_failure:
1910 err = -EMSGSIZE;
1911err_table_put:
1912 nlmsg_free(skb);
1913 return err;
1914}
1915
1916static int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb,
1917 struct genl_info *info)
1918{
1919 struct devlink *devlink = info->user_ptr[0];
1920 const char *table_name = NULL;
1921
1922 if (info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME])
1923 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
1924
1925 return devlink_dpipe_tables_fill(info, DEVLINK_CMD_DPIPE_TABLE_GET, 0,
1926 &devlink->dpipe_table_list,
1927 table_name);
1928}
1929
1930static int devlink_dpipe_value_put(struct sk_buff *skb,
1931 struct devlink_dpipe_value *value)
1932{
1933 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE,
1934 value->value_size, value->value))
1935 return -EMSGSIZE;
1936 if (value->mask)
1937 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE_MASK,
1938 value->value_size, value->mask))
1939 return -EMSGSIZE;
1940 if (value->mapping_valid)
1941 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_VALUE_MAPPING,
1942 value->mapping_value))
1943 return -EMSGSIZE;
1944 return 0;
1945}
1946
1947static int devlink_dpipe_action_value_put(struct sk_buff *skb,
1948 struct devlink_dpipe_value *value)
1949{
1950 if (!value->action)
1951 return -EINVAL;
1952 if (devlink_dpipe_action_put(skb, value->action))
1953 return -EMSGSIZE;
1954 if (devlink_dpipe_value_put(skb, value))
1955 return -EMSGSIZE;
1956 return 0;
1957}
1958
1959static int devlink_dpipe_action_values_put(struct sk_buff *skb,
1960 struct devlink_dpipe_value *values,
1961 unsigned int values_count)
1962{
1963 struct nlattr *action_attr;
1964 int i;
1965 int err;
1966
1967 for (i = 0; i < values_count; i++) {
1968 action_attr = nla_nest_start_noflag(skb,
1969 DEVLINK_ATTR_DPIPE_ACTION_VALUE);
1970 if (!action_attr)
1971 return -EMSGSIZE;
1972 err = devlink_dpipe_action_value_put(skb, &values[i]);
1973 if (err)
1974 goto err_action_value_put;
1975 nla_nest_end(skb, action_attr);
1976 }
1977 return 0;
1978
1979err_action_value_put:
1980 nla_nest_cancel(skb, action_attr);
1981 return err;
1982}
1983
1984static int devlink_dpipe_match_value_put(struct sk_buff *skb,
1985 struct devlink_dpipe_value *value)
1986{
1987 if (!value->match)
1988 return -EINVAL;
1989 if (devlink_dpipe_match_put(skb, value->match))
1990 return -EMSGSIZE;
1991 if (devlink_dpipe_value_put(skb, value))
1992 return -EMSGSIZE;
1993 return 0;
1994}
1995
1996static int devlink_dpipe_match_values_put(struct sk_buff *skb,
1997 struct devlink_dpipe_value *values,
1998 unsigned int values_count)
1999{
2000 struct nlattr *match_attr;
2001 int i;
2002 int err;
2003
2004 for (i = 0; i < values_count; i++) {
2005 match_attr = nla_nest_start_noflag(skb,
2006 DEVLINK_ATTR_DPIPE_MATCH_VALUE);
2007 if (!match_attr)
2008 return -EMSGSIZE;
2009 err = devlink_dpipe_match_value_put(skb, &values[i]);
2010 if (err)
2011 goto err_match_value_put;
2012 nla_nest_end(skb, match_attr);
2013 }
2014 return 0;
2015
2016err_match_value_put:
2017 nla_nest_cancel(skb, match_attr);
2018 return err;
2019}
2020
2021static int devlink_dpipe_entry_put(struct sk_buff *skb,
2022 struct devlink_dpipe_entry *entry)
2023{
2024 struct nlattr *entry_attr, *matches_attr, *actions_attr;
2025 int err;
2026
2027 entry_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ENTRY);
2028 if (!entry_attr)
2029 return -EMSGSIZE;
2030
2031 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_INDEX, entry->index,
2032 DEVLINK_ATTR_PAD))
2033 goto nla_put_failure;
2034 if (entry->counter_valid)
2035 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_COUNTER,
2036 entry->counter, DEVLINK_ATTR_PAD))
2037 goto nla_put_failure;
2038
2039 matches_attr = nla_nest_start_noflag(skb,
2040 DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES);
2041 if (!matches_attr)
2042 goto nla_put_failure;
2043
2044 err = devlink_dpipe_match_values_put(skb, entry->match_values,
2045 entry->match_values_count);
2046 if (err) {
2047 nla_nest_cancel(skb, matches_attr);
2048 goto err_match_values_put;
2049 }
2050 nla_nest_end(skb, matches_attr);
2051
2052 actions_attr = nla_nest_start_noflag(skb,
2053 DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES);
2054 if (!actions_attr)
2055 goto nla_put_failure;
2056
2057 err = devlink_dpipe_action_values_put(skb, entry->action_values,
2058 entry->action_values_count);
2059 if (err) {
2060 nla_nest_cancel(skb, actions_attr);
2061 goto err_action_values_put;
2062 }
2063 nla_nest_end(skb, actions_attr);
2064
2065 nla_nest_end(skb, entry_attr);
2066 return 0;
2067
2068nla_put_failure:
2069 err = -EMSGSIZE;
2070err_match_values_put:
2071err_action_values_put:
2072 nla_nest_cancel(skb, entry_attr);
2073 return err;
2074}
2075
2076static struct devlink_dpipe_table *
2077devlink_dpipe_table_find(struct list_head *dpipe_tables,
2078 const char *table_name)
2079{
2080 struct devlink_dpipe_table *table;
2081
2082 list_for_each_entry_rcu(table, dpipe_tables, list) {
2083 if (!strcmp(table->name, table_name))
2084 return table;
2085 }
2086 return NULL;
2087}
2088
2089int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx)
2090{
2091 struct devlink *devlink;
2092 int err;
2093
2094 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx->skb,
2095 dump_ctx->info);
2096 if (err)
2097 return err;
2098
2099 dump_ctx->hdr = genlmsg_put(dump_ctx->skb,
2100 dump_ctx->info->snd_portid,
2101 dump_ctx->info->snd_seq,
2102 &devlink_nl_family, NLM_F_MULTI,
2103 dump_ctx->cmd);
2104 if (!dump_ctx->hdr)
2105 goto nla_put_failure;
2106
2107 devlink = dump_ctx->info->user_ptr[0];
2108 if (devlink_nl_put_handle(dump_ctx->skb, devlink))
2109 goto nla_put_failure;
2110 dump_ctx->nest = nla_nest_start_noflag(dump_ctx->skb,
2111 DEVLINK_ATTR_DPIPE_ENTRIES);
2112 if (!dump_ctx->nest)
2113 goto nla_put_failure;
2114 return 0;
2115
2116nla_put_failure:
2117 nlmsg_free(dump_ctx->skb);
2118 return -EMSGSIZE;
2119}
2120EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_prepare);
2121
2122int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx,
2123 struct devlink_dpipe_entry *entry)
2124{
2125 return devlink_dpipe_entry_put(dump_ctx->skb, entry);
2126}
2127EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_append);
2128
2129int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx)
2130{
2131 nla_nest_end(dump_ctx->skb, dump_ctx->nest);
2132 genlmsg_end(dump_ctx->skb, dump_ctx->hdr);
2133 return 0;
2134}
2135EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close);
2136
2137void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry)
2138
2139{
2140 unsigned int value_count, value_index;
2141 struct devlink_dpipe_value *value;
2142
2143 value = entry->action_values;
2144 value_count = entry->action_values_count;
2145 for (value_index = 0; value_index < value_count; value_index++) {
2146 kfree(value[value_index].value);
2147 kfree(value[value_index].mask);
2148 }
2149
2150 value = entry->match_values;
2151 value_count = entry->match_values_count;
2152 for (value_index = 0; value_index < value_count; value_index++) {
2153 kfree(value[value_index].value);
2154 kfree(value[value_index].mask);
2155 }
2156}
2157EXPORT_SYMBOL(devlink_dpipe_entry_clear);
2158
2159static int devlink_dpipe_entries_fill(struct genl_info *info,
2160 enum devlink_command cmd, int flags,
2161 struct devlink_dpipe_table *table)
2162{
2163 struct devlink_dpipe_dump_ctx dump_ctx;
2164 struct nlmsghdr *nlh;
2165 int err;
2166
2167 dump_ctx.skb = NULL;
2168 dump_ctx.cmd = cmd;
2169 dump_ctx.info = info;
2170
2171 err = table->table_ops->entries_dump(table->priv,
2172 table->counters_enabled,
2173 &dump_ctx);
2174 if (err)
2175 return err;
2176
2177send_done:
2178 nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq,
2179 NLMSG_DONE, 0, flags | NLM_F_MULTI);
2180 if (!nlh) {
2181 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info);
2182 if (err)
2183 return err;
2184 goto send_done;
2185 }
2186 return genlmsg_reply(dump_ctx.skb, info);
2187}
2188
2189static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb,
2190 struct genl_info *info)
2191{
2192 struct devlink *devlink = info->user_ptr[0];
2193 struct devlink_dpipe_table *table;
2194 const char *table_name;
2195
2196 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME])
2197 return -EINVAL;
2198
2199 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
2200 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2201 table_name);
2202 if (!table)
2203 return -EINVAL;
2204
2205 if (!table->table_ops->entries_dump)
2206 return -EINVAL;
2207
2208 return devlink_dpipe_entries_fill(info, DEVLINK_CMD_DPIPE_ENTRIES_GET,
2209 0, table);
2210}
2211
2212static int devlink_dpipe_fields_put(struct sk_buff *skb,
2213 const struct devlink_dpipe_header *header)
2214{
2215 struct devlink_dpipe_field *field;
2216 struct nlattr *field_attr;
2217 int i;
2218
2219 for (i = 0; i < header->fields_count; i++) {
2220 field = &header->fields[i];
2221 field_attr = nla_nest_start_noflag(skb,
2222 DEVLINK_ATTR_DPIPE_FIELD);
2223 if (!field_attr)
2224 return -EMSGSIZE;
2225 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_FIELD_NAME, field->name) ||
2226 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) ||
2227 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, field->bitwidth) ||
2228 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, field->mapping_type))
2229 goto nla_put_failure;
2230 nla_nest_end(skb, field_attr);
2231 }
2232 return 0;
2233
2234nla_put_failure:
2235 nla_nest_cancel(skb, field_attr);
2236 return -EMSGSIZE;
2237}
2238
2239static int devlink_dpipe_header_put(struct sk_buff *skb,
2240 struct devlink_dpipe_header *header)
2241{
2242 struct nlattr *fields_attr, *header_attr;
2243 int err;
2244
2245 header_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADER);
2246 if (!header_attr)
2247 return -EMSGSIZE;
2248
2249 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_HEADER_NAME, header->name) ||
2250 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) ||
2251 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global))
2252 goto nla_put_failure;
2253
2254 fields_attr = nla_nest_start_noflag(skb,
2255 DEVLINK_ATTR_DPIPE_HEADER_FIELDS);
2256 if (!fields_attr)
2257 goto nla_put_failure;
2258
2259 err = devlink_dpipe_fields_put(skb, header);
2260 if (err) {
2261 nla_nest_cancel(skb, fields_attr);
2262 goto nla_put_failure;
2263 }
2264 nla_nest_end(skb, fields_attr);
2265 nla_nest_end(skb, header_attr);
2266 return 0;
2267
2268nla_put_failure:
2269 err = -EMSGSIZE;
2270 nla_nest_cancel(skb, header_attr);
2271 return err;
2272}
2273
2274static int devlink_dpipe_headers_fill(struct genl_info *info,
2275 enum devlink_command cmd, int flags,
2276 struct devlink_dpipe_headers *
2277 dpipe_headers)
2278{
2279 struct devlink *devlink = info->user_ptr[0];
2280 struct nlattr *headers_attr;
2281 struct sk_buff *skb = NULL;
2282 struct nlmsghdr *nlh;
2283 void *hdr;
2284 int i, j;
2285 int err;
2286
2287 i = 0;
2288start_again:
2289 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2290 if (err)
2291 return err;
2292
2293 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
2294 &devlink_nl_family, NLM_F_MULTI, cmd);
2295 if (!hdr) {
2296 nlmsg_free(skb);
2297 return -EMSGSIZE;
2298 }
2299
2300 if (devlink_nl_put_handle(skb, devlink))
2301 goto nla_put_failure;
2302 headers_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADERS);
2303 if (!headers_attr)
2304 goto nla_put_failure;
2305
2306 j = 0;
2307 for (; i < dpipe_headers->headers_count; i++) {
2308 err = devlink_dpipe_header_put(skb, dpipe_headers->headers[i]);
2309 if (err) {
2310 if (!j)
2311 goto err_table_put;
2312 break;
2313 }
2314 j++;
2315 }
2316 nla_nest_end(skb, headers_attr);
2317 genlmsg_end(skb, hdr);
2318 if (i != dpipe_headers->headers_count)
2319 goto start_again;
2320
2321send_done:
2322 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
2323 NLMSG_DONE, 0, flags | NLM_F_MULTI);
2324 if (!nlh) {
2325 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2326 if (err)
2327 return err;
2328 goto send_done;
2329 }
2330 return genlmsg_reply(skb, info);
2331
2332nla_put_failure:
2333 err = -EMSGSIZE;
2334err_table_put:
2335 nlmsg_free(skb);
2336 return err;
2337}
2338
2339static int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb,
2340 struct genl_info *info)
2341{
2342 struct devlink *devlink = info->user_ptr[0];
2343
2344 if (!devlink->dpipe_headers)
2345 return -EOPNOTSUPP;
2346 return devlink_dpipe_headers_fill(info, DEVLINK_CMD_DPIPE_HEADERS_GET,
2347 0, devlink->dpipe_headers);
2348}
2349
2350static int devlink_dpipe_table_counters_set(struct devlink *devlink,
2351 const char *table_name,
2352 bool enable)
2353{
2354 struct devlink_dpipe_table *table;
2355
2356 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
2357 table_name);
2358 if (!table)
2359 return -EINVAL;
2360
2361 if (table->counter_control_extern)
2362 return -EOPNOTSUPP;
2363
2364 if (!(table->counters_enabled ^ enable))
2365 return 0;
2366
2367 table->counters_enabled = enable;
2368 if (table->table_ops->counters_set_update)
2369 table->table_ops->counters_set_update(table->priv, enable);
2370 return 0;
2371}
2372
2373static int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb,
2374 struct genl_info *info)
2375{
2376 struct devlink *devlink = info->user_ptr[0];
2377 const char *table_name;
2378 bool counters_enable;
2379
2380 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME] ||
2381 !info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED])
2382 return -EINVAL;
2383
2384 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]);
2385 counters_enable = !!nla_get_u8(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]);
2386
2387 return devlink_dpipe_table_counters_set(devlink, table_name,
2388 counters_enable);
2389}
2390
2391static struct devlink_resource *
2392devlink_resource_find(struct devlink *devlink,
2393 struct devlink_resource *resource, u64 resource_id)
2394{
2395 struct list_head *resource_list;
2396
2397 if (resource)
2398 resource_list = &resource->resource_list;
2399 else
2400 resource_list = &devlink->resource_list;
2401
2402 list_for_each_entry(resource, resource_list, list) {
2403 struct devlink_resource *child_resource;
2404
2405 if (resource->id == resource_id)
2406 return resource;
2407
2408 child_resource = devlink_resource_find(devlink, resource,
2409 resource_id);
2410 if (child_resource)
2411 return child_resource;
2412 }
2413 return NULL;
2414}
2415
2416static void
2417devlink_resource_validate_children(struct devlink_resource *resource)
2418{
2419 struct devlink_resource *child_resource;
2420 bool size_valid = true;
2421 u64 parts_size = 0;
2422
2423 if (list_empty(&resource->resource_list))
2424 goto out;
2425
2426 list_for_each_entry(child_resource, &resource->resource_list, list)
2427 parts_size += child_resource->size_new;
2428
2429 if (parts_size > resource->size_new)
2430 size_valid = false;
2431out:
2432 resource->size_valid = size_valid;
2433}
2434
2435static int
2436devlink_resource_validate_size(struct devlink_resource *resource, u64 size,
2437 struct netlink_ext_ack *extack)
2438{
2439 u64 reminder;
2440 int err = 0;
2441
2442 if (size > resource->size_params.size_max) {
2443 NL_SET_ERR_MSG_MOD(extack, "Size larger than maximum");
2444 err = -EINVAL;
2445 }
2446
2447 if (size < resource->size_params.size_min) {
2448 NL_SET_ERR_MSG_MOD(extack, "Size smaller than minimum");
2449 err = -EINVAL;
2450 }
2451
2452 div64_u64_rem(size, resource->size_params.size_granularity, &reminder);
2453 if (reminder) {
2454 NL_SET_ERR_MSG_MOD(extack, "Wrong granularity");
2455 err = -EINVAL;
2456 }
2457
2458 return err;
2459}
2460
2461static int devlink_nl_cmd_resource_set(struct sk_buff *skb,
2462 struct genl_info *info)
2463{
2464 struct devlink *devlink = info->user_ptr[0];
2465 struct devlink_resource *resource;
2466 u64 resource_id;
2467 u64 size;
2468 int err;
2469
2470 if (!info->attrs[DEVLINK_ATTR_RESOURCE_ID] ||
2471 !info->attrs[DEVLINK_ATTR_RESOURCE_SIZE])
2472 return -EINVAL;
2473 resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]);
2474
2475 resource = devlink_resource_find(devlink, NULL, resource_id);
2476 if (!resource)
2477 return -EINVAL;
2478
2479 size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]);
2480 err = devlink_resource_validate_size(resource, size, info->extack);
2481 if (err)
2482 return err;
2483
2484 resource->size_new = size;
2485 devlink_resource_validate_children(resource);
2486 if (resource->parent)
2487 devlink_resource_validate_children(resource->parent);
2488 return 0;
2489}
2490
2491static int
2492devlink_resource_size_params_put(struct devlink_resource *resource,
2493 struct sk_buff *skb)
2494{
2495 struct devlink_resource_size_params *size_params;
2496
2497 size_params = &resource->size_params;
2498 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN,
2499 size_params->size_granularity, DEVLINK_ATTR_PAD) ||
2500 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX,
2501 size_params->size_max, DEVLINK_ATTR_PAD) ||
2502 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN,
2503 size_params->size_min, DEVLINK_ATTR_PAD) ||
2504 nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit))
2505 return -EMSGSIZE;
2506 return 0;
2507}
2508
2509static int devlink_resource_occ_put(struct devlink_resource *resource,
2510 struct sk_buff *skb)
2511{
2512 if (!resource->occ_get)
2513 return 0;
2514 return nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC,
2515 resource->occ_get(resource->occ_get_priv),
2516 DEVLINK_ATTR_PAD);
2517}
2518
2519static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb,
2520 struct devlink_resource *resource)
2521{
2522 struct devlink_resource *child_resource;
2523 struct nlattr *child_resource_attr;
2524 struct nlattr *resource_attr;
2525
2526 resource_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_RESOURCE);
2527 if (!resource_attr)
2528 return -EMSGSIZE;
2529
2530 if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) ||
2531 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size,
2532 DEVLINK_ATTR_PAD) ||
2533 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id,
2534 DEVLINK_ATTR_PAD))
2535 goto nla_put_failure;
2536 if (resource->size != resource->size_new)
2537 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW,
2538 resource->size_new, DEVLINK_ATTR_PAD);
2539 if (devlink_resource_occ_put(resource, skb))
2540 goto nla_put_failure;
2541 if (devlink_resource_size_params_put(resource, skb))
2542 goto nla_put_failure;
2543 if (list_empty(&resource->resource_list))
2544 goto out;
2545
2546 if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID,
2547 resource->size_valid))
2548 goto nla_put_failure;
2549
2550 child_resource_attr = nla_nest_start_noflag(skb,
2551 DEVLINK_ATTR_RESOURCE_LIST);
2552 if (!child_resource_attr)
2553 goto nla_put_failure;
2554
2555 list_for_each_entry(child_resource, &resource->resource_list, list) {
2556 if (devlink_resource_put(devlink, skb, child_resource))
2557 goto resource_put_failure;
2558 }
2559
2560 nla_nest_end(skb, child_resource_attr);
2561out:
2562 nla_nest_end(skb, resource_attr);
2563 return 0;
2564
2565resource_put_failure:
2566 nla_nest_cancel(skb, child_resource_attr);
2567nla_put_failure:
2568 nla_nest_cancel(skb, resource_attr);
2569 return -EMSGSIZE;
2570}
2571
2572static int devlink_resource_fill(struct genl_info *info,
2573 enum devlink_command cmd, int flags)
2574{
2575 struct devlink *devlink = info->user_ptr[0];
2576 struct devlink_resource *resource;
2577 struct nlattr *resources_attr;
2578 struct sk_buff *skb = NULL;
2579 struct nlmsghdr *nlh;
2580 bool incomplete;
2581 void *hdr;
2582 int i;
2583 int err;
2584
2585 resource = list_first_entry(&devlink->resource_list,
2586 struct devlink_resource, list);
2587start_again:
2588 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2589 if (err)
2590 return err;
2591
2592 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
2593 &devlink_nl_family, NLM_F_MULTI, cmd);
2594 if (!hdr) {
2595 nlmsg_free(skb);
2596 return -EMSGSIZE;
2597 }
2598
2599 if (devlink_nl_put_handle(skb, devlink))
2600 goto nla_put_failure;
2601
2602 resources_attr = nla_nest_start_noflag(skb,
2603 DEVLINK_ATTR_RESOURCE_LIST);
2604 if (!resources_attr)
2605 goto nla_put_failure;
2606
2607 incomplete = false;
2608 i = 0;
2609 list_for_each_entry_from(resource, &devlink->resource_list, list) {
2610 err = devlink_resource_put(devlink, skb, resource);
2611 if (err) {
2612 if (!i)
2613 goto err_resource_put;
2614 incomplete = true;
2615 break;
2616 }
2617 i++;
2618 }
2619 nla_nest_end(skb, resources_attr);
2620 genlmsg_end(skb, hdr);
2621 if (incomplete)
2622 goto start_again;
2623send_done:
2624 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
2625 NLMSG_DONE, 0, flags | NLM_F_MULTI);
2626 if (!nlh) {
2627 err = devlink_dpipe_send_and_alloc_skb(&skb, info);
2628 if (err)
2629 return err;
2630 goto send_done;
2631 }
2632 return genlmsg_reply(skb, info);
2633
2634nla_put_failure:
2635 err = -EMSGSIZE;
2636err_resource_put:
2637 nlmsg_free(skb);
2638 return err;
2639}
2640
2641static int devlink_nl_cmd_resource_dump(struct sk_buff *skb,
2642 struct genl_info *info)
2643{
2644 struct devlink *devlink = info->user_ptr[0];
2645
2646 if (list_empty(&devlink->resource_list))
2647 return -EOPNOTSUPP;
2648
2649 return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0);
2650}
2651
2652static int
2653devlink_resources_validate(struct devlink *devlink,
2654 struct devlink_resource *resource,
2655 struct genl_info *info)
2656{
2657 struct list_head *resource_list;
2658 int err = 0;
2659
2660 if (resource)
2661 resource_list = &resource->resource_list;
2662 else
2663 resource_list = &devlink->resource_list;
2664
2665 list_for_each_entry(resource, resource_list, list) {
2666 if (!resource->size_valid)
2667 return -EINVAL;
2668 err = devlink_resources_validate(devlink, resource, info);
2669 if (err)
2670 return err;
2671 }
2672 return err;
2673}
2674
2675static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info)
2676{
2677 struct devlink *devlink = info->user_ptr[0];
2678 int err;
2679
2680 if (!devlink->ops->reload)
2681 return -EOPNOTSUPP;
2682
2683 err = devlink_resources_validate(devlink, NULL, info);
2684 if (err) {
2685 NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed");
2686 return err;
2687 }
2688 return devlink->ops->reload(devlink, info->extack);
2689}
2690
2691static int devlink_nl_flash_update_fill(struct sk_buff *msg,
2692 struct devlink *devlink,
2693 enum devlink_command cmd,
2694 const char *status_msg,
2695 const char *component,
2696 unsigned long done, unsigned long total)
2697{
2698 void *hdr;
2699
2700 hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd);
2701 if (!hdr)
2702 return -EMSGSIZE;
2703
2704 if (devlink_nl_put_handle(msg, devlink))
2705 goto nla_put_failure;
2706
2707 if (cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS)
2708 goto out;
2709
2710 if (status_msg &&
2711 nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_MSG,
2712 status_msg))
2713 goto nla_put_failure;
2714 if (component &&
2715 nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_COMPONENT,
2716 component))
2717 goto nla_put_failure;
2718 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_DONE,
2719 done, DEVLINK_ATTR_PAD))
2720 goto nla_put_failure;
2721 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TOTAL,
2722 total, DEVLINK_ATTR_PAD))
2723 goto nla_put_failure;
2724
2725out:
2726 genlmsg_end(msg, hdr);
2727 return 0;
2728
2729nla_put_failure:
2730 genlmsg_cancel(msg, hdr);
2731 return -EMSGSIZE;
2732}
2733
2734static void __devlink_flash_update_notify(struct devlink *devlink,
2735 enum devlink_command cmd,
2736 const char *status_msg,
2737 const char *component,
2738 unsigned long done,
2739 unsigned long total)
2740{
2741 struct sk_buff *msg;
2742 int err;
2743
2744 WARN_ON(cmd != DEVLINK_CMD_FLASH_UPDATE &&
2745 cmd != DEVLINK_CMD_FLASH_UPDATE_END &&
2746 cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS);
2747
2748 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
2749 if (!msg)
2750 return;
2751
2752 err = devlink_nl_flash_update_fill(msg, devlink, cmd, status_msg,
2753 component, done, total);
2754 if (err)
2755 goto out_free_msg;
2756
2757 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
2758 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
2759 return;
2760
2761out_free_msg:
2762 nlmsg_free(msg);
2763}
2764
2765void devlink_flash_update_begin_notify(struct devlink *devlink)
2766{
2767 __devlink_flash_update_notify(devlink,
2768 DEVLINK_CMD_FLASH_UPDATE,
2769 NULL, NULL, 0, 0);
2770}
2771EXPORT_SYMBOL_GPL(devlink_flash_update_begin_notify);
2772
2773void devlink_flash_update_end_notify(struct devlink *devlink)
2774{
2775 __devlink_flash_update_notify(devlink,
2776 DEVLINK_CMD_FLASH_UPDATE_END,
2777 NULL, NULL, 0, 0);
2778}
2779EXPORT_SYMBOL_GPL(devlink_flash_update_end_notify);
2780
2781void devlink_flash_update_status_notify(struct devlink *devlink,
2782 const char *status_msg,
2783 const char *component,
2784 unsigned long done,
2785 unsigned long total)
2786{
2787 __devlink_flash_update_notify(devlink,
2788 DEVLINK_CMD_FLASH_UPDATE_STATUS,
2789 status_msg, component, done, total);
2790}
2791EXPORT_SYMBOL_GPL(devlink_flash_update_status_notify);
2792
2793static int devlink_nl_cmd_flash_update(struct sk_buff *skb,
2794 struct genl_info *info)
2795{
2796 struct devlink *devlink = info->user_ptr[0];
2797 const char *file_name, *component;
2798 struct nlattr *nla_component;
2799
2800 if (!devlink->ops->flash_update)
2801 return -EOPNOTSUPP;
2802
2803 if (!info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME])
2804 return -EINVAL;
2805 file_name = nla_data(info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME]);
2806
2807 nla_component = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT];
2808 component = nla_component ? nla_data(nla_component) : NULL;
2809
2810 return devlink->ops->flash_update(devlink, file_name, component,
2811 info->extack);
2812}
2813
2814static const struct devlink_param devlink_param_generic[] = {
2815 {
2816 .id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET,
2817 .name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME,
2818 .type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE,
2819 },
2820 {
2821 .id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS,
2822 .name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME,
2823 .type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE,
2824 },
2825 {
2826 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV,
2827 .name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME,
2828 .type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE,
2829 },
2830 {
2831 .id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT,
2832 .name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME,
2833 .type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE,
2834 },
2835 {
2836 .id = DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI,
2837 .name = DEVLINK_PARAM_GENERIC_IGNORE_ARI_NAME,
2838 .type = DEVLINK_PARAM_GENERIC_IGNORE_ARI_TYPE,
2839 },
2840 {
2841 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX,
2842 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_NAME,
2843 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_TYPE,
2844 },
2845 {
2846 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN,
2847 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_NAME,
2848 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_TYPE,
2849 },
2850 {
2851 .id = DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY,
2852 .name = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME,
2853 .type = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE,
2854 },
2855};
2856
2857static int devlink_param_generic_verify(const struct devlink_param *param)
2858{
2859 /* verify it match generic parameter by id and name */
2860 if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX)
2861 return -EINVAL;
2862 if (strcmp(param->name, devlink_param_generic[param->id].name))
2863 return -ENOENT;
2864
2865 WARN_ON(param->type != devlink_param_generic[param->id].type);
2866
2867 return 0;
2868}
2869
2870static int devlink_param_driver_verify(const struct devlink_param *param)
2871{
2872 int i;
2873
2874 if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX)
2875 return -EINVAL;
2876 /* verify no such name in generic params */
2877 for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++)
2878 if (!strcmp(param->name, devlink_param_generic[i].name))
2879 return -EEXIST;
2880
2881 return 0;
2882}
2883
2884static struct devlink_param_item *
2885devlink_param_find_by_name(struct list_head *param_list,
2886 const char *param_name)
2887{
2888 struct devlink_param_item *param_item;
2889
2890 list_for_each_entry(param_item, param_list, list)
2891 if (!strcmp(param_item->param->name, param_name))
2892 return param_item;
2893 return NULL;
2894}
2895
2896static struct devlink_param_item *
2897devlink_param_find_by_id(struct list_head *param_list, u32 param_id)
2898{
2899 struct devlink_param_item *param_item;
2900
2901 list_for_each_entry(param_item, param_list, list)
2902 if (param_item->param->id == param_id)
2903 return param_item;
2904 return NULL;
2905}
2906
2907static bool
2908devlink_param_cmode_is_supported(const struct devlink_param *param,
2909 enum devlink_param_cmode cmode)
2910{
2911 return test_bit(cmode, ¶m->supported_cmodes);
2912}
2913
2914static int devlink_param_get(struct devlink *devlink,
2915 const struct devlink_param *param,
2916 struct devlink_param_gset_ctx *ctx)
2917{
2918 if (!param->get)
2919 return -EOPNOTSUPP;
2920 return param->get(devlink, param->id, ctx);
2921}
2922
2923static int devlink_param_set(struct devlink *devlink,
2924 const struct devlink_param *param,
2925 struct devlink_param_gset_ctx *ctx)
2926{
2927 if (!param->set)
2928 return -EOPNOTSUPP;
2929 return param->set(devlink, param->id, ctx);
2930}
2931
2932static int
2933devlink_param_type_to_nla_type(enum devlink_param_type param_type)
2934{
2935 switch (param_type) {
2936 case DEVLINK_PARAM_TYPE_U8:
2937 return NLA_U8;
2938 case DEVLINK_PARAM_TYPE_U16:
2939 return NLA_U16;
2940 case DEVLINK_PARAM_TYPE_U32:
2941 return NLA_U32;
2942 case DEVLINK_PARAM_TYPE_STRING:
2943 return NLA_STRING;
2944 case DEVLINK_PARAM_TYPE_BOOL:
2945 return NLA_FLAG;
2946 default:
2947 return -EINVAL;
2948 }
2949}
2950
2951static int
2952devlink_nl_param_value_fill_one(struct sk_buff *msg,
2953 enum devlink_param_type type,
2954 enum devlink_param_cmode cmode,
2955 union devlink_param_value val)
2956{
2957 struct nlattr *param_value_attr;
2958
2959 param_value_attr = nla_nest_start_noflag(msg,
2960 DEVLINK_ATTR_PARAM_VALUE);
2961 if (!param_value_attr)
2962 goto nla_put_failure;
2963
2964 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode))
2965 goto value_nest_cancel;
2966
2967 switch (type) {
2968 case DEVLINK_PARAM_TYPE_U8:
2969 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8))
2970 goto value_nest_cancel;
2971 break;
2972 case DEVLINK_PARAM_TYPE_U16:
2973 if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16))
2974 goto value_nest_cancel;
2975 break;
2976 case DEVLINK_PARAM_TYPE_U32:
2977 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32))
2978 goto value_nest_cancel;
2979 break;
2980 case DEVLINK_PARAM_TYPE_STRING:
2981 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA,
2982 val.vstr))
2983 goto value_nest_cancel;
2984 break;
2985 case DEVLINK_PARAM_TYPE_BOOL:
2986 if (val.vbool &&
2987 nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA))
2988 goto value_nest_cancel;
2989 break;
2990 }
2991
2992 nla_nest_end(msg, param_value_attr);
2993 return 0;
2994
2995value_nest_cancel:
2996 nla_nest_cancel(msg, param_value_attr);
2997nla_put_failure:
2998 return -EMSGSIZE;
2999}
3000
3001static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink,
3002 unsigned int port_index,
3003 struct devlink_param_item *param_item,
3004 enum devlink_command cmd,
3005 u32 portid, u32 seq, int flags)
3006{
3007 union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1];
3008 bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {};
3009 const struct devlink_param *param = param_item->param;
3010 struct devlink_param_gset_ctx ctx;
3011 struct nlattr *param_values_list;
3012 struct nlattr *param_attr;
3013 int nla_type;
3014 void *hdr;
3015 int err;
3016 int i;
3017
3018 /* Get value from driver part to driverinit configuration mode */
3019 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
3020 if (!devlink_param_cmode_is_supported(param, i))
3021 continue;
3022 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) {
3023 if (!param_item->driverinit_value_valid)
3024 return -EOPNOTSUPP;
3025 param_value[i] = param_item->driverinit_value;
3026 } else {
3027 if (!param_item->published)
3028 continue;
3029 ctx.cmode = i;
3030 err = devlink_param_get(devlink, param, &ctx);
3031 if (err)
3032 return err;
3033 param_value[i] = ctx.val;
3034 }
3035 param_value_set[i] = true;
3036 }
3037
3038 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
3039 if (!hdr)
3040 return -EMSGSIZE;
3041
3042 if (devlink_nl_put_handle(msg, devlink))
3043 goto genlmsg_cancel;
3044
3045 if (cmd == DEVLINK_CMD_PORT_PARAM_GET ||
3046 cmd == DEVLINK_CMD_PORT_PARAM_NEW ||
3047 cmd == DEVLINK_CMD_PORT_PARAM_DEL)
3048 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index))
3049 goto genlmsg_cancel;
3050
3051 param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM);
3052 if (!param_attr)
3053 goto genlmsg_cancel;
3054 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name))
3055 goto param_nest_cancel;
3056 if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC))
3057 goto param_nest_cancel;
3058
3059 nla_type = devlink_param_type_to_nla_type(param->type);
3060 if (nla_type < 0)
3061 goto param_nest_cancel;
3062 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type))
3063 goto param_nest_cancel;
3064
3065 param_values_list = nla_nest_start_noflag(msg,
3066 DEVLINK_ATTR_PARAM_VALUES_LIST);
3067 if (!param_values_list)
3068 goto param_nest_cancel;
3069
3070 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) {
3071 if (!param_value_set[i])
3072 continue;
3073 err = devlink_nl_param_value_fill_one(msg, param->type,
3074 i, param_value[i]);
3075 if (err)
3076 goto values_list_nest_cancel;
3077 }
3078
3079 nla_nest_end(msg, param_values_list);
3080 nla_nest_end(msg, param_attr);
3081 genlmsg_end(msg, hdr);
3082 return 0;
3083
3084values_list_nest_cancel:
3085 nla_nest_end(msg, param_values_list);
3086param_nest_cancel:
3087 nla_nest_cancel(msg, param_attr);
3088genlmsg_cancel:
3089 genlmsg_cancel(msg, hdr);
3090 return -EMSGSIZE;
3091}
3092
3093static void devlink_param_notify(struct devlink *devlink,
3094 unsigned int port_index,
3095 struct devlink_param_item *param_item,
3096 enum devlink_command cmd)
3097{
3098 struct sk_buff *msg;
3099 int err;
3100
3101 WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL &&
3102 cmd != DEVLINK_CMD_PORT_PARAM_NEW &&
3103 cmd != DEVLINK_CMD_PORT_PARAM_DEL);
3104
3105 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3106 if (!msg)
3107 return;
3108 err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd,
3109 0, 0, 0);
3110 if (err) {
3111 nlmsg_free(msg);
3112 return;
3113 }
3114
3115 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
3116 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
3117}
3118
3119static int devlink_nl_cmd_param_get_dumpit(struct sk_buff *msg,
3120 struct netlink_callback *cb)
3121{
3122 struct devlink_param_item *param_item;
3123 struct devlink *devlink;
3124 int start = cb->args[0];
3125 int idx = 0;
3126 int err;
3127
3128 mutex_lock(&devlink_mutex);
3129 list_for_each_entry(devlink, &devlink_list, list) {
3130 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3131 continue;
3132 mutex_lock(&devlink->lock);
3133 list_for_each_entry(param_item, &devlink->param_list, list) {
3134 if (idx < start) {
3135 idx++;
3136 continue;
3137 }
3138 err = devlink_nl_param_fill(msg, devlink, 0, param_item,
3139 DEVLINK_CMD_PARAM_GET,
3140 NETLINK_CB(cb->skb).portid,
3141 cb->nlh->nlmsg_seq,
3142 NLM_F_MULTI);
3143 if (err) {
3144 mutex_unlock(&devlink->lock);
3145 goto out;
3146 }
3147 idx++;
3148 }
3149 mutex_unlock(&devlink->lock);
3150 }
3151out:
3152 mutex_unlock(&devlink_mutex);
3153
3154 cb->args[0] = idx;
3155 return msg->len;
3156}
3157
3158static int
3159devlink_param_type_get_from_info(struct genl_info *info,
3160 enum devlink_param_type *param_type)
3161{
3162 if (!info->attrs[DEVLINK_ATTR_PARAM_TYPE])
3163 return -EINVAL;
3164
3165 switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) {
3166 case NLA_U8:
3167 *param_type = DEVLINK_PARAM_TYPE_U8;
3168 break;
3169 case NLA_U16:
3170 *param_type = DEVLINK_PARAM_TYPE_U16;
3171 break;
3172 case NLA_U32:
3173 *param_type = DEVLINK_PARAM_TYPE_U32;
3174 break;
3175 case NLA_STRING:
3176 *param_type = DEVLINK_PARAM_TYPE_STRING;
3177 break;
3178 case NLA_FLAG:
3179 *param_type = DEVLINK_PARAM_TYPE_BOOL;
3180 break;
3181 default:
3182 return -EINVAL;
3183 }
3184
3185 return 0;
3186}
3187
3188static int
3189devlink_param_value_get_from_info(const struct devlink_param *param,
3190 struct genl_info *info,
3191 union devlink_param_value *value)
3192{
3193 int len;
3194
3195 if (param->type != DEVLINK_PARAM_TYPE_BOOL &&
3196 !info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])
3197 return -EINVAL;
3198
3199 switch (param->type) {
3200 case DEVLINK_PARAM_TYPE_U8:
3201 value->vu8 = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
3202 break;
3203 case DEVLINK_PARAM_TYPE_U16:
3204 value->vu16 = nla_get_u16(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
3205 break;
3206 case DEVLINK_PARAM_TYPE_U32:
3207 value->vu32 = nla_get_u32(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]);
3208 break;
3209 case DEVLINK_PARAM_TYPE_STRING:
3210 len = strnlen(nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]),
3211 nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]));
3212 if (len == nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) ||
3213 len >= __DEVLINK_PARAM_MAX_STRING_VALUE)
3214 return -EINVAL;
3215 strcpy(value->vstr,
3216 nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]));
3217 break;
3218 case DEVLINK_PARAM_TYPE_BOOL:
3219 value->vbool = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA] ?
3220 true : false;
3221 break;
3222 }
3223 return 0;
3224}
3225
3226static struct devlink_param_item *
3227devlink_param_get_from_info(struct list_head *param_list,
3228 struct genl_info *info)
3229{
3230 char *param_name;
3231
3232 if (!info->attrs[DEVLINK_ATTR_PARAM_NAME])
3233 return NULL;
3234
3235 param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]);
3236 return devlink_param_find_by_name(param_list, param_name);
3237}
3238
3239static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb,
3240 struct genl_info *info)
3241{
3242 struct devlink *devlink = info->user_ptr[0];
3243 struct devlink_param_item *param_item;
3244 struct sk_buff *msg;
3245 int err;
3246
3247 param_item = devlink_param_get_from_info(&devlink->param_list, info);
3248 if (!param_item)
3249 return -EINVAL;
3250
3251 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3252 if (!msg)
3253 return -ENOMEM;
3254
3255 err = devlink_nl_param_fill(msg, devlink, 0, param_item,
3256 DEVLINK_CMD_PARAM_GET,
3257 info->snd_portid, info->snd_seq, 0);
3258 if (err) {
3259 nlmsg_free(msg);
3260 return err;
3261 }
3262
3263 return genlmsg_reply(msg, info);
3264}
3265
3266static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink,
3267 unsigned int port_index,
3268 struct list_head *param_list,
3269 struct genl_info *info,
3270 enum devlink_command cmd)
3271{
3272 enum devlink_param_type param_type;
3273 struct devlink_param_gset_ctx ctx;
3274 enum devlink_param_cmode cmode;
3275 struct devlink_param_item *param_item;
3276 const struct devlink_param *param;
3277 union devlink_param_value value;
3278 int err = 0;
3279
3280 param_item = devlink_param_get_from_info(param_list, info);
3281 if (!param_item)
3282 return -EINVAL;
3283 param = param_item->param;
3284 err = devlink_param_type_get_from_info(info, ¶m_type);
3285 if (err)
3286 return err;
3287 if (param_type != param->type)
3288 return -EINVAL;
3289 err = devlink_param_value_get_from_info(param, info, &value);
3290 if (err)
3291 return err;
3292 if (param->validate) {
3293 err = param->validate(devlink, param->id, value, info->extack);
3294 if (err)
3295 return err;
3296 }
3297
3298 if (!info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE])
3299 return -EINVAL;
3300 cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]);
3301 if (!devlink_param_cmode_is_supported(param, cmode))
3302 return -EOPNOTSUPP;
3303
3304 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) {
3305 if (param->type == DEVLINK_PARAM_TYPE_STRING)
3306 strcpy(param_item->driverinit_value.vstr, value.vstr);
3307 else
3308 param_item->driverinit_value = value;
3309 param_item->driverinit_value_valid = true;
3310 } else {
3311 if (!param->set)
3312 return -EOPNOTSUPP;
3313 ctx.val = value;
3314 ctx.cmode = cmode;
3315 err = devlink_param_set(devlink, param, &ctx);
3316 if (err)
3317 return err;
3318 }
3319
3320 devlink_param_notify(devlink, port_index, param_item, cmd);
3321 return 0;
3322}
3323
3324static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb,
3325 struct genl_info *info)
3326{
3327 struct devlink *devlink = info->user_ptr[0];
3328
3329 return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->param_list,
3330 info, DEVLINK_CMD_PARAM_NEW);
3331}
3332
3333static int devlink_param_register_one(struct devlink *devlink,
3334 unsigned int port_index,
3335 struct list_head *param_list,
3336 const struct devlink_param *param,
3337 enum devlink_command cmd)
3338{
3339 struct devlink_param_item *param_item;
3340
3341 if (devlink_param_find_by_name(param_list, param->name))
3342 return -EEXIST;
3343
3344 if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT))
3345 WARN_ON(param->get || param->set);
3346 else
3347 WARN_ON(!param->get || !param->set);
3348
3349 param_item = kzalloc(sizeof(*param_item), GFP_KERNEL);
3350 if (!param_item)
3351 return -ENOMEM;
3352 param_item->param = param;
3353
3354 list_add_tail(¶m_item->list, param_list);
3355 devlink_param_notify(devlink, port_index, param_item, cmd);
3356 return 0;
3357}
3358
3359static void devlink_param_unregister_one(struct devlink *devlink,
3360 unsigned int port_index,
3361 struct list_head *param_list,
3362 const struct devlink_param *param,
3363 enum devlink_command cmd)
3364{
3365 struct devlink_param_item *param_item;
3366
3367 param_item = devlink_param_find_by_name(param_list, param->name);
3368 WARN_ON(!param_item);
3369 devlink_param_notify(devlink, port_index, param_item, cmd);
3370 list_del(¶m_item->list);
3371 kfree(param_item);
3372}
3373
3374static int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg,
3375 struct netlink_callback *cb)
3376{
3377 struct devlink_param_item *param_item;
3378 struct devlink_port *devlink_port;
3379 struct devlink *devlink;
3380 int start = cb->args[0];
3381 int idx = 0;
3382 int err;
3383
3384 mutex_lock(&devlink_mutex);
3385 list_for_each_entry(devlink, &devlink_list, list) {
3386 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3387 continue;
3388 mutex_lock(&devlink->lock);
3389 list_for_each_entry(devlink_port, &devlink->port_list, list) {
3390 list_for_each_entry(param_item,
3391 &devlink_port->param_list, list) {
3392 if (idx < start) {
3393 idx++;
3394 continue;
3395 }
3396 err = devlink_nl_param_fill(msg,
3397 devlink_port->devlink,
3398 devlink_port->index, param_item,
3399 DEVLINK_CMD_PORT_PARAM_GET,
3400 NETLINK_CB(cb->skb).portid,
3401 cb->nlh->nlmsg_seq,
3402 NLM_F_MULTI);
3403 if (err) {
3404 mutex_unlock(&devlink->lock);
3405 goto out;
3406 }
3407 idx++;
3408 }
3409 }
3410 mutex_unlock(&devlink->lock);
3411 }
3412out:
3413 mutex_unlock(&devlink_mutex);
3414
3415 cb->args[0] = idx;
3416 return msg->len;
3417}
3418
3419static int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb,
3420 struct genl_info *info)
3421{
3422 struct devlink_port *devlink_port = info->user_ptr[0];
3423 struct devlink_param_item *param_item;
3424 struct sk_buff *msg;
3425 int err;
3426
3427 param_item = devlink_param_get_from_info(&devlink_port->param_list,
3428 info);
3429 if (!param_item)
3430 return -EINVAL;
3431
3432 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3433 if (!msg)
3434 return -ENOMEM;
3435
3436 err = devlink_nl_param_fill(msg, devlink_port->devlink,
3437 devlink_port->index, param_item,
3438 DEVLINK_CMD_PORT_PARAM_GET,
3439 info->snd_portid, info->snd_seq, 0);
3440 if (err) {
3441 nlmsg_free(msg);
3442 return err;
3443 }
3444
3445 return genlmsg_reply(msg, info);
3446}
3447
3448static int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb,
3449 struct genl_info *info)
3450{
3451 struct devlink_port *devlink_port = info->user_ptr[0];
3452
3453 return __devlink_nl_cmd_param_set_doit(devlink_port->devlink,
3454 devlink_port->index,
3455 &devlink_port->param_list, info,
3456 DEVLINK_CMD_PORT_PARAM_NEW);
3457}
3458
3459static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg,
3460 struct devlink *devlink,
3461 struct devlink_snapshot *snapshot)
3462{
3463 struct nlattr *snap_attr;
3464 int err;
3465
3466 snap_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_SNAPSHOT);
3467 if (!snap_attr)
3468 return -EINVAL;
3469
3470 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id);
3471 if (err)
3472 goto nla_put_failure;
3473
3474 nla_nest_end(msg, snap_attr);
3475 return 0;
3476
3477nla_put_failure:
3478 nla_nest_cancel(msg, snap_attr);
3479 return err;
3480}
3481
3482static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg,
3483 struct devlink *devlink,
3484 struct devlink_region *region)
3485{
3486 struct devlink_snapshot *snapshot;
3487 struct nlattr *snapshots_attr;
3488 int err;
3489
3490 snapshots_attr = nla_nest_start_noflag(msg,
3491 DEVLINK_ATTR_REGION_SNAPSHOTS);
3492 if (!snapshots_attr)
3493 return -EINVAL;
3494
3495 list_for_each_entry(snapshot, ®ion->snapshot_list, list) {
3496 err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot);
3497 if (err)
3498 goto nla_put_failure;
3499 }
3500
3501 nla_nest_end(msg, snapshots_attr);
3502 return 0;
3503
3504nla_put_failure:
3505 nla_nest_cancel(msg, snapshots_attr);
3506 return err;
3507}
3508
3509static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink,
3510 enum devlink_command cmd, u32 portid,
3511 u32 seq, int flags,
3512 struct devlink_region *region)
3513{
3514 void *hdr;
3515 int err;
3516
3517 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
3518 if (!hdr)
3519 return -EMSGSIZE;
3520
3521 err = devlink_nl_put_handle(msg, devlink);
3522 if (err)
3523 goto nla_put_failure;
3524
3525 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->name);
3526 if (err)
3527 goto nla_put_failure;
3528
3529 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
3530 region->size,
3531 DEVLINK_ATTR_PAD);
3532 if (err)
3533 goto nla_put_failure;
3534
3535 err = devlink_nl_region_snapshots_id_put(msg, devlink, region);
3536 if (err)
3537 goto nla_put_failure;
3538
3539 genlmsg_end(msg, hdr);
3540 return 0;
3541
3542nla_put_failure:
3543 genlmsg_cancel(msg, hdr);
3544 return err;
3545}
3546
3547static void devlink_nl_region_notify(struct devlink_region *region,
3548 struct devlink_snapshot *snapshot,
3549 enum devlink_command cmd)
3550{
3551 struct devlink *devlink = region->devlink;
3552 struct sk_buff *msg;
3553 void *hdr;
3554 int err;
3555
3556 WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL);
3557
3558 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3559 if (!msg)
3560 return;
3561
3562 hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd);
3563 if (!hdr)
3564 goto out_free_msg;
3565
3566 err = devlink_nl_put_handle(msg, devlink);
3567 if (err)
3568 goto out_cancel_msg;
3569
3570 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME,
3571 region->name);
3572 if (err)
3573 goto out_cancel_msg;
3574
3575 if (snapshot) {
3576 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID,
3577 snapshot->id);
3578 if (err)
3579 goto out_cancel_msg;
3580 } else {
3581 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE,
3582 region->size, DEVLINK_ATTR_PAD);
3583 if (err)
3584 goto out_cancel_msg;
3585 }
3586 genlmsg_end(msg, hdr);
3587
3588 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
3589 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
3590
3591 return;
3592
3593out_cancel_msg:
3594 genlmsg_cancel(msg, hdr);
3595out_free_msg:
3596 nlmsg_free(msg);
3597}
3598
3599static int devlink_nl_cmd_region_get_doit(struct sk_buff *skb,
3600 struct genl_info *info)
3601{
3602 struct devlink *devlink = info->user_ptr[0];
3603 struct devlink_region *region;
3604 const char *region_name;
3605 struct sk_buff *msg;
3606 int err;
3607
3608 if (!info->attrs[DEVLINK_ATTR_REGION_NAME])
3609 return -EINVAL;
3610
3611 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
3612 region = devlink_region_get_by_name(devlink, region_name);
3613 if (!region)
3614 return -EINVAL;
3615
3616 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
3617 if (!msg)
3618 return -ENOMEM;
3619
3620 err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET,
3621 info->snd_portid, info->snd_seq, 0,
3622 region);
3623 if (err) {
3624 nlmsg_free(msg);
3625 return err;
3626 }
3627
3628 return genlmsg_reply(msg, info);
3629}
3630
3631static int devlink_nl_cmd_region_get_dumpit(struct sk_buff *msg,
3632 struct netlink_callback *cb)
3633{
3634 struct devlink_region *region;
3635 struct devlink *devlink;
3636 int start = cb->args[0];
3637 int idx = 0;
3638 int err;
3639
3640 mutex_lock(&devlink_mutex);
3641 list_for_each_entry(devlink, &devlink_list, list) {
3642 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
3643 continue;
3644
3645 mutex_lock(&devlink->lock);
3646 list_for_each_entry(region, &devlink->region_list, list) {
3647 if (idx < start) {
3648 idx++;
3649 continue;
3650 }
3651 err = devlink_nl_region_fill(msg, devlink,
3652 DEVLINK_CMD_REGION_GET,
3653 NETLINK_CB(cb->skb).portid,
3654 cb->nlh->nlmsg_seq,
3655 NLM_F_MULTI, region);
3656 if (err) {
3657 mutex_unlock(&devlink->lock);
3658 goto out;
3659 }
3660 idx++;
3661 }
3662 mutex_unlock(&devlink->lock);
3663 }
3664out:
3665 mutex_unlock(&devlink_mutex);
3666 cb->args[0] = idx;
3667 return msg->len;
3668}
3669
3670static int devlink_nl_cmd_region_del(struct sk_buff *skb,
3671 struct genl_info *info)
3672{
3673 struct devlink *devlink = info->user_ptr[0];
3674 struct devlink_snapshot *snapshot;
3675 struct devlink_region *region;
3676 const char *region_name;
3677 u32 snapshot_id;
3678
3679 if (!info->attrs[DEVLINK_ATTR_REGION_NAME] ||
3680 !info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID])
3681 return -EINVAL;
3682
3683 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]);
3684 snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
3685
3686 region = devlink_region_get_by_name(devlink, region_name);
3687 if (!region)
3688 return -EINVAL;
3689
3690 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
3691 if (!snapshot)
3692 return -EINVAL;
3693
3694 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL);
3695 devlink_region_snapshot_del(snapshot);
3696 return 0;
3697}
3698
3699static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg,
3700 struct devlink *devlink,
3701 u8 *chunk, u32 chunk_size,
3702 u64 addr)
3703{
3704 struct nlattr *chunk_attr;
3705 int err;
3706
3707 chunk_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_CHUNK);
3708 if (!chunk_attr)
3709 return -EINVAL;
3710
3711 err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk);
3712 if (err)
3713 goto nla_put_failure;
3714
3715 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr,
3716 DEVLINK_ATTR_PAD);
3717 if (err)
3718 goto nla_put_failure;
3719
3720 nla_nest_end(msg, chunk_attr);
3721 return 0;
3722
3723nla_put_failure:
3724 nla_nest_cancel(msg, chunk_attr);
3725 return err;
3726}
3727
3728#define DEVLINK_REGION_READ_CHUNK_SIZE 256
3729
3730static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb,
3731 struct devlink *devlink,
3732 struct devlink_region *region,
3733 struct nlattr **attrs,
3734 u64 start_offset,
3735 u64 end_offset,
3736 bool dump,
3737 u64 *new_offset)
3738{
3739 struct devlink_snapshot *snapshot;
3740 u64 curr_offset = start_offset;
3741 u32 snapshot_id;
3742 int err = 0;
3743
3744 *new_offset = start_offset;
3745
3746 snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]);
3747 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id);
3748 if (!snapshot)
3749 return -EINVAL;
3750
3751 if (end_offset > snapshot->data_len || dump)
3752 end_offset = snapshot->data_len;
3753
3754 while (curr_offset < end_offset) {
3755 u32 data_size;
3756 u8 *data;
3757
3758 if (end_offset - curr_offset < DEVLINK_REGION_READ_CHUNK_SIZE)
3759 data_size = end_offset - curr_offset;
3760 else
3761 data_size = DEVLINK_REGION_READ_CHUNK_SIZE;
3762
3763 data = &snapshot->data[curr_offset];
3764 err = devlink_nl_cmd_region_read_chunk_fill(skb, devlink,
3765 data, data_size,
3766 curr_offset);
3767 if (err)
3768 break;
3769
3770 curr_offset += data_size;
3771 }
3772 *new_offset = curr_offset;
3773
3774 return err;
3775}
3776
3777static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb,
3778 struct netlink_callback *cb)
3779{
3780 u64 ret_offset, start_offset, end_offset = 0;
3781 struct devlink_region *region;
3782 struct nlattr *chunks_attr;
3783 const char *region_name;
3784 struct devlink *devlink;
3785 struct nlattr **attrs;
3786 bool dump = true;
3787 void *hdr;
3788 int err;
3789
3790 start_offset = *((u64 *)&cb->args[0]);
3791
3792 attrs = kmalloc_array(DEVLINK_ATTR_MAX + 1, sizeof(*attrs), GFP_KERNEL);
3793 if (!attrs)
3794 return -ENOMEM;
3795
3796 err = nlmsg_parse_deprecated(cb->nlh,
3797 GENL_HDRLEN + devlink_nl_family.hdrsize,
3798 attrs, DEVLINK_ATTR_MAX,
3799 devlink_nl_family.policy, cb->extack);
3800 if (err)
3801 goto out_free;
3802
3803 mutex_lock(&devlink_mutex);
3804 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
3805 if (IS_ERR(devlink)) {
3806 err = PTR_ERR(devlink);
3807 goto out_dev;
3808 }
3809
3810 mutex_lock(&devlink->lock);
3811
3812 if (!attrs[DEVLINK_ATTR_REGION_NAME] ||
3813 !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) {
3814 err = -EINVAL;
3815 goto out_unlock;
3816 }
3817
3818 region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]);
3819 region = devlink_region_get_by_name(devlink, region_name);
3820 if (!region) {
3821 err = -EINVAL;
3822 goto out_unlock;
3823 }
3824
3825 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
3826 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI,
3827 DEVLINK_CMD_REGION_READ);
3828 if (!hdr) {
3829 err = -EMSGSIZE;
3830 goto out_unlock;
3831 }
3832
3833 err = devlink_nl_put_handle(skb, devlink);
3834 if (err)
3835 goto nla_put_failure;
3836
3837 err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name);
3838 if (err)
3839 goto nla_put_failure;
3840
3841 chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS);
3842 if (!chunks_attr) {
3843 err = -EMSGSIZE;
3844 goto nla_put_failure;
3845 }
3846
3847 if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] &&
3848 attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) {
3849 if (!start_offset)
3850 start_offset =
3851 nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
3852
3853 end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]);
3854 end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]);
3855 dump = false;
3856 }
3857
3858 err = devlink_nl_region_read_snapshot_fill(skb, devlink,
3859 region, attrs,
3860 start_offset,
3861 end_offset, dump,
3862 &ret_offset);
3863
3864 if (err && err != -EMSGSIZE)
3865 goto nla_put_failure;
3866
3867 /* Check if there was any progress done to prevent infinite loop */
3868 if (ret_offset == start_offset) {
3869 err = -EINVAL;
3870 goto nla_put_failure;
3871 }
3872
3873 *((u64 *)&cb->args[0]) = ret_offset;
3874
3875 nla_nest_end(skb, chunks_attr);
3876 genlmsg_end(skb, hdr);
3877 mutex_unlock(&devlink->lock);
3878 mutex_unlock(&devlink_mutex);
3879 kfree(attrs);
3880
3881 return skb->len;
3882
3883nla_put_failure:
3884 genlmsg_cancel(skb, hdr);
3885out_unlock:
3886 mutex_unlock(&devlink->lock);
3887out_dev:
3888 mutex_unlock(&devlink_mutex);
3889out_free:
3890 kfree(attrs);
3891 return err;
3892}
3893
3894struct devlink_info_req {
3895 struct sk_buff *msg;
3896};
3897
3898int devlink_info_driver_name_put(struct devlink_info_req *req, const char *name)
3899{
3900 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRIVER_NAME, name);
3901}
3902EXPORT_SYMBOL_GPL(devlink_info_driver_name_put);
3903
3904int devlink_info_serial_number_put(struct devlink_info_req *req, const char *sn)
3905{
3906 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_SERIAL_NUMBER, sn);
3907}
3908EXPORT_SYMBOL_GPL(devlink_info_serial_number_put);
3909
3910static int devlink_info_version_put(struct devlink_info_req *req, int attr,
3911 const char *version_name,
3912 const char *version_value)
3913{
3914 struct nlattr *nest;
3915 int err;
3916
3917 nest = nla_nest_start_noflag(req->msg, attr);
3918 if (!nest)
3919 return -EMSGSIZE;
3920
3921 err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_NAME,
3922 version_name);
3923 if (err)
3924 goto nla_put_failure;
3925
3926 err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_VALUE,
3927 version_value);
3928 if (err)
3929 goto nla_put_failure;
3930
3931 nla_nest_end(req->msg, nest);
3932
3933 return 0;
3934
3935nla_put_failure:
3936 nla_nest_cancel(req->msg, nest);
3937 return err;
3938}
3939
3940int devlink_info_version_fixed_put(struct devlink_info_req *req,
3941 const char *version_name,
3942 const char *version_value)
3943{
3944 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_FIXED,
3945 version_name, version_value);
3946}
3947EXPORT_SYMBOL_GPL(devlink_info_version_fixed_put);
3948
3949int devlink_info_version_stored_put(struct devlink_info_req *req,
3950 const char *version_name,
3951 const char *version_value)
3952{
3953 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_STORED,
3954 version_name, version_value);
3955}
3956EXPORT_SYMBOL_GPL(devlink_info_version_stored_put);
3957
3958int devlink_info_version_running_put(struct devlink_info_req *req,
3959 const char *version_name,
3960 const char *version_value)
3961{
3962 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_RUNNING,
3963 version_name, version_value);
3964}
3965EXPORT_SYMBOL_GPL(devlink_info_version_running_put);
3966
3967static int
3968devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink,
3969 enum devlink_command cmd, u32 portid,
3970 u32 seq, int flags, struct netlink_ext_ack *extack)
3971{
3972 struct devlink_info_req req;
3973 void *hdr;
3974 int err;
3975
3976 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
3977 if (!hdr)
3978 return -EMSGSIZE;
3979
3980 err = -EMSGSIZE;
3981 if (devlink_nl_put_handle(msg, devlink))
3982 goto err_cancel_msg;
3983
3984 req.msg = msg;
3985 err = devlink->ops->info_get(devlink, &req, extack);
3986 if (err)
3987 goto err_cancel_msg;
3988
3989 genlmsg_end(msg, hdr);
3990 return 0;
3991
3992err_cancel_msg:
3993 genlmsg_cancel(msg, hdr);
3994 return err;
3995}
3996
3997static int devlink_nl_cmd_info_get_doit(struct sk_buff *skb,
3998 struct genl_info *info)
3999{
4000 struct devlink *devlink = info->user_ptr[0];
4001 struct sk_buff *msg;
4002 int err;
4003
4004 if (!devlink->ops->info_get)
4005 return -EOPNOTSUPP;
4006
4007 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4008 if (!msg)
4009 return -ENOMEM;
4010
4011 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
4012 info->snd_portid, info->snd_seq, 0,
4013 info->extack);
4014 if (err) {
4015 nlmsg_free(msg);
4016 return err;
4017 }
4018
4019 return genlmsg_reply(msg, info);
4020}
4021
4022static int devlink_nl_cmd_info_get_dumpit(struct sk_buff *msg,
4023 struct netlink_callback *cb)
4024{
4025 struct devlink *devlink;
4026 int start = cb->args[0];
4027 int idx = 0;
4028 int err;
4029
4030 mutex_lock(&devlink_mutex);
4031 list_for_each_entry(devlink, &devlink_list, list) {
4032 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
4033 continue;
4034 if (idx < start) {
4035 idx++;
4036 continue;
4037 }
4038
4039 if (!devlink->ops->info_get) {
4040 idx++;
4041 continue;
4042 }
4043
4044 mutex_lock(&devlink->lock);
4045 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET,
4046 NETLINK_CB(cb->skb).portid,
4047 cb->nlh->nlmsg_seq, NLM_F_MULTI,
4048 cb->extack);
4049 mutex_unlock(&devlink->lock);
4050 if (err)
4051 break;
4052 idx++;
4053 }
4054 mutex_unlock(&devlink_mutex);
4055
4056 cb->args[0] = idx;
4057 return msg->len;
4058}
4059
4060struct devlink_fmsg_item {
4061 struct list_head list;
4062 int attrtype;
4063 u8 nla_type;
4064 u16 len;
4065 int value[0];
4066};
4067
4068struct devlink_fmsg {
4069 struct list_head item_list;
4070};
4071
4072static struct devlink_fmsg *devlink_fmsg_alloc(void)
4073{
4074 struct devlink_fmsg *fmsg;
4075
4076 fmsg = kzalloc(sizeof(*fmsg), GFP_KERNEL);
4077 if (!fmsg)
4078 return NULL;
4079
4080 INIT_LIST_HEAD(&fmsg->item_list);
4081
4082 return fmsg;
4083}
4084
4085static void devlink_fmsg_free(struct devlink_fmsg *fmsg)
4086{
4087 struct devlink_fmsg_item *item, *tmp;
4088
4089 list_for_each_entry_safe(item, tmp, &fmsg->item_list, list) {
4090 list_del(&item->list);
4091 kfree(item);
4092 }
4093 kfree(fmsg);
4094}
4095
4096static int devlink_fmsg_nest_common(struct devlink_fmsg *fmsg,
4097 int attrtype)
4098{
4099 struct devlink_fmsg_item *item;
4100
4101 item = kzalloc(sizeof(*item), GFP_KERNEL);
4102 if (!item)
4103 return -ENOMEM;
4104
4105 item->attrtype = attrtype;
4106 list_add_tail(&item->list, &fmsg->item_list);
4107
4108 return 0;
4109}
4110
4111int devlink_fmsg_obj_nest_start(struct devlink_fmsg *fmsg)
4112{
4113 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_OBJ_NEST_START);
4114}
4115EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_start);
4116
4117static int devlink_fmsg_nest_end(struct devlink_fmsg *fmsg)
4118{
4119 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_NEST_END);
4120}
4121
4122int devlink_fmsg_obj_nest_end(struct devlink_fmsg *fmsg)
4123{
4124 return devlink_fmsg_nest_end(fmsg);
4125}
4126EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_end);
4127
4128#define DEVLINK_FMSG_MAX_SIZE (GENLMSG_DEFAULT_SIZE - GENL_HDRLEN - NLA_HDRLEN)
4129
4130static int devlink_fmsg_put_name(struct devlink_fmsg *fmsg, const char *name)
4131{
4132 struct devlink_fmsg_item *item;
4133
4134 if (strlen(name) + 1 > DEVLINK_FMSG_MAX_SIZE)
4135 return -EMSGSIZE;
4136
4137 item = kzalloc(sizeof(*item) + strlen(name) + 1, GFP_KERNEL);
4138 if (!item)
4139 return -ENOMEM;
4140
4141 item->nla_type = NLA_NUL_STRING;
4142 item->len = strlen(name) + 1;
4143 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_NAME;
4144 memcpy(&item->value, name, item->len);
4145 list_add_tail(&item->list, &fmsg->item_list);
4146
4147 return 0;
4148}
4149
4150int devlink_fmsg_pair_nest_start(struct devlink_fmsg *fmsg, const char *name)
4151{
4152 int err;
4153
4154 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_PAIR_NEST_START);
4155 if (err)
4156 return err;
4157
4158 err = devlink_fmsg_put_name(fmsg, name);
4159 if (err)
4160 return err;
4161
4162 return 0;
4163}
4164EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_start);
4165
4166int devlink_fmsg_pair_nest_end(struct devlink_fmsg *fmsg)
4167{
4168 return devlink_fmsg_nest_end(fmsg);
4169}
4170EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_end);
4171
4172int devlink_fmsg_arr_pair_nest_start(struct devlink_fmsg *fmsg,
4173 const char *name)
4174{
4175 int err;
4176
4177 err = devlink_fmsg_pair_nest_start(fmsg, name);
4178 if (err)
4179 return err;
4180
4181 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_ARR_NEST_START);
4182 if (err)
4183 return err;
4184
4185 return 0;
4186}
4187EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_start);
4188
4189int devlink_fmsg_arr_pair_nest_end(struct devlink_fmsg *fmsg)
4190{
4191 int err;
4192
4193 err = devlink_fmsg_nest_end(fmsg);
4194 if (err)
4195 return err;
4196
4197 err = devlink_fmsg_nest_end(fmsg);
4198 if (err)
4199 return err;
4200
4201 return 0;
4202}
4203EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_end);
4204
4205static int devlink_fmsg_put_value(struct devlink_fmsg *fmsg,
4206 const void *value, u16 value_len,
4207 u8 value_nla_type)
4208{
4209 struct devlink_fmsg_item *item;
4210
4211 if (value_len > DEVLINK_FMSG_MAX_SIZE)
4212 return -EMSGSIZE;
4213
4214 item = kzalloc(sizeof(*item) + value_len, GFP_KERNEL);
4215 if (!item)
4216 return -ENOMEM;
4217
4218 item->nla_type = value_nla_type;
4219 item->len = value_len;
4220 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
4221 memcpy(&item->value, value, item->len);
4222 list_add_tail(&item->list, &fmsg->item_list);
4223
4224 return 0;
4225}
4226
4227int devlink_fmsg_bool_put(struct devlink_fmsg *fmsg, bool value)
4228{
4229 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_FLAG);
4230}
4231EXPORT_SYMBOL_GPL(devlink_fmsg_bool_put);
4232
4233int devlink_fmsg_u8_put(struct devlink_fmsg *fmsg, u8 value)
4234{
4235 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U8);
4236}
4237EXPORT_SYMBOL_GPL(devlink_fmsg_u8_put);
4238
4239int devlink_fmsg_u32_put(struct devlink_fmsg *fmsg, u32 value)
4240{
4241 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U32);
4242}
4243EXPORT_SYMBOL_GPL(devlink_fmsg_u32_put);
4244
4245int devlink_fmsg_u64_put(struct devlink_fmsg *fmsg, u64 value)
4246{
4247 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U64);
4248}
4249EXPORT_SYMBOL_GPL(devlink_fmsg_u64_put);
4250
4251int devlink_fmsg_string_put(struct devlink_fmsg *fmsg, const char *value)
4252{
4253 return devlink_fmsg_put_value(fmsg, value, strlen(value) + 1,
4254 NLA_NUL_STRING);
4255}
4256EXPORT_SYMBOL_GPL(devlink_fmsg_string_put);
4257
4258int devlink_fmsg_binary_put(struct devlink_fmsg *fmsg, const void *value,
4259 u16 value_len)
4260{
4261 return devlink_fmsg_put_value(fmsg, value, value_len, NLA_BINARY);
4262}
4263EXPORT_SYMBOL_GPL(devlink_fmsg_binary_put);
4264
4265int devlink_fmsg_bool_pair_put(struct devlink_fmsg *fmsg, const char *name,
4266 bool value)
4267{
4268 int err;
4269
4270 err = devlink_fmsg_pair_nest_start(fmsg, name);
4271 if (err)
4272 return err;
4273
4274 err = devlink_fmsg_bool_put(fmsg, value);
4275 if (err)
4276 return err;
4277
4278 err = devlink_fmsg_pair_nest_end(fmsg);
4279 if (err)
4280 return err;
4281
4282 return 0;
4283}
4284EXPORT_SYMBOL_GPL(devlink_fmsg_bool_pair_put);
4285
4286int devlink_fmsg_u8_pair_put(struct devlink_fmsg *fmsg, const char *name,
4287 u8 value)
4288{
4289 int err;
4290
4291 err = devlink_fmsg_pair_nest_start(fmsg, name);
4292 if (err)
4293 return err;
4294
4295 err = devlink_fmsg_u8_put(fmsg, value);
4296 if (err)
4297 return err;
4298
4299 err = devlink_fmsg_pair_nest_end(fmsg);
4300 if (err)
4301 return err;
4302
4303 return 0;
4304}
4305EXPORT_SYMBOL_GPL(devlink_fmsg_u8_pair_put);
4306
4307int devlink_fmsg_u32_pair_put(struct devlink_fmsg *fmsg, const char *name,
4308 u32 value)
4309{
4310 int err;
4311
4312 err = devlink_fmsg_pair_nest_start(fmsg, name);
4313 if (err)
4314 return err;
4315
4316 err = devlink_fmsg_u32_put(fmsg, value);
4317 if (err)
4318 return err;
4319
4320 err = devlink_fmsg_pair_nest_end(fmsg);
4321 if (err)
4322 return err;
4323
4324 return 0;
4325}
4326EXPORT_SYMBOL_GPL(devlink_fmsg_u32_pair_put);
4327
4328int devlink_fmsg_u64_pair_put(struct devlink_fmsg *fmsg, const char *name,
4329 u64 value)
4330{
4331 int err;
4332
4333 err = devlink_fmsg_pair_nest_start(fmsg, name);
4334 if (err)
4335 return err;
4336
4337 err = devlink_fmsg_u64_put(fmsg, value);
4338 if (err)
4339 return err;
4340
4341 err = devlink_fmsg_pair_nest_end(fmsg);
4342 if (err)
4343 return err;
4344
4345 return 0;
4346}
4347EXPORT_SYMBOL_GPL(devlink_fmsg_u64_pair_put);
4348
4349int devlink_fmsg_string_pair_put(struct devlink_fmsg *fmsg, const char *name,
4350 const char *value)
4351{
4352 int err;
4353
4354 err = devlink_fmsg_pair_nest_start(fmsg, name);
4355 if (err)
4356 return err;
4357
4358 err = devlink_fmsg_string_put(fmsg, value);
4359 if (err)
4360 return err;
4361
4362 err = devlink_fmsg_pair_nest_end(fmsg);
4363 if (err)
4364 return err;
4365
4366 return 0;
4367}
4368EXPORT_SYMBOL_GPL(devlink_fmsg_string_pair_put);
4369
4370int devlink_fmsg_binary_pair_put(struct devlink_fmsg *fmsg, const char *name,
4371 const void *value, u16 value_len)
4372{
4373 int err;
4374
4375 err = devlink_fmsg_pair_nest_start(fmsg, name);
4376 if (err)
4377 return err;
4378
4379 err = devlink_fmsg_binary_put(fmsg, value, value_len);
4380 if (err)
4381 return err;
4382
4383 err = devlink_fmsg_pair_nest_end(fmsg);
4384 if (err)
4385 return err;
4386
4387 return 0;
4388}
4389EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_put);
4390
4391static int
4392devlink_fmsg_item_fill_type(struct devlink_fmsg_item *msg, struct sk_buff *skb)
4393{
4394 switch (msg->nla_type) {
4395 case NLA_FLAG:
4396 case NLA_U8:
4397 case NLA_U32:
4398 case NLA_U64:
4399 case NLA_NUL_STRING:
4400 case NLA_BINARY:
4401 return nla_put_u8(skb, DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE,
4402 msg->nla_type);
4403 default:
4404 return -EINVAL;
4405 }
4406}
4407
4408static int
4409devlink_fmsg_item_fill_data(struct devlink_fmsg_item *msg, struct sk_buff *skb)
4410{
4411 int attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA;
4412 u8 tmp;
4413
4414 switch (msg->nla_type) {
4415 case NLA_FLAG:
4416 /* Always provide flag data, regardless of its value */
4417 tmp = *(bool *) msg->value;
4418
4419 return nla_put_u8(skb, attrtype, tmp);
4420 case NLA_U8:
4421 return nla_put_u8(skb, attrtype, *(u8 *) msg->value);
4422 case NLA_U32:
4423 return nla_put_u32(skb, attrtype, *(u32 *) msg->value);
4424 case NLA_U64:
4425 return nla_put_u64_64bit(skb, attrtype, *(u64 *) msg->value,
4426 DEVLINK_ATTR_PAD);
4427 case NLA_NUL_STRING:
4428 return nla_put_string(skb, attrtype, (char *) &msg->value);
4429 case NLA_BINARY:
4430 return nla_put(skb, attrtype, msg->len, (void *) &msg->value);
4431 default:
4432 return -EINVAL;
4433 }
4434}
4435
4436static int
4437devlink_fmsg_prepare_skb(struct devlink_fmsg *fmsg, struct sk_buff *skb,
4438 int *start)
4439{
4440 struct devlink_fmsg_item *item;
4441 struct nlattr *fmsg_nlattr;
4442 int i = 0;
4443 int err;
4444
4445 fmsg_nlattr = nla_nest_start_noflag(skb, DEVLINK_ATTR_FMSG);
4446 if (!fmsg_nlattr)
4447 return -EMSGSIZE;
4448
4449 list_for_each_entry(item, &fmsg->item_list, list) {
4450 if (i < *start) {
4451 i++;
4452 continue;
4453 }
4454
4455 switch (item->attrtype) {
4456 case DEVLINK_ATTR_FMSG_OBJ_NEST_START:
4457 case DEVLINK_ATTR_FMSG_PAIR_NEST_START:
4458 case DEVLINK_ATTR_FMSG_ARR_NEST_START:
4459 case DEVLINK_ATTR_FMSG_NEST_END:
4460 err = nla_put_flag(skb, item->attrtype);
4461 break;
4462 case DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA:
4463 err = devlink_fmsg_item_fill_type(item, skb);
4464 if (err)
4465 break;
4466 err = devlink_fmsg_item_fill_data(item, skb);
4467 break;
4468 case DEVLINK_ATTR_FMSG_OBJ_NAME:
4469 err = nla_put_string(skb, item->attrtype,
4470 (char *) &item->value);
4471 break;
4472 default:
4473 err = -EINVAL;
4474 break;
4475 }
4476 if (!err)
4477 *start = ++i;
4478 else
4479 break;
4480 }
4481
4482 nla_nest_end(skb, fmsg_nlattr);
4483 return err;
4484}
4485
4486static int devlink_fmsg_snd(struct devlink_fmsg *fmsg,
4487 struct genl_info *info,
4488 enum devlink_command cmd, int flags)
4489{
4490 struct nlmsghdr *nlh;
4491 struct sk_buff *skb;
4492 bool last = false;
4493 int index = 0;
4494 void *hdr;
4495 int err;
4496
4497 while (!last) {
4498 int tmp_index = index;
4499
4500 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
4501 if (!skb)
4502 return -ENOMEM;
4503
4504 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
4505 &devlink_nl_family, flags | NLM_F_MULTI, cmd);
4506 if (!hdr) {
4507 err = -EMSGSIZE;
4508 goto nla_put_failure;
4509 }
4510
4511 err = devlink_fmsg_prepare_skb(fmsg, skb, &index);
4512 if (!err)
4513 last = true;
4514 else if (err != -EMSGSIZE || tmp_index == index)
4515 goto nla_put_failure;
4516
4517 genlmsg_end(skb, hdr);
4518 err = genlmsg_reply(skb, info);
4519 if (err)
4520 return err;
4521 }
4522
4523 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
4524 if (!skb)
4525 return -ENOMEM;
4526 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
4527 NLMSG_DONE, 0, flags | NLM_F_MULTI);
4528 if (!nlh) {
4529 err = -EMSGSIZE;
4530 goto nla_put_failure;
4531 }
4532
4533 return genlmsg_reply(skb, info);
4534
4535nla_put_failure:
4536 nlmsg_free(skb);
4537 return err;
4538}
4539
4540static int devlink_fmsg_dumpit(struct devlink_fmsg *fmsg, struct sk_buff *skb,
4541 struct netlink_callback *cb,
4542 enum devlink_command cmd)
4543{
4544 int index = cb->args[0];
4545 int tmp_index = index;
4546 void *hdr;
4547 int err;
4548
4549 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
4550 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, cmd);
4551 if (!hdr) {
4552 err = -EMSGSIZE;
4553 goto nla_put_failure;
4554 }
4555
4556 err = devlink_fmsg_prepare_skb(fmsg, skb, &index);
4557 if ((err && err != -EMSGSIZE) || tmp_index == index)
4558 goto nla_put_failure;
4559
4560 cb->args[0] = index;
4561 genlmsg_end(skb, hdr);
4562 return skb->len;
4563
4564nla_put_failure:
4565 genlmsg_cancel(skb, hdr);
4566 return err;
4567}
4568
4569struct devlink_health_reporter {
4570 struct list_head list;
4571 void *priv;
4572 const struct devlink_health_reporter_ops *ops;
4573 struct devlink *devlink;
4574 struct devlink_fmsg *dump_fmsg;
4575 struct mutex dump_lock; /* lock parallel read/write from dump buffers */
4576 u64 graceful_period;
4577 bool auto_recover;
4578 u8 health_state;
4579 u64 dump_ts;
4580 u64 error_count;
4581 u64 recovery_count;
4582 u64 last_recovery_ts;
4583 refcount_t refcount;
4584};
4585
4586void *
4587devlink_health_reporter_priv(struct devlink_health_reporter *reporter)
4588{
4589 return reporter->priv;
4590}
4591EXPORT_SYMBOL_GPL(devlink_health_reporter_priv);
4592
4593static struct devlink_health_reporter *
4594devlink_health_reporter_find_by_name(struct devlink *devlink,
4595 const char *reporter_name)
4596{
4597 struct devlink_health_reporter *reporter;
4598
4599 lockdep_assert_held(&devlink->reporters_lock);
4600 list_for_each_entry(reporter, &devlink->reporter_list, list)
4601 if (!strcmp(reporter->ops->name, reporter_name))
4602 return reporter;
4603 return NULL;
4604}
4605
4606/**
4607 * devlink_health_reporter_create - create devlink health reporter
4608 *
4609 * @devlink: devlink
4610 * @ops: ops
4611 * @graceful_period: to avoid recovery loops, in msecs
4612 * @auto_recover: auto recover when error occurs
4613 * @priv: priv
4614 */
4615struct devlink_health_reporter *
4616devlink_health_reporter_create(struct devlink *devlink,
4617 const struct devlink_health_reporter_ops *ops,
4618 u64 graceful_period, bool auto_recover,
4619 void *priv)
4620{
4621 struct devlink_health_reporter *reporter;
4622
4623 mutex_lock(&devlink->reporters_lock);
4624 if (devlink_health_reporter_find_by_name(devlink, ops->name)) {
4625 reporter = ERR_PTR(-EEXIST);
4626 goto unlock;
4627 }
4628
4629 if (WARN_ON(auto_recover && !ops->recover) ||
4630 WARN_ON(graceful_period && !ops->recover)) {
4631 reporter = ERR_PTR(-EINVAL);
4632 goto unlock;
4633 }
4634
4635 reporter = kzalloc(sizeof(*reporter), GFP_KERNEL);
4636 if (!reporter) {
4637 reporter = ERR_PTR(-ENOMEM);
4638 goto unlock;
4639 }
4640
4641 reporter->priv = priv;
4642 reporter->ops = ops;
4643 reporter->devlink = devlink;
4644 reporter->graceful_period = graceful_period;
4645 reporter->auto_recover = auto_recover;
4646 mutex_init(&reporter->dump_lock);
4647 refcount_set(&reporter->refcount, 1);
4648 list_add_tail(&reporter->list, &devlink->reporter_list);
4649unlock:
4650 mutex_unlock(&devlink->reporters_lock);
4651 return reporter;
4652}
4653EXPORT_SYMBOL_GPL(devlink_health_reporter_create);
4654
4655/**
4656 * devlink_health_reporter_destroy - destroy devlink health reporter
4657 *
4658 * @reporter: devlink health reporter to destroy
4659 */
4660void
4661devlink_health_reporter_destroy(struct devlink_health_reporter *reporter)
4662{
4663 mutex_lock(&reporter->devlink->reporters_lock);
4664 list_del(&reporter->list);
4665 mutex_unlock(&reporter->devlink->reporters_lock);
4666 while (refcount_read(&reporter->refcount) > 1)
4667 msleep(100);
4668 mutex_destroy(&reporter->dump_lock);
4669 if (reporter->dump_fmsg)
4670 devlink_fmsg_free(reporter->dump_fmsg);
4671 kfree(reporter);
4672}
4673EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy);
4674
4675void
4676devlink_health_reporter_state_update(struct devlink_health_reporter *reporter,
4677 enum devlink_health_reporter_state state)
4678{
4679 if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY &&
4680 state != DEVLINK_HEALTH_REPORTER_STATE_ERROR))
4681 return;
4682
4683 if (reporter->health_state == state)
4684 return;
4685
4686 reporter->health_state = state;
4687 trace_devlink_health_reporter_state_update(reporter->devlink,
4688 reporter->ops->name, state);
4689}
4690EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update);
4691
4692static int
4693devlink_health_reporter_recover(struct devlink_health_reporter *reporter,
4694 void *priv_ctx)
4695{
4696 int err;
4697
4698 if (!reporter->ops->recover)
4699 return -EOPNOTSUPP;
4700
4701 err = reporter->ops->recover(reporter, priv_ctx);
4702 if (err)
4703 return err;
4704
4705 reporter->recovery_count++;
4706 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY;
4707 reporter->last_recovery_ts = jiffies;
4708
4709 return 0;
4710}
4711
4712static void
4713devlink_health_dump_clear(struct devlink_health_reporter *reporter)
4714{
4715 if (!reporter->dump_fmsg)
4716 return;
4717 devlink_fmsg_free(reporter->dump_fmsg);
4718 reporter->dump_fmsg = NULL;
4719}
4720
4721static int devlink_health_do_dump(struct devlink_health_reporter *reporter,
4722 void *priv_ctx)
4723{
4724 int err;
4725
4726 if (!reporter->ops->dump)
4727 return 0;
4728
4729 if (reporter->dump_fmsg)
4730 return 0;
4731
4732 reporter->dump_fmsg = devlink_fmsg_alloc();
4733 if (!reporter->dump_fmsg) {
4734 err = -ENOMEM;
4735 return err;
4736 }
4737
4738 err = devlink_fmsg_obj_nest_start(reporter->dump_fmsg);
4739 if (err)
4740 goto dump_err;
4741
4742 err = reporter->ops->dump(reporter, reporter->dump_fmsg,
4743 priv_ctx);
4744 if (err)
4745 goto dump_err;
4746
4747 err = devlink_fmsg_obj_nest_end(reporter->dump_fmsg);
4748 if (err)
4749 goto dump_err;
4750
4751 reporter->dump_ts = jiffies;
4752
4753 return 0;
4754
4755dump_err:
4756 devlink_health_dump_clear(reporter);
4757 return err;
4758}
4759
4760int devlink_health_report(struct devlink_health_reporter *reporter,
4761 const char *msg, void *priv_ctx)
4762{
4763 enum devlink_health_reporter_state prev_health_state;
4764 struct devlink *devlink = reporter->devlink;
4765
4766 /* write a log message of the current error */
4767 WARN_ON(!msg);
4768 trace_devlink_health_report(devlink, reporter->ops->name, msg);
4769 reporter->error_count++;
4770 prev_health_state = reporter->health_state;
4771 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
4772
4773 /* abort if the previous error wasn't recovered */
4774 if (reporter->auto_recover &&
4775 (prev_health_state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY ||
4776 jiffies - reporter->last_recovery_ts <
4777 msecs_to_jiffies(reporter->graceful_period))) {
4778 trace_devlink_health_recover_aborted(devlink,
4779 reporter->ops->name,
4780 reporter->health_state,
4781 jiffies -
4782 reporter->last_recovery_ts);
4783 return -ECANCELED;
4784 }
4785
4786 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR;
4787
4788 mutex_lock(&reporter->dump_lock);
4789 /* store current dump of current error, for later analysis */
4790 devlink_health_do_dump(reporter, priv_ctx);
4791 mutex_unlock(&reporter->dump_lock);
4792
4793 if (reporter->auto_recover)
4794 return devlink_health_reporter_recover(reporter, priv_ctx);
4795
4796 return 0;
4797}
4798EXPORT_SYMBOL_GPL(devlink_health_report);
4799
4800static struct devlink_health_reporter *
4801devlink_health_reporter_get_from_attrs(struct devlink *devlink,
4802 struct nlattr **attrs)
4803{
4804 struct devlink_health_reporter *reporter;
4805 char *reporter_name;
4806
4807 if (!attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME])
4808 return NULL;
4809
4810 reporter_name = nla_data(attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]);
4811 mutex_lock(&devlink->reporters_lock);
4812 reporter = devlink_health_reporter_find_by_name(devlink, reporter_name);
4813 if (reporter)
4814 refcount_inc(&reporter->refcount);
4815 mutex_unlock(&devlink->reporters_lock);
4816 return reporter;
4817}
4818
4819static struct devlink_health_reporter *
4820devlink_health_reporter_get_from_info(struct devlink *devlink,
4821 struct genl_info *info)
4822{
4823 return devlink_health_reporter_get_from_attrs(devlink, info->attrs);
4824}
4825
4826static struct devlink_health_reporter *
4827devlink_health_reporter_get_from_cb(struct netlink_callback *cb)
4828{
4829 struct devlink_health_reporter *reporter;
4830 struct devlink *devlink;
4831 struct nlattr **attrs;
4832 int err;
4833
4834 attrs = kmalloc_array(DEVLINK_ATTR_MAX + 1, sizeof(*attrs), GFP_KERNEL);
4835 if (!attrs)
4836 return NULL;
4837
4838 err = nlmsg_parse_deprecated(cb->nlh,
4839 GENL_HDRLEN + devlink_nl_family.hdrsize,
4840 attrs, DEVLINK_ATTR_MAX,
4841 devlink_nl_family.policy, cb->extack);
4842 if (err)
4843 goto free;
4844
4845 mutex_lock(&devlink_mutex);
4846 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs);
4847 if (IS_ERR(devlink))
4848 goto unlock;
4849
4850 reporter = devlink_health_reporter_get_from_attrs(devlink, attrs);
4851 mutex_unlock(&devlink_mutex);
4852 kfree(attrs);
4853 return reporter;
4854unlock:
4855 mutex_unlock(&devlink_mutex);
4856free:
4857 kfree(attrs);
4858 return NULL;
4859}
4860
4861static void
4862devlink_health_reporter_put(struct devlink_health_reporter *reporter)
4863{
4864 refcount_dec(&reporter->refcount);
4865}
4866
4867static int
4868devlink_nl_health_reporter_fill(struct sk_buff *msg,
4869 struct devlink *devlink,
4870 struct devlink_health_reporter *reporter,
4871 enum devlink_command cmd, u32 portid,
4872 u32 seq, int flags)
4873{
4874 struct nlattr *reporter_attr;
4875 void *hdr;
4876
4877 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
4878 if (!hdr)
4879 return -EMSGSIZE;
4880
4881 if (devlink_nl_put_handle(msg, devlink))
4882 goto genlmsg_cancel;
4883
4884 reporter_attr = nla_nest_start_noflag(msg,
4885 DEVLINK_ATTR_HEALTH_REPORTER);
4886 if (!reporter_attr)
4887 goto genlmsg_cancel;
4888 if (nla_put_string(msg, DEVLINK_ATTR_HEALTH_REPORTER_NAME,
4889 reporter->ops->name))
4890 goto reporter_nest_cancel;
4891 if (nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_STATE,
4892 reporter->health_state))
4893 goto reporter_nest_cancel;
4894 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_ERR_COUNT,
4895 reporter->error_count, DEVLINK_ATTR_PAD))
4896 goto reporter_nest_cancel;
4897 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_RECOVER_COUNT,
4898 reporter->recovery_count, DEVLINK_ATTR_PAD))
4899 goto reporter_nest_cancel;
4900 if (reporter->ops->recover &&
4901 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD,
4902 reporter->graceful_period,
4903 DEVLINK_ATTR_PAD))
4904 goto reporter_nest_cancel;
4905 if (reporter->ops->recover &&
4906 nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER,
4907 reporter->auto_recover))
4908 goto reporter_nest_cancel;
4909 if (reporter->dump_fmsg &&
4910 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS,
4911 jiffies_to_msecs(reporter->dump_ts),
4912 DEVLINK_ATTR_PAD))
4913 goto reporter_nest_cancel;
4914
4915 nla_nest_end(msg, reporter_attr);
4916 genlmsg_end(msg, hdr);
4917 return 0;
4918
4919reporter_nest_cancel:
4920 nla_nest_end(msg, reporter_attr);
4921genlmsg_cancel:
4922 genlmsg_cancel(msg, hdr);
4923 return -EMSGSIZE;
4924}
4925
4926static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb,
4927 struct genl_info *info)
4928{
4929 struct devlink *devlink = info->user_ptr[0];
4930 struct devlink_health_reporter *reporter;
4931 struct sk_buff *msg;
4932 int err;
4933
4934 reporter = devlink_health_reporter_get_from_info(devlink, info);
4935 if (!reporter)
4936 return -EINVAL;
4937
4938 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4939 if (!msg) {
4940 err = -ENOMEM;
4941 goto out;
4942 }
4943
4944 err = devlink_nl_health_reporter_fill(msg, devlink, reporter,
4945 DEVLINK_CMD_HEALTH_REPORTER_GET,
4946 info->snd_portid, info->snd_seq,
4947 0);
4948 if (err) {
4949 nlmsg_free(msg);
4950 goto out;
4951 }
4952
4953 err = genlmsg_reply(msg, info);
4954out:
4955 devlink_health_reporter_put(reporter);
4956 return err;
4957}
4958
4959static int
4960devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg,
4961 struct netlink_callback *cb)
4962{
4963 struct devlink_health_reporter *reporter;
4964 struct devlink *devlink;
4965 int start = cb->args[0];
4966 int idx = 0;
4967 int err;
4968
4969 mutex_lock(&devlink_mutex);
4970 list_for_each_entry(devlink, &devlink_list, list) {
4971 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
4972 continue;
4973 mutex_lock(&devlink->reporters_lock);
4974 list_for_each_entry(reporter, &devlink->reporter_list,
4975 list) {
4976 if (idx < start) {
4977 idx++;
4978 continue;
4979 }
4980 err = devlink_nl_health_reporter_fill(msg, devlink,
4981 reporter,
4982 DEVLINK_CMD_HEALTH_REPORTER_GET,
4983 NETLINK_CB(cb->skb).portid,
4984 cb->nlh->nlmsg_seq,
4985 NLM_F_MULTI);
4986 if (err) {
4987 mutex_unlock(&devlink->reporters_lock);
4988 goto out;
4989 }
4990 idx++;
4991 }
4992 mutex_unlock(&devlink->reporters_lock);
4993 }
4994out:
4995 mutex_unlock(&devlink_mutex);
4996
4997 cb->args[0] = idx;
4998 return msg->len;
4999}
5000
5001static int
5002devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb,
5003 struct genl_info *info)
5004{
5005 struct devlink *devlink = info->user_ptr[0];
5006 struct devlink_health_reporter *reporter;
5007 int err;
5008
5009 reporter = devlink_health_reporter_get_from_info(devlink, info);
5010 if (!reporter)
5011 return -EINVAL;
5012
5013 if (!reporter->ops->recover &&
5014 (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] ||
5015 info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])) {
5016 err = -EOPNOTSUPP;
5017 goto out;
5018 }
5019
5020 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD])
5021 reporter->graceful_period =
5022 nla_get_u64(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]);
5023
5024 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])
5025 reporter->auto_recover =
5026 nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]);
5027
5028 devlink_health_reporter_put(reporter);
5029 return 0;
5030out:
5031 devlink_health_reporter_put(reporter);
5032 return err;
5033}
5034
5035static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb,
5036 struct genl_info *info)
5037{
5038 struct devlink *devlink = info->user_ptr[0];
5039 struct devlink_health_reporter *reporter;
5040 int err;
5041
5042 reporter = devlink_health_reporter_get_from_info(devlink, info);
5043 if (!reporter)
5044 return -EINVAL;
5045
5046 err = devlink_health_reporter_recover(reporter, NULL);
5047
5048 devlink_health_reporter_put(reporter);
5049 return err;
5050}
5051
5052static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb,
5053 struct genl_info *info)
5054{
5055 struct devlink *devlink = info->user_ptr[0];
5056 struct devlink_health_reporter *reporter;
5057 struct devlink_fmsg *fmsg;
5058 int err;
5059
5060 reporter = devlink_health_reporter_get_from_info(devlink, info);
5061 if (!reporter)
5062 return -EINVAL;
5063
5064 if (!reporter->ops->diagnose) {
5065 devlink_health_reporter_put(reporter);
5066 return -EOPNOTSUPP;
5067 }
5068
5069 fmsg = devlink_fmsg_alloc();
5070 if (!fmsg) {
5071 devlink_health_reporter_put(reporter);
5072 return -ENOMEM;
5073 }
5074
5075 err = devlink_fmsg_obj_nest_start(fmsg);
5076 if (err)
5077 goto out;
5078
5079 err = reporter->ops->diagnose(reporter, fmsg);
5080 if (err)
5081 goto out;
5082
5083 err = devlink_fmsg_obj_nest_end(fmsg);
5084 if (err)
5085 goto out;
5086
5087 err = devlink_fmsg_snd(fmsg, info,
5088 DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 0);
5089
5090out:
5091 devlink_fmsg_free(fmsg);
5092 devlink_health_reporter_put(reporter);
5093 return err;
5094}
5095
5096static int
5097devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb,
5098 struct netlink_callback *cb)
5099{
5100 struct devlink_health_reporter *reporter;
5101 u64 start = cb->args[0];
5102 int err;
5103
5104 reporter = devlink_health_reporter_get_from_cb(cb);
5105 if (!reporter)
5106 return -EINVAL;
5107
5108 if (!reporter->ops->dump) {
5109 err = -EOPNOTSUPP;
5110 goto out;
5111 }
5112 mutex_lock(&reporter->dump_lock);
5113 if (!start) {
5114 err = devlink_health_do_dump(reporter, NULL);
5115 if (err)
5116 goto unlock;
5117 cb->args[1] = reporter->dump_ts;
5118 }
5119 if (!reporter->dump_fmsg || cb->args[1] != reporter->dump_ts) {
5120 NL_SET_ERR_MSG_MOD(cb->extack, "Dump trampled, please retry");
5121 err = -EAGAIN;
5122 goto unlock;
5123 }
5124
5125 err = devlink_fmsg_dumpit(reporter->dump_fmsg, skb, cb,
5126 DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET);
5127unlock:
5128 mutex_unlock(&reporter->dump_lock);
5129out:
5130 devlink_health_reporter_put(reporter);
5131 return err;
5132}
5133
5134static int
5135devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb,
5136 struct genl_info *info)
5137{
5138 struct devlink *devlink = info->user_ptr[0];
5139 struct devlink_health_reporter *reporter;
5140
5141 reporter = devlink_health_reporter_get_from_info(devlink, info);
5142 if (!reporter)
5143 return -EINVAL;
5144
5145 if (!reporter->ops->dump) {
5146 devlink_health_reporter_put(reporter);
5147 return -EOPNOTSUPP;
5148 }
5149
5150 mutex_lock(&reporter->dump_lock);
5151 devlink_health_dump_clear(reporter);
5152 mutex_unlock(&reporter->dump_lock);
5153 devlink_health_reporter_put(reporter);
5154 return 0;
5155}
5156
5157static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
5158 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
5159 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
5160 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 },
5161 [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 },
5162 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 },
5163 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 },
5164 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 },
5165 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 },
5166 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 },
5167 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 },
5168 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 },
5169 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 },
5170 [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 },
5171 [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 },
5172 [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 },
5173 [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING },
5174 [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 },
5175 [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64},
5176 [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64},
5177 [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING },
5178 [DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 },
5179 [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 },
5180 [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING },
5181 [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 },
5182 [DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING },
5183 [DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] = { .type = NLA_U64 },
5184 [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER] = { .type = NLA_U8 },
5185 [DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME] = { .type = NLA_NUL_STRING },
5186 [DEVLINK_ATTR_FLASH_UPDATE_COMPONENT] = { .type = NLA_NUL_STRING },
5187};
5188
5189static const struct genl_ops devlink_nl_ops[] = {
5190 {
5191 .cmd = DEVLINK_CMD_GET,
5192 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5193 .doit = devlink_nl_cmd_get_doit,
5194 .dumpit = devlink_nl_cmd_get_dumpit,
5195 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5196 /* can be retrieved by unprivileged users */
5197 },
5198 {
5199 .cmd = DEVLINK_CMD_PORT_GET,
5200 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5201 .doit = devlink_nl_cmd_port_get_doit,
5202 .dumpit = devlink_nl_cmd_port_get_dumpit,
5203 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
5204 /* can be retrieved by unprivileged users */
5205 },
5206 {
5207 .cmd = DEVLINK_CMD_PORT_SET,
5208 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5209 .doit = devlink_nl_cmd_port_set_doit,
5210 .flags = GENL_ADMIN_PERM,
5211 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
5212 },
5213 {
5214 .cmd = DEVLINK_CMD_PORT_SPLIT,
5215 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5216 .doit = devlink_nl_cmd_port_split_doit,
5217 .flags = GENL_ADMIN_PERM,
5218 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5219 DEVLINK_NL_FLAG_NO_LOCK,
5220 },
5221 {
5222 .cmd = DEVLINK_CMD_PORT_UNSPLIT,
5223 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5224 .doit = devlink_nl_cmd_port_unsplit_doit,
5225 .flags = GENL_ADMIN_PERM,
5226 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5227 DEVLINK_NL_FLAG_NO_LOCK,
5228 },
5229 {
5230 .cmd = DEVLINK_CMD_SB_GET,
5231 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5232 .doit = devlink_nl_cmd_sb_get_doit,
5233 .dumpit = devlink_nl_cmd_sb_get_dumpit,
5234 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5235 DEVLINK_NL_FLAG_NEED_SB,
5236 /* can be retrieved by unprivileged users */
5237 },
5238 {
5239 .cmd = DEVLINK_CMD_SB_POOL_GET,
5240 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5241 .doit = devlink_nl_cmd_sb_pool_get_doit,
5242 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit,
5243 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5244 DEVLINK_NL_FLAG_NEED_SB,
5245 /* can be retrieved by unprivileged users */
5246 },
5247 {
5248 .cmd = DEVLINK_CMD_SB_POOL_SET,
5249 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5250 .doit = devlink_nl_cmd_sb_pool_set_doit,
5251 .flags = GENL_ADMIN_PERM,
5252 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5253 DEVLINK_NL_FLAG_NEED_SB,
5254 },
5255 {
5256 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET,
5257 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5258 .doit = devlink_nl_cmd_sb_port_pool_get_doit,
5259 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit,
5260 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5261 DEVLINK_NL_FLAG_NEED_SB,
5262 /* can be retrieved by unprivileged users */
5263 },
5264 {
5265 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET,
5266 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5267 .doit = devlink_nl_cmd_sb_port_pool_set_doit,
5268 .flags = GENL_ADMIN_PERM,
5269 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5270 DEVLINK_NL_FLAG_NEED_SB,
5271 },
5272 {
5273 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET,
5274 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5275 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit,
5276 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit,
5277 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5278 DEVLINK_NL_FLAG_NEED_SB,
5279 /* can be retrieved by unprivileged users */
5280 },
5281 {
5282 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET,
5283 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5284 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit,
5285 .flags = GENL_ADMIN_PERM,
5286 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
5287 DEVLINK_NL_FLAG_NEED_SB,
5288 },
5289 {
5290 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT,
5291 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5292 .doit = devlink_nl_cmd_sb_occ_snapshot_doit,
5293 .flags = GENL_ADMIN_PERM,
5294 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5295 DEVLINK_NL_FLAG_NEED_SB,
5296 },
5297 {
5298 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR,
5299 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5300 .doit = devlink_nl_cmd_sb_occ_max_clear_doit,
5301 .flags = GENL_ADMIN_PERM,
5302 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5303 DEVLINK_NL_FLAG_NEED_SB,
5304 },
5305 {
5306 .cmd = DEVLINK_CMD_ESWITCH_GET,
5307 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5308 .doit = devlink_nl_cmd_eswitch_get_doit,
5309 .flags = GENL_ADMIN_PERM,
5310 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5311 },
5312 {
5313 .cmd = DEVLINK_CMD_ESWITCH_SET,
5314 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5315 .doit = devlink_nl_cmd_eswitch_set_doit,
5316 .flags = GENL_ADMIN_PERM,
5317 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5318 DEVLINK_NL_FLAG_NO_LOCK,
5319 },
5320 {
5321 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET,
5322 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5323 .doit = devlink_nl_cmd_dpipe_table_get,
5324 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5325 /* can be retrieved by unprivileged users */
5326 },
5327 {
5328 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET,
5329 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5330 .doit = devlink_nl_cmd_dpipe_entries_get,
5331 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5332 /* can be retrieved by unprivileged users */
5333 },
5334 {
5335 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET,
5336 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5337 .doit = devlink_nl_cmd_dpipe_headers_get,
5338 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5339 /* can be retrieved by unprivileged users */
5340 },
5341 {
5342 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET,
5343 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5344 .doit = devlink_nl_cmd_dpipe_table_counters_set,
5345 .flags = GENL_ADMIN_PERM,
5346 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5347 },
5348 {
5349 .cmd = DEVLINK_CMD_RESOURCE_SET,
5350 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5351 .doit = devlink_nl_cmd_resource_set,
5352 .flags = GENL_ADMIN_PERM,
5353 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5354 },
5355 {
5356 .cmd = DEVLINK_CMD_RESOURCE_DUMP,
5357 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5358 .doit = devlink_nl_cmd_resource_dump,
5359 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5360 /* can be retrieved by unprivileged users */
5361 },
5362 {
5363 .cmd = DEVLINK_CMD_RELOAD,
5364 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5365 .doit = devlink_nl_cmd_reload,
5366 .flags = GENL_ADMIN_PERM,
5367 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5368 DEVLINK_NL_FLAG_NO_LOCK,
5369 },
5370 {
5371 .cmd = DEVLINK_CMD_PARAM_GET,
5372 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5373 .doit = devlink_nl_cmd_param_get_doit,
5374 .dumpit = devlink_nl_cmd_param_get_dumpit,
5375 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5376 /* can be retrieved by unprivileged users */
5377 },
5378 {
5379 .cmd = DEVLINK_CMD_PARAM_SET,
5380 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5381 .doit = devlink_nl_cmd_param_set_doit,
5382 .flags = GENL_ADMIN_PERM,
5383 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5384 },
5385 {
5386 .cmd = DEVLINK_CMD_PORT_PARAM_GET,
5387 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5388 .doit = devlink_nl_cmd_port_param_get_doit,
5389 .dumpit = devlink_nl_cmd_port_param_get_dumpit,
5390 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
5391 /* can be retrieved by unprivileged users */
5392 },
5393 {
5394 .cmd = DEVLINK_CMD_PORT_PARAM_SET,
5395 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5396 .doit = devlink_nl_cmd_port_param_set_doit,
5397 .flags = GENL_ADMIN_PERM,
5398 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
5399 },
5400 {
5401 .cmd = DEVLINK_CMD_REGION_GET,
5402 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5403 .doit = devlink_nl_cmd_region_get_doit,
5404 .dumpit = devlink_nl_cmd_region_get_dumpit,
5405 .flags = GENL_ADMIN_PERM,
5406 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5407 },
5408 {
5409 .cmd = DEVLINK_CMD_REGION_DEL,
5410 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5411 .doit = devlink_nl_cmd_region_del,
5412 .flags = GENL_ADMIN_PERM,
5413 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5414 },
5415 {
5416 .cmd = DEVLINK_CMD_REGION_READ,
5417 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5418 .dumpit = devlink_nl_cmd_region_read_dumpit,
5419 .flags = GENL_ADMIN_PERM,
5420 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5421 },
5422 {
5423 .cmd = DEVLINK_CMD_INFO_GET,
5424 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5425 .doit = devlink_nl_cmd_info_get_doit,
5426 .dumpit = devlink_nl_cmd_info_get_dumpit,
5427 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5428 /* can be retrieved by unprivileged users */
5429 },
5430 {
5431 .cmd = DEVLINK_CMD_HEALTH_REPORTER_GET,
5432 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5433 .doit = devlink_nl_cmd_health_reporter_get_doit,
5434 .dumpit = devlink_nl_cmd_health_reporter_get_dumpit,
5435 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5436 DEVLINK_NL_FLAG_NO_LOCK,
5437 /* can be retrieved by unprivileged users */
5438 },
5439 {
5440 .cmd = DEVLINK_CMD_HEALTH_REPORTER_SET,
5441 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5442 .doit = devlink_nl_cmd_health_reporter_set_doit,
5443 .flags = GENL_ADMIN_PERM,
5444 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5445 DEVLINK_NL_FLAG_NO_LOCK,
5446 },
5447 {
5448 .cmd = DEVLINK_CMD_HEALTH_REPORTER_RECOVER,
5449 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5450 .doit = devlink_nl_cmd_health_reporter_recover_doit,
5451 .flags = GENL_ADMIN_PERM,
5452 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5453 DEVLINK_NL_FLAG_NO_LOCK,
5454 },
5455 {
5456 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE,
5457 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5458 .doit = devlink_nl_cmd_health_reporter_diagnose_doit,
5459 .flags = GENL_ADMIN_PERM,
5460 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5461 DEVLINK_NL_FLAG_NO_LOCK,
5462 },
5463 {
5464 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET,
5465 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5466 .dumpit = devlink_nl_cmd_health_reporter_dump_get_dumpit,
5467 .flags = GENL_ADMIN_PERM,
5468 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5469 DEVLINK_NL_FLAG_NO_LOCK,
5470 },
5471 {
5472 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR,
5473 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5474 .doit = devlink_nl_cmd_health_reporter_dump_clear_doit,
5475 .flags = GENL_ADMIN_PERM,
5476 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
5477 DEVLINK_NL_FLAG_NO_LOCK,
5478 },
5479 {
5480 .cmd = DEVLINK_CMD_FLASH_UPDATE,
5481 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
5482 .doit = devlink_nl_cmd_flash_update,
5483 .flags = GENL_ADMIN_PERM,
5484 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
5485 },
5486};
5487
5488static struct genl_family devlink_nl_family __ro_after_init = {
5489 .name = DEVLINK_GENL_NAME,
5490 .version = DEVLINK_GENL_VERSION,
5491 .maxattr = DEVLINK_ATTR_MAX,
5492 .policy = devlink_nl_policy,
5493 .netnsok = true,
5494 .pre_doit = devlink_nl_pre_doit,
5495 .post_doit = devlink_nl_post_doit,
5496 .module = THIS_MODULE,
5497 .ops = devlink_nl_ops,
5498 .n_ops = ARRAY_SIZE(devlink_nl_ops),
5499 .mcgrps = devlink_nl_mcgrps,
5500 .n_mcgrps = ARRAY_SIZE(devlink_nl_mcgrps),
5501};
5502
5503/**
5504 * devlink_alloc - Allocate new devlink instance resources
5505 *
5506 * @ops: ops
5507 * @priv_size: size of user private data
5508 *
5509 * Allocate new devlink instance resources, including devlink index
5510 * and name.
5511 */
5512struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
5513{
5514 struct devlink *devlink;
5515
5516 if (WARN_ON(!ops))
5517 return NULL;
5518
5519 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL);
5520 if (!devlink)
5521 return NULL;
5522 devlink->ops = ops;
5523 devlink_net_set(devlink, &init_net);
5524 INIT_LIST_HEAD(&devlink->port_list);
5525 INIT_LIST_HEAD(&devlink->sb_list);
5526 INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list);
5527 INIT_LIST_HEAD(&devlink->resource_list);
5528 INIT_LIST_HEAD(&devlink->param_list);
5529 INIT_LIST_HEAD(&devlink->region_list);
5530 INIT_LIST_HEAD(&devlink->reporter_list);
5531 mutex_init(&devlink->lock);
5532 mutex_init(&devlink->reporters_lock);
5533 return devlink;
5534}
5535EXPORT_SYMBOL_GPL(devlink_alloc);
5536
5537/**
5538 * devlink_register - Register devlink instance
5539 *
5540 * @devlink: devlink
5541 * @dev: parent device
5542 */
5543int devlink_register(struct devlink *devlink, struct device *dev)
5544{
5545 mutex_lock(&devlink_mutex);
5546 devlink->dev = dev;
5547 list_add_tail(&devlink->list, &devlink_list);
5548 devlink_notify(devlink, DEVLINK_CMD_NEW);
5549 mutex_unlock(&devlink_mutex);
5550 return 0;
5551}
5552EXPORT_SYMBOL_GPL(devlink_register);
5553
5554/**
5555 * devlink_unregister - Unregister devlink instance
5556 *
5557 * @devlink: devlink
5558 */
5559void devlink_unregister(struct devlink *devlink)
5560{
5561 mutex_lock(&devlink_mutex);
5562 devlink_notify(devlink, DEVLINK_CMD_DEL);
5563 list_del(&devlink->list);
5564 mutex_unlock(&devlink_mutex);
5565}
5566EXPORT_SYMBOL_GPL(devlink_unregister);
5567
5568/**
5569 * devlink_free - Free devlink instance resources
5570 *
5571 * @devlink: devlink
5572 */
5573void devlink_free(struct devlink *devlink)
5574{
5575 mutex_destroy(&devlink->reporters_lock);
5576 mutex_destroy(&devlink->lock);
5577 WARN_ON(!list_empty(&devlink->reporter_list));
5578 WARN_ON(!list_empty(&devlink->region_list));
5579 WARN_ON(!list_empty(&devlink->param_list));
5580 WARN_ON(!list_empty(&devlink->resource_list));
5581 WARN_ON(!list_empty(&devlink->dpipe_table_list));
5582 WARN_ON(!list_empty(&devlink->sb_list));
5583 WARN_ON(!list_empty(&devlink->port_list));
5584
5585 kfree(devlink);
5586}
5587EXPORT_SYMBOL_GPL(devlink_free);
5588
5589static void devlink_port_type_warn(struct work_struct *work)
5590{
5591 WARN(true, "Type was not set for devlink port.");
5592}
5593
5594static bool devlink_port_type_should_warn(struct devlink_port *devlink_port)
5595{
5596 /* Ignore CPU and DSA flavours. */
5597 return devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_CPU &&
5598 devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_DSA;
5599}
5600
5601#define DEVLINK_PORT_TYPE_WARN_TIMEOUT (HZ * 30)
5602
5603static void devlink_port_type_warn_schedule(struct devlink_port *devlink_port)
5604{
5605 if (!devlink_port_type_should_warn(devlink_port))
5606 return;
5607 /* Schedule a work to WARN in case driver does not set port
5608 * type within timeout.
5609 */
5610 schedule_delayed_work(&devlink_port->type_warn_dw,
5611 DEVLINK_PORT_TYPE_WARN_TIMEOUT);
5612}
5613
5614static void devlink_port_type_warn_cancel(struct devlink_port *devlink_port)
5615{
5616 if (!devlink_port_type_should_warn(devlink_port))
5617 return;
5618 cancel_delayed_work_sync(&devlink_port->type_warn_dw);
5619}
5620
5621/**
5622 * devlink_port_register - Register devlink port
5623 *
5624 * @devlink: devlink
5625 * @devlink_port: devlink port
5626 * @port_index: driver-specific numerical identifier of the port
5627 *
5628 * Register devlink port with provided port index. User can use
5629 * any indexing, even hw-related one. devlink_port structure
5630 * is convenient to be embedded inside user driver private structure.
5631 * Note that the caller should take care of zeroing the devlink_port
5632 * structure.
5633 */
5634int devlink_port_register(struct devlink *devlink,
5635 struct devlink_port *devlink_port,
5636 unsigned int port_index)
5637{
5638 mutex_lock(&devlink->lock);
5639 if (devlink_port_index_exists(devlink, port_index)) {
5640 mutex_unlock(&devlink->lock);
5641 return -EEXIST;
5642 }
5643 devlink_port->devlink = devlink;
5644 devlink_port->index = port_index;
5645 devlink_port->registered = true;
5646 spin_lock_init(&devlink_port->type_lock);
5647 list_add_tail(&devlink_port->list, &devlink->port_list);
5648 INIT_LIST_HEAD(&devlink_port->param_list);
5649 mutex_unlock(&devlink->lock);
5650 INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn);
5651 devlink_port_type_warn_schedule(devlink_port);
5652 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
5653 return 0;
5654}
5655EXPORT_SYMBOL_GPL(devlink_port_register);
5656
5657/**
5658 * devlink_port_unregister - Unregister devlink port
5659 *
5660 * @devlink_port: devlink port
5661 */
5662void devlink_port_unregister(struct devlink_port *devlink_port)
5663{
5664 struct devlink *devlink = devlink_port->devlink;
5665
5666 devlink_port_type_warn_cancel(devlink_port);
5667 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
5668 mutex_lock(&devlink->lock);
5669 list_del(&devlink_port->list);
5670 mutex_unlock(&devlink->lock);
5671}
5672EXPORT_SYMBOL_GPL(devlink_port_unregister);
5673
5674static void __devlink_port_type_set(struct devlink_port *devlink_port,
5675 enum devlink_port_type type,
5676 void *type_dev)
5677{
5678 if (WARN_ON(!devlink_port->registered))
5679 return;
5680 devlink_port_type_warn_cancel(devlink_port);
5681 spin_lock(&devlink_port->type_lock);
5682 devlink_port->type = type;
5683 devlink_port->type_dev = type_dev;
5684 spin_unlock(&devlink_port->type_lock);
5685 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
5686}
5687
5688/**
5689 * devlink_port_type_eth_set - Set port type to Ethernet
5690 *
5691 * @devlink_port: devlink port
5692 * @netdev: related netdevice
5693 */
5694void devlink_port_type_eth_set(struct devlink_port *devlink_port,
5695 struct net_device *netdev)
5696{
5697 const struct net_device_ops *ops = netdev->netdev_ops;
5698
5699 /* If driver registers devlink port, it should set devlink port
5700 * attributes accordingly so the compat functions are called
5701 * and the original ops are not used.
5702 */
5703 if (ops->ndo_get_phys_port_name) {
5704 /* Some drivers use the same set of ndos for netdevs
5705 * that have devlink_port registered and also for
5706 * those who don't. Make sure that ndo_get_phys_port_name
5707 * returns -EOPNOTSUPP here in case it is defined.
5708 * Warn if not.
5709 */
5710 char name[IFNAMSIZ];
5711 int err;
5712
5713 err = ops->ndo_get_phys_port_name(netdev, name, sizeof(name));
5714 WARN_ON(err != -EOPNOTSUPP);
5715 }
5716 if (ops->ndo_get_port_parent_id) {
5717 /* Some drivers use the same set of ndos for netdevs
5718 * that have devlink_port registered and also for
5719 * those who don't. Make sure that ndo_get_port_parent_id
5720 * returns -EOPNOTSUPP here in case it is defined.
5721 * Warn if not.
5722 */
5723 struct netdev_phys_item_id ppid;
5724 int err;
5725
5726 err = ops->ndo_get_port_parent_id(netdev, &ppid);
5727 WARN_ON(err != -EOPNOTSUPP);
5728 }
5729 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, netdev);
5730}
5731EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
5732
5733/**
5734 * devlink_port_type_ib_set - Set port type to InfiniBand
5735 *
5736 * @devlink_port: devlink port
5737 * @ibdev: related IB device
5738 */
5739void devlink_port_type_ib_set(struct devlink_port *devlink_port,
5740 struct ib_device *ibdev)
5741{
5742 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_IB, ibdev);
5743}
5744EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
5745
5746/**
5747 * devlink_port_type_clear - Clear port type
5748 *
5749 * @devlink_port: devlink port
5750 */
5751void devlink_port_type_clear(struct devlink_port *devlink_port)
5752{
5753 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL);
5754 devlink_port_type_warn_schedule(devlink_port);
5755}
5756EXPORT_SYMBOL_GPL(devlink_port_type_clear);
5757
5758static int __devlink_port_attrs_set(struct devlink_port *devlink_port,
5759 enum devlink_port_flavour flavour,
5760 const unsigned char *switch_id,
5761 unsigned char switch_id_len)
5762{
5763 struct devlink_port_attrs *attrs = &devlink_port->attrs;
5764
5765 if (WARN_ON(devlink_port->registered))
5766 return -EEXIST;
5767 attrs->set = true;
5768 attrs->flavour = flavour;
5769 if (switch_id) {
5770 attrs->switch_port = true;
5771 if (WARN_ON(switch_id_len > MAX_PHYS_ITEM_ID_LEN))
5772 switch_id_len = MAX_PHYS_ITEM_ID_LEN;
5773 memcpy(attrs->switch_id.id, switch_id, switch_id_len);
5774 attrs->switch_id.id_len = switch_id_len;
5775 } else {
5776 attrs->switch_port = false;
5777 }
5778 return 0;
5779}
5780
5781/**
5782 * devlink_port_attrs_set - Set port attributes
5783 *
5784 * @devlink_port: devlink port
5785 * @flavour: flavour of the port
5786 * @port_number: number of the port that is facing user, for example
5787 * the front panel port number
5788 * @split: indicates if this is split port
5789 * @split_subport_number: if the port is split, this is the number
5790 * of subport.
5791 * @switch_id: if the port is part of switch, this is buffer with ID,
5792 * otwerwise this is NULL
5793 * @switch_id_len: length of the switch_id buffer
5794 */
5795void devlink_port_attrs_set(struct devlink_port *devlink_port,
5796 enum devlink_port_flavour flavour,
5797 u32 port_number, bool split,
5798 u32 split_subport_number,
5799 const unsigned char *switch_id,
5800 unsigned char switch_id_len)
5801{
5802 struct devlink_port_attrs *attrs = &devlink_port->attrs;
5803 int ret;
5804
5805 ret = __devlink_port_attrs_set(devlink_port, flavour,
5806 switch_id, switch_id_len);
5807 if (ret)
5808 return;
5809 attrs->split = split;
5810 attrs->phys.port_number = port_number;
5811 attrs->phys.split_subport_number = split_subport_number;
5812}
5813EXPORT_SYMBOL_GPL(devlink_port_attrs_set);
5814
5815/**
5816 * devlink_port_attrs_pci_pf_set - Set PCI PF port attributes
5817 *
5818 * @devlink_port: devlink port
5819 * @pf: associated PF for the devlink port instance
5820 * @switch_id: if the port is part of switch, this is buffer with ID,
5821 * otherwise this is NULL
5822 * @switch_id_len: length of the switch_id buffer
5823 */
5824void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port,
5825 const unsigned char *switch_id,
5826 unsigned char switch_id_len, u16 pf)
5827{
5828 struct devlink_port_attrs *attrs = &devlink_port->attrs;
5829 int ret;
5830
5831 ret = __devlink_port_attrs_set(devlink_port,
5832 DEVLINK_PORT_FLAVOUR_PCI_PF,
5833 switch_id, switch_id_len);
5834 if (ret)
5835 return;
5836
5837 attrs->pci_pf.pf = pf;
5838}
5839EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_pf_set);
5840
5841/**
5842 * devlink_port_attrs_pci_vf_set - Set PCI VF port attributes
5843 *
5844 * @devlink_port: devlink port
5845 * @pf: associated PF for the devlink port instance
5846 * @vf: associated VF of a PF for the devlink port instance
5847 * @switch_id: if the port is part of switch, this is buffer with ID,
5848 * otherwise this is NULL
5849 * @switch_id_len: length of the switch_id buffer
5850 */
5851void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port,
5852 const unsigned char *switch_id,
5853 unsigned char switch_id_len,
5854 u16 pf, u16 vf)
5855{
5856 struct devlink_port_attrs *attrs = &devlink_port->attrs;
5857 int ret;
5858
5859 ret = __devlink_port_attrs_set(devlink_port,
5860 DEVLINK_PORT_FLAVOUR_PCI_VF,
5861 switch_id, switch_id_len);
5862 if (ret)
5863 return;
5864 attrs->pci_vf.pf = pf;
5865 attrs->pci_vf.vf = vf;
5866}
5867EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_vf_set);
5868
5869static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port,
5870 char *name, size_t len)
5871{
5872 struct devlink_port_attrs *attrs = &devlink_port->attrs;
5873 int n = 0;
5874
5875 if (!attrs->set)
5876 return -EOPNOTSUPP;
5877
5878 switch (attrs->flavour) {
5879 case DEVLINK_PORT_FLAVOUR_PHYSICAL:
5880 if (!attrs->split)
5881 n = snprintf(name, len, "p%u", attrs->phys.port_number);
5882 else
5883 n = snprintf(name, len, "p%us%u",
5884 attrs->phys.port_number,
5885 attrs->phys.split_subport_number);
5886 break;
5887 case DEVLINK_PORT_FLAVOUR_CPU:
5888 case DEVLINK_PORT_FLAVOUR_DSA:
5889 /* As CPU and DSA ports do not have a netdevice associated
5890 * case should not ever happen.
5891 */
5892 WARN_ON(1);
5893 return -EINVAL;
5894 case DEVLINK_PORT_FLAVOUR_PCI_PF:
5895 n = snprintf(name, len, "pf%u", attrs->pci_pf.pf);
5896 break;
5897 case DEVLINK_PORT_FLAVOUR_PCI_VF:
5898 n = snprintf(name, len, "pf%uvf%u",
5899 attrs->pci_vf.pf, attrs->pci_vf.vf);
5900 break;
5901 }
5902
5903 if (n >= len)
5904 return -EINVAL;
5905
5906 return 0;
5907}
5908
5909int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
5910 u32 size, u16 ingress_pools_count,
5911 u16 egress_pools_count, u16 ingress_tc_count,
5912 u16 egress_tc_count)
5913{
5914 struct devlink_sb *devlink_sb;
5915 int err = 0;
5916
5917 mutex_lock(&devlink->lock);
5918 if (devlink_sb_index_exists(devlink, sb_index)) {
5919 err = -EEXIST;
5920 goto unlock;
5921 }
5922
5923 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL);
5924 if (!devlink_sb) {
5925 err = -ENOMEM;
5926 goto unlock;
5927 }
5928 devlink_sb->index = sb_index;
5929 devlink_sb->size = size;
5930 devlink_sb->ingress_pools_count = ingress_pools_count;
5931 devlink_sb->egress_pools_count = egress_pools_count;
5932 devlink_sb->ingress_tc_count = ingress_tc_count;
5933 devlink_sb->egress_tc_count = egress_tc_count;
5934 list_add_tail(&devlink_sb->list, &devlink->sb_list);
5935unlock:
5936 mutex_unlock(&devlink->lock);
5937 return err;
5938}
5939EXPORT_SYMBOL_GPL(devlink_sb_register);
5940
5941void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index)
5942{
5943 struct devlink_sb *devlink_sb;
5944
5945 mutex_lock(&devlink->lock);
5946 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
5947 WARN_ON(!devlink_sb);
5948 list_del(&devlink_sb->list);
5949 mutex_unlock(&devlink->lock);
5950 kfree(devlink_sb);
5951}
5952EXPORT_SYMBOL_GPL(devlink_sb_unregister);
5953
5954/**
5955 * devlink_dpipe_headers_register - register dpipe headers
5956 *
5957 * @devlink: devlink
5958 * @dpipe_headers: dpipe header array
5959 *
5960 * Register the headers supported by hardware.
5961 */
5962int devlink_dpipe_headers_register(struct devlink *devlink,
5963 struct devlink_dpipe_headers *dpipe_headers)
5964{
5965 mutex_lock(&devlink->lock);
5966 devlink->dpipe_headers = dpipe_headers;
5967 mutex_unlock(&devlink->lock);
5968 return 0;
5969}
5970EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register);
5971
5972/**
5973 * devlink_dpipe_headers_unregister - unregister dpipe headers
5974 *
5975 * @devlink: devlink
5976 *
5977 * Unregister the headers supported by hardware.
5978 */
5979void devlink_dpipe_headers_unregister(struct devlink *devlink)
5980{
5981 mutex_lock(&devlink->lock);
5982 devlink->dpipe_headers = NULL;
5983 mutex_unlock(&devlink->lock);
5984}
5985EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister);
5986
5987/**
5988 * devlink_dpipe_table_counter_enabled - check if counter allocation
5989 * required
5990 * @devlink: devlink
5991 * @table_name: tables name
5992 *
5993 * Used by driver to check if counter allocation is required.
5994 * After counter allocation is turned on the table entries
5995 * are updated to include counter statistics.
5996 *
5997 * After that point on the driver must respect the counter
5998 * state so that each entry added to the table is added
5999 * with a counter.
6000 */
6001bool devlink_dpipe_table_counter_enabled(struct devlink *devlink,
6002 const char *table_name)
6003{
6004 struct devlink_dpipe_table *table;
6005 bool enabled;
6006
6007 rcu_read_lock();
6008 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
6009 table_name);
6010 enabled = false;
6011 if (table)
6012 enabled = table->counters_enabled;
6013 rcu_read_unlock();
6014 return enabled;
6015}
6016EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled);
6017
6018/**
6019 * devlink_dpipe_table_register - register dpipe table
6020 *
6021 * @devlink: devlink
6022 * @table_name: table name
6023 * @table_ops: table ops
6024 * @priv: priv
6025 * @counter_control_extern: external control for counters
6026 */
6027int devlink_dpipe_table_register(struct devlink *devlink,
6028 const char *table_name,
6029 struct devlink_dpipe_table_ops *table_ops,
6030 void *priv, bool counter_control_extern)
6031{
6032 struct devlink_dpipe_table *table;
6033
6034 if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name))
6035 return -EEXIST;
6036
6037 if (WARN_ON(!table_ops->size_get))
6038 return -EINVAL;
6039
6040 table = kzalloc(sizeof(*table), GFP_KERNEL);
6041 if (!table)
6042 return -ENOMEM;
6043
6044 table->name = table_name;
6045 table->table_ops = table_ops;
6046 table->priv = priv;
6047 table->counter_control_extern = counter_control_extern;
6048
6049 mutex_lock(&devlink->lock);
6050 list_add_tail_rcu(&table->list, &devlink->dpipe_table_list);
6051 mutex_unlock(&devlink->lock);
6052 return 0;
6053}
6054EXPORT_SYMBOL_GPL(devlink_dpipe_table_register);
6055
6056/**
6057 * devlink_dpipe_table_unregister - unregister dpipe table
6058 *
6059 * @devlink: devlink
6060 * @table_name: table name
6061 */
6062void devlink_dpipe_table_unregister(struct devlink *devlink,
6063 const char *table_name)
6064{
6065 struct devlink_dpipe_table *table;
6066
6067 mutex_lock(&devlink->lock);
6068 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
6069 table_name);
6070 if (!table)
6071 goto unlock;
6072 list_del_rcu(&table->list);
6073 mutex_unlock(&devlink->lock);
6074 kfree_rcu(table, rcu);
6075 return;
6076unlock:
6077 mutex_unlock(&devlink->lock);
6078}
6079EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister);
6080
6081/**
6082 * devlink_resource_register - devlink resource register
6083 *
6084 * @devlink: devlink
6085 * @resource_name: resource's name
6086 * @resource_size: resource's size
6087 * @resource_id: resource's id
6088 * @parent_resource_id: resource's parent id
6089 * @size_params: size parameters
6090 */
6091int devlink_resource_register(struct devlink *devlink,
6092 const char *resource_name,
6093 u64 resource_size,
6094 u64 resource_id,
6095 u64 parent_resource_id,
6096 const struct devlink_resource_size_params *size_params)
6097{
6098 struct devlink_resource *resource;
6099 struct list_head *resource_list;
6100 bool top_hierarchy;
6101 int err = 0;
6102
6103 top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP;
6104
6105 mutex_lock(&devlink->lock);
6106 resource = devlink_resource_find(devlink, NULL, resource_id);
6107 if (resource) {
6108 err = -EINVAL;
6109 goto out;
6110 }
6111
6112 resource = kzalloc(sizeof(*resource), GFP_KERNEL);
6113 if (!resource) {
6114 err = -ENOMEM;
6115 goto out;
6116 }
6117
6118 if (top_hierarchy) {
6119 resource_list = &devlink->resource_list;
6120 } else {
6121 struct devlink_resource *parent_resource;
6122
6123 parent_resource = devlink_resource_find(devlink, NULL,
6124 parent_resource_id);
6125 if (parent_resource) {
6126 resource_list = &parent_resource->resource_list;
6127 resource->parent = parent_resource;
6128 } else {
6129 kfree(resource);
6130 err = -EINVAL;
6131 goto out;
6132 }
6133 }
6134
6135 resource->name = resource_name;
6136 resource->size = resource_size;
6137 resource->size_new = resource_size;
6138 resource->id = resource_id;
6139 resource->size_valid = true;
6140 memcpy(&resource->size_params, size_params,
6141 sizeof(resource->size_params));
6142 INIT_LIST_HEAD(&resource->resource_list);
6143 list_add_tail(&resource->list, resource_list);
6144out:
6145 mutex_unlock(&devlink->lock);
6146 return err;
6147}
6148EXPORT_SYMBOL_GPL(devlink_resource_register);
6149
6150/**
6151 * devlink_resources_unregister - free all resources
6152 *
6153 * @devlink: devlink
6154 * @resource: resource
6155 */
6156void devlink_resources_unregister(struct devlink *devlink,
6157 struct devlink_resource *resource)
6158{
6159 struct devlink_resource *tmp, *child_resource;
6160 struct list_head *resource_list;
6161
6162 if (resource)
6163 resource_list = &resource->resource_list;
6164 else
6165 resource_list = &devlink->resource_list;
6166
6167 if (!resource)
6168 mutex_lock(&devlink->lock);
6169
6170 list_for_each_entry_safe(child_resource, tmp, resource_list, list) {
6171 devlink_resources_unregister(devlink, child_resource);
6172 list_del(&child_resource->list);
6173 kfree(child_resource);
6174 }
6175
6176 if (!resource)
6177 mutex_unlock(&devlink->lock);
6178}
6179EXPORT_SYMBOL_GPL(devlink_resources_unregister);
6180
6181/**
6182 * devlink_resource_size_get - get and update size
6183 *
6184 * @devlink: devlink
6185 * @resource_id: the requested resource id
6186 * @p_resource_size: ptr to update
6187 */
6188int devlink_resource_size_get(struct devlink *devlink,
6189 u64 resource_id,
6190 u64 *p_resource_size)
6191{
6192 struct devlink_resource *resource;
6193 int err = 0;
6194
6195 mutex_lock(&devlink->lock);
6196 resource = devlink_resource_find(devlink, NULL, resource_id);
6197 if (!resource) {
6198 err = -EINVAL;
6199 goto out;
6200 }
6201 *p_resource_size = resource->size_new;
6202 resource->size = resource->size_new;
6203out:
6204 mutex_unlock(&devlink->lock);
6205 return err;
6206}
6207EXPORT_SYMBOL_GPL(devlink_resource_size_get);
6208
6209/**
6210 * devlink_dpipe_table_resource_set - set the resource id
6211 *
6212 * @devlink: devlink
6213 * @table_name: table name
6214 * @resource_id: resource id
6215 * @resource_units: number of resource's units consumed per table's entry
6216 */
6217int devlink_dpipe_table_resource_set(struct devlink *devlink,
6218 const char *table_name, u64 resource_id,
6219 u64 resource_units)
6220{
6221 struct devlink_dpipe_table *table;
6222 int err = 0;
6223
6224 mutex_lock(&devlink->lock);
6225 table = devlink_dpipe_table_find(&devlink->dpipe_table_list,
6226 table_name);
6227 if (!table) {
6228 err = -EINVAL;
6229 goto out;
6230 }
6231 table->resource_id = resource_id;
6232 table->resource_units = resource_units;
6233 table->resource_valid = true;
6234out:
6235 mutex_unlock(&devlink->lock);
6236 return err;
6237}
6238EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set);
6239
6240/**
6241 * devlink_resource_occ_get_register - register occupancy getter
6242 *
6243 * @devlink: devlink
6244 * @resource_id: resource id
6245 * @occ_get: occupancy getter callback
6246 * @occ_get_priv: occupancy getter callback priv
6247 */
6248void devlink_resource_occ_get_register(struct devlink *devlink,
6249 u64 resource_id,
6250 devlink_resource_occ_get_t *occ_get,
6251 void *occ_get_priv)
6252{
6253 struct devlink_resource *resource;
6254
6255 mutex_lock(&devlink->lock);
6256 resource = devlink_resource_find(devlink, NULL, resource_id);
6257 if (WARN_ON(!resource))
6258 goto out;
6259 WARN_ON(resource->occ_get);
6260
6261 resource->occ_get = occ_get;
6262 resource->occ_get_priv = occ_get_priv;
6263out:
6264 mutex_unlock(&devlink->lock);
6265}
6266EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register);
6267
6268/**
6269 * devlink_resource_occ_get_unregister - unregister occupancy getter
6270 *
6271 * @devlink: devlink
6272 * @resource_id: resource id
6273 */
6274void devlink_resource_occ_get_unregister(struct devlink *devlink,
6275 u64 resource_id)
6276{
6277 struct devlink_resource *resource;
6278
6279 mutex_lock(&devlink->lock);
6280 resource = devlink_resource_find(devlink, NULL, resource_id);
6281 if (WARN_ON(!resource))
6282 goto out;
6283 WARN_ON(!resource->occ_get);
6284
6285 resource->occ_get = NULL;
6286 resource->occ_get_priv = NULL;
6287out:
6288 mutex_unlock(&devlink->lock);
6289}
6290EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister);
6291
6292static int devlink_param_verify(const struct devlink_param *param)
6293{
6294 if (!param || !param->name || !param->supported_cmodes)
6295 return -EINVAL;
6296 if (param->generic)
6297 return devlink_param_generic_verify(param);
6298 else
6299 return devlink_param_driver_verify(param);
6300}
6301
6302static int __devlink_params_register(struct devlink *devlink,
6303 unsigned int port_index,
6304 struct list_head *param_list,
6305 const struct devlink_param *params,
6306 size_t params_count,
6307 enum devlink_command reg_cmd,
6308 enum devlink_command unreg_cmd)
6309{
6310 const struct devlink_param *param = params;
6311 int i;
6312 int err;
6313
6314 mutex_lock(&devlink->lock);
6315 for (i = 0; i < params_count; i++, param++) {
6316 err = devlink_param_verify(param);
6317 if (err)
6318 goto rollback;
6319
6320 err = devlink_param_register_one(devlink, port_index,
6321 param_list, param, reg_cmd);
6322 if (err)
6323 goto rollback;
6324 }
6325
6326 mutex_unlock(&devlink->lock);
6327 return 0;
6328
6329rollback:
6330 if (!i)
6331 goto unlock;
6332 for (param--; i > 0; i--, param--)
6333 devlink_param_unregister_one(devlink, port_index, param_list,
6334 param, unreg_cmd);
6335unlock:
6336 mutex_unlock(&devlink->lock);
6337 return err;
6338}
6339
6340static void __devlink_params_unregister(struct devlink *devlink,
6341 unsigned int port_index,
6342 struct list_head *param_list,
6343 const struct devlink_param *params,
6344 size_t params_count,
6345 enum devlink_command cmd)
6346{
6347 const struct devlink_param *param = params;
6348 int i;
6349
6350 mutex_lock(&devlink->lock);
6351 for (i = 0; i < params_count; i++, param++)
6352 devlink_param_unregister_one(devlink, 0, param_list, param,
6353 cmd);
6354 mutex_unlock(&devlink->lock);
6355}
6356
6357/**
6358 * devlink_params_register - register configuration parameters
6359 *
6360 * @devlink: devlink
6361 * @params: configuration parameters array
6362 * @params_count: number of parameters provided
6363 *
6364 * Register the configuration parameters supported by the driver.
6365 */
6366int devlink_params_register(struct devlink *devlink,
6367 const struct devlink_param *params,
6368 size_t params_count)
6369{
6370 return __devlink_params_register(devlink, 0, &devlink->param_list,
6371 params, params_count,
6372 DEVLINK_CMD_PARAM_NEW,
6373 DEVLINK_CMD_PARAM_DEL);
6374}
6375EXPORT_SYMBOL_GPL(devlink_params_register);
6376
6377/**
6378 * devlink_params_unregister - unregister configuration parameters
6379 * @devlink: devlink
6380 * @params: configuration parameters to unregister
6381 * @params_count: number of parameters provided
6382 */
6383void devlink_params_unregister(struct devlink *devlink,
6384 const struct devlink_param *params,
6385 size_t params_count)
6386{
6387 return __devlink_params_unregister(devlink, 0, &devlink->param_list,
6388 params, params_count,
6389 DEVLINK_CMD_PARAM_DEL);
6390}
6391EXPORT_SYMBOL_GPL(devlink_params_unregister);
6392
6393/**
6394 * devlink_params_publish - publish configuration parameters
6395 *
6396 * @devlink: devlink
6397 *
6398 * Publish previously registered configuration parameters.
6399 */
6400void devlink_params_publish(struct devlink *devlink)
6401{
6402 struct devlink_param_item *param_item;
6403
6404 list_for_each_entry(param_item, &devlink->param_list, list) {
6405 if (param_item->published)
6406 continue;
6407 param_item->published = true;
6408 devlink_param_notify(devlink, 0, param_item,
6409 DEVLINK_CMD_PARAM_NEW);
6410 }
6411}
6412EXPORT_SYMBOL_GPL(devlink_params_publish);
6413
6414/**
6415 * devlink_params_unpublish - unpublish configuration parameters
6416 *
6417 * @devlink: devlink
6418 *
6419 * Unpublish previously registered configuration parameters.
6420 */
6421void devlink_params_unpublish(struct devlink *devlink)
6422{
6423 struct devlink_param_item *param_item;
6424
6425 list_for_each_entry(param_item, &devlink->param_list, list) {
6426 if (!param_item->published)
6427 continue;
6428 param_item->published = false;
6429 devlink_param_notify(devlink, 0, param_item,
6430 DEVLINK_CMD_PARAM_DEL);
6431 }
6432}
6433EXPORT_SYMBOL_GPL(devlink_params_unpublish);
6434
6435/**
6436 * devlink_port_params_register - register port configuration parameters
6437 *
6438 * @devlink_port: devlink port
6439 * @params: configuration parameters array
6440 * @params_count: number of parameters provided
6441 *
6442 * Register the configuration parameters supported by the port.
6443 */
6444int devlink_port_params_register(struct devlink_port *devlink_port,
6445 const struct devlink_param *params,
6446 size_t params_count)
6447{
6448 return __devlink_params_register(devlink_port->devlink,
6449 devlink_port->index,
6450 &devlink_port->param_list, params,
6451 params_count,
6452 DEVLINK_CMD_PORT_PARAM_NEW,
6453 DEVLINK_CMD_PORT_PARAM_DEL);
6454}
6455EXPORT_SYMBOL_GPL(devlink_port_params_register);
6456
6457/**
6458 * devlink_port_params_unregister - unregister port configuration
6459 * parameters
6460 *
6461 * @devlink_port: devlink port
6462 * @params: configuration parameters array
6463 * @params_count: number of parameters provided
6464 */
6465void devlink_port_params_unregister(struct devlink_port *devlink_port,
6466 const struct devlink_param *params,
6467 size_t params_count)
6468{
6469 return __devlink_params_unregister(devlink_port->devlink,
6470 devlink_port->index,
6471 &devlink_port->param_list,
6472 params, params_count,
6473 DEVLINK_CMD_PORT_PARAM_DEL);
6474}
6475EXPORT_SYMBOL_GPL(devlink_port_params_unregister);
6476
6477static int
6478__devlink_param_driverinit_value_get(struct list_head *param_list, u32 param_id,
6479 union devlink_param_value *init_val)
6480{
6481 struct devlink_param_item *param_item;
6482
6483 param_item = devlink_param_find_by_id(param_list, param_id);
6484 if (!param_item)
6485 return -EINVAL;
6486
6487 if (!param_item->driverinit_value_valid ||
6488 !devlink_param_cmode_is_supported(param_item->param,
6489 DEVLINK_PARAM_CMODE_DRIVERINIT))
6490 return -EOPNOTSUPP;
6491
6492 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
6493 strcpy(init_val->vstr, param_item->driverinit_value.vstr);
6494 else
6495 *init_val = param_item->driverinit_value;
6496
6497 return 0;
6498}
6499
6500static int
6501__devlink_param_driverinit_value_set(struct devlink *devlink,
6502 unsigned int port_index,
6503 struct list_head *param_list, u32 param_id,
6504 union devlink_param_value init_val,
6505 enum devlink_command cmd)
6506{
6507 struct devlink_param_item *param_item;
6508
6509 param_item = devlink_param_find_by_id(param_list, param_id);
6510 if (!param_item)
6511 return -EINVAL;
6512
6513 if (!devlink_param_cmode_is_supported(param_item->param,
6514 DEVLINK_PARAM_CMODE_DRIVERINIT))
6515 return -EOPNOTSUPP;
6516
6517 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING)
6518 strcpy(param_item->driverinit_value.vstr, init_val.vstr);
6519 else
6520 param_item->driverinit_value = init_val;
6521 param_item->driverinit_value_valid = true;
6522
6523 devlink_param_notify(devlink, port_index, param_item, cmd);
6524 return 0;
6525}
6526
6527/**
6528 * devlink_param_driverinit_value_get - get configuration parameter
6529 * value for driver initializing
6530 *
6531 * @devlink: devlink
6532 * @param_id: parameter ID
6533 * @init_val: value of parameter in driverinit configuration mode
6534 *
6535 * This function should be used by the driver to get driverinit
6536 * configuration for initialization after reload command.
6537 */
6538int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id,
6539 union devlink_param_value *init_val)
6540{
6541 if (!devlink->ops->reload)
6542 return -EOPNOTSUPP;
6543
6544 return __devlink_param_driverinit_value_get(&devlink->param_list,
6545 param_id, init_val);
6546}
6547EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_get);
6548
6549/**
6550 * devlink_param_driverinit_value_set - set value of configuration
6551 * parameter for driverinit
6552 * configuration mode
6553 *
6554 * @devlink: devlink
6555 * @param_id: parameter ID
6556 * @init_val: value of parameter to set for driverinit configuration mode
6557 *
6558 * This function should be used by the driver to set driverinit
6559 * configuration mode default value.
6560 */
6561int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id,
6562 union devlink_param_value init_val)
6563{
6564 return __devlink_param_driverinit_value_set(devlink, 0,
6565 &devlink->param_list,
6566 param_id, init_val,
6567 DEVLINK_CMD_PARAM_NEW);
6568}
6569EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_set);
6570
6571/**
6572 * devlink_port_param_driverinit_value_get - get configuration parameter
6573 * value for driver initializing
6574 *
6575 * @devlink_port: devlink_port
6576 * @param_id: parameter ID
6577 * @init_val: value of parameter in driverinit configuration mode
6578 *
6579 * This function should be used by the driver to get driverinit
6580 * configuration for initialization after reload command.
6581 */
6582int devlink_port_param_driverinit_value_get(struct devlink_port *devlink_port,
6583 u32 param_id,
6584 union devlink_param_value *init_val)
6585{
6586 struct devlink *devlink = devlink_port->devlink;
6587
6588 if (!devlink->ops->reload)
6589 return -EOPNOTSUPP;
6590
6591 return __devlink_param_driverinit_value_get(&devlink_port->param_list,
6592 param_id, init_val);
6593}
6594EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_get);
6595
6596/**
6597 * devlink_port_param_driverinit_value_set - set value of configuration
6598 * parameter for driverinit
6599 * configuration mode
6600 *
6601 * @devlink_port: devlink_port
6602 * @param_id: parameter ID
6603 * @init_val: value of parameter to set for driverinit configuration mode
6604 *
6605 * This function should be used by the driver to set driverinit
6606 * configuration mode default value.
6607 */
6608int devlink_port_param_driverinit_value_set(struct devlink_port *devlink_port,
6609 u32 param_id,
6610 union devlink_param_value init_val)
6611{
6612 return __devlink_param_driverinit_value_set(devlink_port->devlink,
6613 devlink_port->index,
6614 &devlink_port->param_list,
6615 param_id, init_val,
6616 DEVLINK_CMD_PORT_PARAM_NEW);
6617}
6618EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_set);
6619
6620/**
6621 * devlink_param_value_changed - notify devlink on a parameter's value
6622 * change. Should be called by the driver
6623 * right after the change.
6624 *
6625 * @devlink: devlink
6626 * @param_id: parameter ID
6627 *
6628 * This function should be used by the driver to notify devlink on value
6629 * change, excluding driverinit configuration mode.
6630 * For driverinit configuration mode driver should use the function
6631 */
6632void devlink_param_value_changed(struct devlink *devlink, u32 param_id)
6633{
6634 struct devlink_param_item *param_item;
6635
6636 param_item = devlink_param_find_by_id(&devlink->param_list, param_id);
6637 WARN_ON(!param_item);
6638
6639 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW);
6640}
6641EXPORT_SYMBOL_GPL(devlink_param_value_changed);
6642
6643/**
6644 * devlink_port_param_value_changed - notify devlink on a parameter's value
6645 * change. Should be called by the driver
6646 * right after the change.
6647 *
6648 * @devlink_port: devlink_port
6649 * @param_id: parameter ID
6650 *
6651 * This function should be used by the driver to notify devlink on value
6652 * change, excluding driverinit configuration mode.
6653 * For driverinit configuration mode driver should use the function
6654 * devlink_port_param_driverinit_value_set() instead.
6655 */
6656void devlink_port_param_value_changed(struct devlink_port *devlink_port,
6657 u32 param_id)
6658{
6659 struct devlink_param_item *param_item;
6660
6661 param_item = devlink_param_find_by_id(&devlink_port->param_list,
6662 param_id);
6663 WARN_ON(!param_item);
6664
6665 devlink_param_notify(devlink_port->devlink, devlink_port->index,
6666 param_item, DEVLINK_CMD_PORT_PARAM_NEW);
6667}
6668EXPORT_SYMBOL_GPL(devlink_port_param_value_changed);
6669
6670/**
6671 * devlink_param_value_str_fill - Safely fill-up the string preventing
6672 * from overflow of the preallocated buffer
6673 *
6674 * @dst_val: destination devlink_param_value
6675 * @src: source buffer
6676 */
6677void devlink_param_value_str_fill(union devlink_param_value *dst_val,
6678 const char *src)
6679{
6680 size_t len;
6681
6682 len = strlcpy(dst_val->vstr, src, __DEVLINK_PARAM_MAX_STRING_VALUE);
6683 WARN_ON(len >= __DEVLINK_PARAM_MAX_STRING_VALUE);
6684}
6685EXPORT_SYMBOL_GPL(devlink_param_value_str_fill);
6686
6687/**
6688 * devlink_region_create - create a new address region
6689 *
6690 * @devlink: devlink
6691 * @region_name: region name
6692 * @region_max_snapshots: Maximum supported number of snapshots for region
6693 * @region_size: size of region
6694 */
6695struct devlink_region *devlink_region_create(struct devlink *devlink,
6696 const char *region_name,
6697 u32 region_max_snapshots,
6698 u64 region_size)
6699{
6700 struct devlink_region *region;
6701 int err = 0;
6702
6703 mutex_lock(&devlink->lock);
6704
6705 if (devlink_region_get_by_name(devlink, region_name)) {
6706 err = -EEXIST;
6707 goto unlock;
6708 }
6709
6710 region = kzalloc(sizeof(*region), GFP_KERNEL);
6711 if (!region) {
6712 err = -ENOMEM;
6713 goto unlock;
6714 }
6715
6716 region->devlink = devlink;
6717 region->max_snapshots = region_max_snapshots;
6718 region->name = region_name;
6719 region->size = region_size;
6720 INIT_LIST_HEAD(®ion->snapshot_list);
6721 list_add_tail(®ion->list, &devlink->region_list);
6722 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW);
6723
6724 mutex_unlock(&devlink->lock);
6725 return region;
6726
6727unlock:
6728 mutex_unlock(&devlink->lock);
6729 return ERR_PTR(err);
6730}
6731EXPORT_SYMBOL_GPL(devlink_region_create);
6732
6733/**
6734 * devlink_region_destroy - destroy address region
6735 *
6736 * @region: devlink region to destroy
6737 */
6738void devlink_region_destroy(struct devlink_region *region)
6739{
6740 struct devlink *devlink = region->devlink;
6741 struct devlink_snapshot *snapshot, *ts;
6742
6743 mutex_lock(&devlink->lock);
6744
6745 /* Free all snapshots of region */
6746 list_for_each_entry_safe(snapshot, ts, ®ion->snapshot_list, list)
6747 devlink_region_snapshot_del(snapshot);
6748
6749 list_del(®ion->list);
6750
6751 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL);
6752 mutex_unlock(&devlink->lock);
6753 kfree(region);
6754}
6755EXPORT_SYMBOL_GPL(devlink_region_destroy);
6756
6757/**
6758 * devlink_region_shapshot_id_get - get snapshot ID
6759 *
6760 * This callback should be called when adding a new snapshot,
6761 * Driver should use the same id for multiple snapshots taken
6762 * on multiple regions at the same time/by the same trigger.
6763 *
6764 * @devlink: devlink
6765 */
6766u32 devlink_region_shapshot_id_get(struct devlink *devlink)
6767{
6768 u32 id;
6769
6770 mutex_lock(&devlink->lock);
6771 id = ++devlink->snapshot_id;
6772 mutex_unlock(&devlink->lock);
6773
6774 return id;
6775}
6776EXPORT_SYMBOL_GPL(devlink_region_shapshot_id_get);
6777
6778/**
6779 * devlink_region_snapshot_create - create a new snapshot
6780 * This will add a new snapshot of a region. The snapshot
6781 * will be stored on the region struct and can be accessed
6782 * from devlink. This is useful for future analyses of snapshots.
6783 * Multiple snapshots can be created on a region.
6784 * The @snapshot_id should be obtained using the getter function.
6785 *
6786 * @region: devlink region of the snapshot
6787 * @data_len: size of snapshot data
6788 * @data: snapshot data
6789 * @snapshot_id: snapshot id to be created
6790 * @data_destructor: pointer to destructor function to free data
6791 */
6792int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len,
6793 u8 *data, u32 snapshot_id,
6794 devlink_snapshot_data_dest_t *data_destructor)
6795{
6796 struct devlink *devlink = region->devlink;
6797 struct devlink_snapshot *snapshot;
6798 int err;
6799
6800 mutex_lock(&devlink->lock);
6801
6802 /* check if region can hold one more snapshot */
6803 if (region->cur_snapshots == region->max_snapshots) {
6804 err = -ENOMEM;
6805 goto unlock;
6806 }
6807
6808 if (devlink_region_snapshot_get_by_id(region, snapshot_id)) {
6809 err = -EEXIST;
6810 goto unlock;
6811 }
6812
6813 snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL);
6814 if (!snapshot) {
6815 err = -ENOMEM;
6816 goto unlock;
6817 }
6818
6819 snapshot->id = snapshot_id;
6820 snapshot->region = region;
6821 snapshot->data = data;
6822 snapshot->data_len = data_len;
6823 snapshot->data_destructor = data_destructor;
6824
6825 list_add_tail(&snapshot->list, ®ion->snapshot_list);
6826
6827 region->cur_snapshots++;
6828
6829 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW);
6830 mutex_unlock(&devlink->lock);
6831 return 0;
6832
6833unlock:
6834 mutex_unlock(&devlink->lock);
6835 return err;
6836}
6837EXPORT_SYMBOL_GPL(devlink_region_snapshot_create);
6838
6839static void __devlink_compat_running_version(struct devlink *devlink,
6840 char *buf, size_t len)
6841{
6842 const struct nlattr *nlattr;
6843 struct devlink_info_req req;
6844 struct sk_buff *msg;
6845 int rem, err;
6846
6847 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
6848 if (!msg)
6849 return;
6850
6851 req.msg = msg;
6852 err = devlink->ops->info_get(devlink, &req, NULL);
6853 if (err)
6854 goto free_msg;
6855
6856 nla_for_each_attr(nlattr, (void *)msg->data, msg->len, rem) {
6857 const struct nlattr *kv;
6858 int rem_kv;
6859
6860 if (nla_type(nlattr) != DEVLINK_ATTR_INFO_VERSION_RUNNING)
6861 continue;
6862
6863 nla_for_each_nested(kv, nlattr, rem_kv) {
6864 if (nla_type(kv) != DEVLINK_ATTR_INFO_VERSION_VALUE)
6865 continue;
6866
6867 strlcat(buf, nla_data(kv), len);
6868 strlcat(buf, " ", len);
6869 }
6870 }
6871free_msg:
6872 nlmsg_free(msg);
6873}
6874
6875void devlink_compat_running_version(struct net_device *dev,
6876 char *buf, size_t len)
6877{
6878 struct devlink *devlink;
6879
6880 dev_hold(dev);
6881 rtnl_unlock();
6882
6883 devlink = netdev_to_devlink(dev);
6884 if (!devlink || !devlink->ops->info_get)
6885 goto out;
6886
6887 mutex_lock(&devlink->lock);
6888 __devlink_compat_running_version(devlink, buf, len);
6889 mutex_unlock(&devlink->lock);
6890
6891out:
6892 rtnl_lock();
6893 dev_put(dev);
6894}
6895
6896int devlink_compat_flash_update(struct net_device *dev, const char *file_name)
6897{
6898 struct devlink *devlink;
6899 int ret;
6900
6901 dev_hold(dev);
6902 rtnl_unlock();
6903
6904 devlink = netdev_to_devlink(dev);
6905 if (!devlink || !devlink->ops->flash_update) {
6906 ret = -EOPNOTSUPP;
6907 goto out;
6908 }
6909
6910 mutex_lock(&devlink->lock);
6911 ret = devlink->ops->flash_update(devlink, file_name, NULL, NULL);
6912 mutex_unlock(&devlink->lock);
6913
6914out:
6915 rtnl_lock();
6916 dev_put(dev);
6917
6918 return ret;
6919}
6920
6921int devlink_compat_phys_port_name_get(struct net_device *dev,
6922 char *name, size_t len)
6923{
6924 struct devlink_port *devlink_port;
6925
6926 /* RTNL mutex is held here which ensures that devlink_port
6927 * instance cannot disappear in the middle. No need to take
6928 * any devlink lock as only permanent values are accessed.
6929 */
6930 ASSERT_RTNL();
6931
6932 devlink_port = netdev_to_devlink_port(dev);
6933 if (!devlink_port)
6934 return -EOPNOTSUPP;
6935
6936 return __devlink_port_phys_port_name_get(devlink_port, name, len);
6937}
6938
6939int devlink_compat_switch_id_get(struct net_device *dev,
6940 struct netdev_phys_item_id *ppid)
6941{
6942 struct devlink_port *devlink_port;
6943
6944 /* RTNL mutex is held here which ensures that devlink_port
6945 * instance cannot disappear in the middle. No need to take
6946 * any devlink lock as only permanent values are accessed.
6947 */
6948 ASSERT_RTNL();
6949 devlink_port = netdev_to_devlink_port(dev);
6950 if (!devlink_port || !devlink_port->attrs.switch_port)
6951 return -EOPNOTSUPP;
6952
6953 memcpy(ppid, &devlink_port->attrs.switch_id, sizeof(*ppid));
6954
6955 return 0;
6956}
6957
6958static int __init devlink_init(void)
6959{
6960 return genl_register_family(&devlink_nl_family);
6961}
6962
6963subsys_initcall(devlink_init);