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