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