blob: b2e592a198c07736cfd03e577b4ff8e85fa3ca61 [file] [log] [blame]
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001/*
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>
29
30static LIST_HEAD(devlink_list);
31
32/* devlink_mutex
33 *
34 * An overall lock guarding every operation coming from userspace.
35 * It also guards devlink devices list and it is taken when
36 * driver registers/unregisters it.
37 */
38static DEFINE_MUTEX(devlink_mutex);
39
40/* devlink_port_mutex
41 *
42 * Shared lock to guard lists of ports in all devlink devices.
43 */
44static DEFINE_MUTEX(devlink_port_mutex);
45
46static struct net *devlink_net(const struct devlink *devlink)
47{
48 return read_pnet(&devlink->_net);
49}
50
51static void devlink_net_set(struct devlink *devlink, struct net *net)
52{
53 write_pnet(&devlink->_net, net);
54}
55
56static struct devlink *devlink_get_from_attrs(struct net *net,
57 struct nlattr **attrs)
58{
59 struct devlink *devlink;
60 char *busname;
61 char *devname;
62
63 if (!attrs[DEVLINK_ATTR_BUS_NAME] || !attrs[DEVLINK_ATTR_DEV_NAME])
64 return ERR_PTR(-EINVAL);
65
66 busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]);
67 devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]);
68
69 list_for_each_entry(devlink, &devlink_list, list) {
70 if (strcmp(devlink->dev->bus->name, busname) == 0 &&
71 strcmp(dev_name(devlink->dev), devname) == 0 &&
72 net_eq(devlink_net(devlink), net))
73 return devlink;
74 }
75
76 return ERR_PTR(-ENODEV);
77}
78
79static struct devlink *devlink_get_from_info(struct genl_info *info)
80{
81 return devlink_get_from_attrs(genl_info_net(info), info->attrs);
82}
83
84static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink,
85 int port_index)
86{
87 struct devlink_port *devlink_port;
88
89 list_for_each_entry(devlink_port, &devlink->port_list, list) {
90 if (devlink_port->index == port_index)
91 return devlink_port;
92 }
93 return NULL;
94}
95
96static bool devlink_port_index_exists(struct devlink *devlink, int port_index)
97{
98 return devlink_port_get_by_index(devlink, port_index);
99}
100
101static struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink,
102 struct nlattr **attrs)
103{
104 if (attrs[DEVLINK_ATTR_PORT_INDEX]) {
105 u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]);
106 struct devlink_port *devlink_port;
107
108 devlink_port = devlink_port_get_by_index(devlink, port_index);
109 if (!devlink_port)
110 return ERR_PTR(-ENODEV);
111 return devlink_port;
112 }
113 return ERR_PTR(-EINVAL);
114}
115
116static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink,
117 struct genl_info *info)
118{
119 return devlink_port_get_from_attrs(devlink, info->attrs);
120}
121
Jiri Pirkobf797472016-04-14 18:19:13 +0200122struct devlink_sb {
123 struct list_head list;
124 unsigned int index;
125 u32 size;
126 u16 ingress_pools_count;
127 u16 egress_pools_count;
128 u16 ingress_tc_count;
129 u16 egress_tc_count;
130};
131
132static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb)
133{
134 return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count;
135}
136
137static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink,
138 unsigned int sb_index)
139{
140 struct devlink_sb *devlink_sb;
141
142 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
143 if (devlink_sb->index == sb_index)
144 return devlink_sb;
145 }
146 return NULL;
147}
148
149static bool devlink_sb_index_exists(struct devlink *devlink,
150 unsigned int sb_index)
151{
152 return devlink_sb_get_by_index(devlink, sb_index);
153}
154
155static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink,
156 struct nlattr **attrs)
157{
158 if (attrs[DEVLINK_ATTR_SB_INDEX]) {
159 u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]);
160 struct devlink_sb *devlink_sb;
161
162 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
163 if (!devlink_sb)
164 return ERR_PTR(-ENODEV);
165 return devlink_sb;
166 }
167 return ERR_PTR(-EINVAL);
168}
169
170static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink,
171 struct genl_info *info)
172{
173 return devlink_sb_get_from_attrs(devlink, info->attrs);
174}
175
176static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb,
177 struct nlattr **attrs,
178 u16 *p_pool_index)
179{
180 u16 val;
181
182 if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX])
183 return -EINVAL;
184
185 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]);
186 if (val >= devlink_sb_pool_count(devlink_sb))
187 return -EINVAL;
188 *p_pool_index = val;
189 return 0;
190}
191
192static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb,
193 struct genl_info *info,
194 u16 *p_pool_index)
195{
196 return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs,
197 p_pool_index);
198}
199
200static int
201devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs,
202 enum devlink_sb_pool_type *p_pool_type)
203{
204 u8 val;
205
206 if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE])
207 return -EINVAL;
208
209 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]);
210 if (val != DEVLINK_SB_POOL_TYPE_INGRESS &&
211 val != DEVLINK_SB_POOL_TYPE_EGRESS)
212 return -EINVAL;
213 *p_pool_type = val;
214 return 0;
215}
216
217static int
218devlink_sb_pool_type_get_from_info(struct genl_info *info,
219 enum devlink_sb_pool_type *p_pool_type)
220{
221 return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type);
222}
223
224static int
225devlink_sb_th_type_get_from_attrs(struct nlattr **attrs,
226 enum devlink_sb_threshold_type *p_th_type)
227{
228 u8 val;
229
230 if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE])
231 return -EINVAL;
232
233 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]);
234 if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC &&
235 val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC)
236 return -EINVAL;
237 *p_th_type = val;
238 return 0;
239}
240
241static int
242devlink_sb_th_type_get_from_info(struct genl_info *info,
243 enum devlink_sb_threshold_type *p_th_type)
244{
245 return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type);
246}
247
248static int
249devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb,
250 struct nlattr **attrs,
251 enum devlink_sb_pool_type pool_type,
252 u16 *p_tc_index)
253{
254 u16 val;
255
256 if (!attrs[DEVLINK_ATTR_SB_TC_INDEX])
257 return -EINVAL;
258
259 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]);
260 if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS &&
261 val >= devlink_sb->ingress_tc_count)
262 return -EINVAL;
263 if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS &&
264 val >= devlink_sb->egress_tc_count)
265 return -EINVAL;
266 *p_tc_index = val;
267 return 0;
268}
269
270static int
271devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb,
272 struct genl_info *info,
273 enum devlink_sb_pool_type pool_type,
274 u16 *p_tc_index)
275{
276 return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs,
277 pool_type, p_tc_index);
278}
279
Jiri Pirko1fc22572016-04-08 19:12:48 +0200280#define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0)
281#define DEVLINK_NL_FLAG_NEED_PORT BIT(1)
Jiri Pirkobf797472016-04-14 18:19:13 +0200282#define DEVLINK_NL_FLAG_NEED_SB BIT(2)
Jiri Pirkodf38daf2016-04-14 18:19:14 +0200283#define DEVLINK_NL_FLAG_LOCK_PORTS BIT(3)
284 /* port is not needed but we need to ensure they don't
285 * change in the middle of command
286 */
Jiri Pirkobfcd3a42016-02-26 17:32:23 +0100287
288static int devlink_nl_pre_doit(const struct genl_ops *ops,
289 struct sk_buff *skb, struct genl_info *info)
290{
291 struct devlink *devlink;
292
293 mutex_lock(&devlink_mutex);
294 devlink = devlink_get_from_info(info);
295 if (IS_ERR(devlink)) {
296 mutex_unlock(&devlink_mutex);
297 return PTR_ERR(devlink);
298 }
Jiri Pirko1fc22572016-04-08 19:12:48 +0200299 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) {
300 info->user_ptr[0] = devlink;
301 } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) {
Jiri Pirkobfcd3a42016-02-26 17:32:23 +0100302 struct devlink_port *devlink_port;
303
304 mutex_lock(&devlink_port_mutex);
305 devlink_port = devlink_port_get_from_info(devlink, info);
306 if (IS_ERR(devlink_port)) {
307 mutex_unlock(&devlink_port_mutex);
308 mutex_unlock(&devlink_mutex);
309 return PTR_ERR(devlink_port);
310 }
Jiri Pirko1fc22572016-04-08 19:12:48 +0200311 info->user_ptr[0] = devlink_port;
Jiri Pirkobfcd3a42016-02-26 17:32:23 +0100312 }
Jiri Pirkodf38daf2016-04-14 18:19:14 +0200313 if (ops->internal_flags & DEVLINK_NL_FLAG_LOCK_PORTS) {
314 mutex_lock(&devlink_port_mutex);
315 }
Jiri Pirkobf797472016-04-14 18:19:13 +0200316 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) {
317 struct devlink_sb *devlink_sb;
318
319 devlink_sb = devlink_sb_get_from_info(devlink, info);
320 if (IS_ERR(devlink_sb)) {
321 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT)
322 mutex_unlock(&devlink_port_mutex);
323 mutex_unlock(&devlink_mutex);
324 return PTR_ERR(devlink_sb);
325 }
326 info->user_ptr[1] = devlink_sb;
327 }
Jiri Pirkobfcd3a42016-02-26 17:32:23 +0100328 return 0;
329}
330
331static void devlink_nl_post_doit(const struct genl_ops *ops,
332 struct sk_buff *skb, struct genl_info *info)
333{
Jiri Pirkodf38daf2016-04-14 18:19:14 +0200334 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT ||
335 ops->internal_flags & DEVLINK_NL_FLAG_LOCK_PORTS)
Jiri Pirkobfcd3a42016-02-26 17:32:23 +0100336 mutex_unlock(&devlink_port_mutex);
337 mutex_unlock(&devlink_mutex);
338}
339
340static struct genl_family devlink_nl_family = {
341 .id = GENL_ID_GENERATE,
342 .name = DEVLINK_GENL_NAME,
343 .version = DEVLINK_GENL_VERSION,
344 .maxattr = DEVLINK_ATTR_MAX,
345 .netnsok = true,
346 .pre_doit = devlink_nl_pre_doit,
347 .post_doit = devlink_nl_post_doit,
348};
349
350enum devlink_multicast_groups {
351 DEVLINK_MCGRP_CONFIG,
352};
353
354static const struct genl_multicast_group devlink_nl_mcgrps[] = {
355 [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME },
356};
357
358static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
359{
360 if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
361 return -EMSGSIZE;
362 if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
363 return -EMSGSIZE;
364 return 0;
365}
366
367static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
368 enum devlink_command cmd, u32 portid,
369 u32 seq, int flags)
370{
371 void *hdr;
372
373 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
374 if (!hdr)
375 return -EMSGSIZE;
376
377 if (devlink_nl_put_handle(msg, devlink))
378 goto nla_put_failure;
379
380 genlmsg_end(msg, hdr);
381 return 0;
382
383nla_put_failure:
384 genlmsg_cancel(msg, hdr);
385 return -EMSGSIZE;
386}
387
388static void devlink_notify(struct devlink *devlink, enum devlink_command cmd)
389{
390 struct sk_buff *msg;
391 int err;
392
393 WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL);
394
395 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
396 if (!msg)
397 return;
398
399 err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0);
400 if (err) {
401 nlmsg_free(msg);
402 return;
403 }
404
405 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
406 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
407}
408
409static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
410 struct devlink_port *devlink_port,
411 enum devlink_command cmd, u32 portid,
412 u32 seq, int flags)
413{
414 void *hdr;
415
416 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
417 if (!hdr)
418 return -EMSGSIZE;
419
420 if (devlink_nl_put_handle(msg, devlink))
421 goto nla_put_failure;
422 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
423 goto nla_put_failure;
424 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type))
425 goto nla_put_failure;
426 if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET &&
427 nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE,
428 devlink_port->desired_type))
429 goto nla_put_failure;
430 if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) {
431 struct net_device *netdev = devlink_port->type_dev;
432
433 if (netdev &&
434 (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX,
435 netdev->ifindex) ||
436 nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME,
437 netdev->name)))
438 goto nla_put_failure;
439 }
440 if (devlink_port->type == DEVLINK_PORT_TYPE_IB) {
441 struct ib_device *ibdev = devlink_port->type_dev;
442
443 if (ibdev &&
444 nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME,
445 ibdev->name))
446 goto nla_put_failure;
447 }
448 if (devlink_port->split &&
449 nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP,
450 devlink_port->split_group))
451 goto nla_put_failure;
452
453 genlmsg_end(msg, hdr);
454 return 0;
455
456nla_put_failure:
457 genlmsg_cancel(msg, hdr);
458 return -EMSGSIZE;
459}
460
461static void devlink_port_notify(struct devlink_port *devlink_port,
462 enum devlink_command cmd)
463{
464 struct devlink *devlink = devlink_port->devlink;
465 struct sk_buff *msg;
466 int err;
467
468 if (!devlink_port->registered)
469 return;
470
471 WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL);
472
473 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
474 if (!msg)
475 return;
476
477 err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0);
478 if (err) {
479 nlmsg_free(msg);
480 return;
481 }
482
483 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
484 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
485}
486
487static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info)
488{
489 struct devlink *devlink = info->user_ptr[0];
490 struct sk_buff *msg;
491 int err;
492
493 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
494 if (!msg)
495 return -ENOMEM;
496
497 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
498 info->snd_portid, info->snd_seq, 0);
499 if (err) {
500 nlmsg_free(msg);
501 return err;
502 }
503
504 return genlmsg_reply(msg, info);
505}
506
507static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg,
508 struct netlink_callback *cb)
509{
510 struct devlink *devlink;
511 int start = cb->args[0];
512 int idx = 0;
513 int err;
514
515 mutex_lock(&devlink_mutex);
516 list_for_each_entry(devlink, &devlink_list, list) {
517 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
518 continue;
519 if (idx < start) {
520 idx++;
521 continue;
522 }
523 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
524 NETLINK_CB(cb->skb).portid,
525 cb->nlh->nlmsg_seq, NLM_F_MULTI);
526 if (err)
527 goto out;
528 idx++;
529 }
530out:
531 mutex_unlock(&devlink_mutex);
532
533 cb->args[0] = idx;
534 return msg->len;
535}
536
537static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb,
538 struct genl_info *info)
539{
Jiri Pirko1fc22572016-04-08 19:12:48 +0200540 struct devlink_port *devlink_port = info->user_ptr[0];
541 struct devlink *devlink = devlink_port->devlink;
Jiri Pirkobfcd3a42016-02-26 17:32:23 +0100542 struct sk_buff *msg;
543 int err;
544
545 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
546 if (!msg)
547 return -ENOMEM;
548
549 err = devlink_nl_port_fill(msg, devlink, devlink_port,
550 DEVLINK_CMD_PORT_NEW,
551 info->snd_portid, info->snd_seq, 0);
552 if (err) {
553 nlmsg_free(msg);
554 return err;
555 }
556
557 return genlmsg_reply(msg, info);
558}
559
560static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg,
561 struct netlink_callback *cb)
562{
563 struct devlink *devlink;
564 struct devlink_port *devlink_port;
565 int start = cb->args[0];
566 int idx = 0;
567 int err;
568
569 mutex_lock(&devlink_mutex);
570 mutex_lock(&devlink_port_mutex);
571 list_for_each_entry(devlink, &devlink_list, list) {
572 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
573 continue;
574 list_for_each_entry(devlink_port, &devlink->port_list, list) {
575 if (idx < start) {
576 idx++;
577 continue;
578 }
579 err = devlink_nl_port_fill(msg, devlink, devlink_port,
580 DEVLINK_CMD_NEW,
581 NETLINK_CB(cb->skb).portid,
582 cb->nlh->nlmsg_seq,
583 NLM_F_MULTI);
584 if (err)
585 goto out;
586 idx++;
587 }
588 }
589out:
590 mutex_unlock(&devlink_port_mutex);
591 mutex_unlock(&devlink_mutex);
592
593 cb->args[0] = idx;
594 return msg->len;
595}
596
597static int devlink_port_type_set(struct devlink *devlink,
598 struct devlink_port *devlink_port,
599 enum devlink_port_type port_type)
600
601{
602 int err;
603
604 if (devlink->ops && devlink->ops->port_type_set) {
605 if (port_type == DEVLINK_PORT_TYPE_NOTSET)
606 return -EINVAL;
607 err = devlink->ops->port_type_set(devlink_port, port_type);
608 if (err)
609 return err;
610 devlink_port->desired_type = port_type;
611 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
612 return 0;
613 }
614 return -EOPNOTSUPP;
615}
616
617static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb,
618 struct genl_info *info)
619{
Jiri Pirko1fc22572016-04-08 19:12:48 +0200620 struct devlink_port *devlink_port = info->user_ptr[0];
621 struct devlink *devlink = devlink_port->devlink;
Jiri Pirkobfcd3a42016-02-26 17:32:23 +0100622 int err;
623
624 if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) {
625 enum devlink_port_type port_type;
626
627 port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]);
628 err = devlink_port_type_set(devlink, devlink_port, port_type);
629 if (err)
630 return err;
631 }
632 return 0;
633}
634
635static int devlink_port_split(struct devlink *devlink,
636 u32 port_index, u32 count)
637
638{
639 if (devlink->ops && devlink->ops->port_split)
640 return devlink->ops->port_split(devlink, port_index, count);
641 return -EOPNOTSUPP;
642}
643
644static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb,
645 struct genl_info *info)
646{
647 struct devlink *devlink = info->user_ptr[0];
648 u32 port_index;
649 u32 count;
650
651 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] ||
652 !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT])
653 return -EINVAL;
654
655 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
656 count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]);
657 return devlink_port_split(devlink, port_index, count);
658}
659
660static int devlink_port_unsplit(struct devlink *devlink, u32 port_index)
661
662{
663 if (devlink->ops && devlink->ops->port_unsplit)
664 return devlink->ops->port_unsplit(devlink, port_index);
665 return -EOPNOTSUPP;
666}
667
668static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb,
669 struct genl_info *info)
670{
671 struct devlink *devlink = info->user_ptr[0];
672 u32 port_index;
673
674 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX])
675 return -EINVAL;
676
677 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
678 return devlink_port_unsplit(devlink, port_index);
679}
680
Jiri Pirkobf797472016-04-14 18:19:13 +0200681static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink,
682 struct devlink_sb *devlink_sb,
683 enum devlink_command cmd, u32 portid,
684 u32 seq, int flags)
685{
686 void *hdr;
687
688 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
689 if (!hdr)
690 return -EMSGSIZE;
691
692 if (devlink_nl_put_handle(msg, devlink))
693 goto nla_put_failure;
694 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
695 goto nla_put_failure;
696 if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size))
697 goto nla_put_failure;
698 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT,
699 devlink_sb->ingress_pools_count))
700 goto nla_put_failure;
701 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT,
702 devlink_sb->egress_pools_count))
703 goto nla_put_failure;
704 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT,
705 devlink_sb->ingress_tc_count))
706 goto nla_put_failure;
707 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT,
708 devlink_sb->egress_tc_count))
709 goto nla_put_failure;
710
711 genlmsg_end(msg, hdr);
712 return 0;
713
714nla_put_failure:
715 genlmsg_cancel(msg, hdr);
716 return -EMSGSIZE;
717}
718
719static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb,
720 struct genl_info *info)
721{
722 struct devlink *devlink = info->user_ptr[0];
723 struct devlink_sb *devlink_sb = info->user_ptr[1];
724 struct sk_buff *msg;
725 int err;
726
727 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
728 if (!msg)
729 return -ENOMEM;
730
731 err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
732 DEVLINK_CMD_SB_NEW,
733 info->snd_portid, info->snd_seq, 0);
734 if (err) {
735 nlmsg_free(msg);
736 return err;
737 }
738
739 return genlmsg_reply(msg, info);
740}
741
742static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg,
743 struct netlink_callback *cb)
744{
745 struct devlink *devlink;
746 struct devlink_sb *devlink_sb;
747 int start = cb->args[0];
748 int idx = 0;
749 int err;
750
751 mutex_lock(&devlink_mutex);
752 list_for_each_entry(devlink, &devlink_list, list) {
753 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
754 continue;
755 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
756 if (idx < start) {
757 idx++;
758 continue;
759 }
760 err = devlink_nl_sb_fill(msg, devlink, devlink_sb,
761 DEVLINK_CMD_SB_NEW,
762 NETLINK_CB(cb->skb).portid,
763 cb->nlh->nlmsg_seq,
764 NLM_F_MULTI);
765 if (err)
766 goto out;
767 idx++;
768 }
769 }
770out:
771 mutex_unlock(&devlink_mutex);
772
773 cb->args[0] = idx;
774 return msg->len;
775}
776
777static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink,
778 struct devlink_sb *devlink_sb,
779 u16 pool_index, enum devlink_command cmd,
780 u32 portid, u32 seq, int flags)
781{
782 struct devlink_sb_pool_info pool_info;
783 void *hdr;
784 int err;
785
786 err = devlink->ops->sb_pool_get(devlink, devlink_sb->index,
787 pool_index, &pool_info);
788 if (err)
789 return err;
790
791 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
792 if (!hdr)
793 return -EMSGSIZE;
794
795 if (devlink_nl_put_handle(msg, devlink))
796 goto nla_put_failure;
797 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
798 goto nla_put_failure;
799 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
800 goto nla_put_failure;
801 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type))
802 goto nla_put_failure;
803 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size))
804 goto nla_put_failure;
805 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE,
806 pool_info.threshold_type))
807 goto nla_put_failure;
808
809 genlmsg_end(msg, hdr);
810 return 0;
811
812nla_put_failure:
813 genlmsg_cancel(msg, hdr);
814 return -EMSGSIZE;
815}
816
817static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb,
818 struct genl_info *info)
819{
820 struct devlink *devlink = info->user_ptr[0];
821 struct devlink_sb *devlink_sb = info->user_ptr[1];
822 struct sk_buff *msg;
823 u16 pool_index;
824 int err;
825
826 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
827 &pool_index);
828 if (err)
829 return err;
830
831 if (!devlink->ops || !devlink->ops->sb_pool_get)
832 return -EOPNOTSUPP;
833
834 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
835 if (!msg)
836 return -ENOMEM;
837
838 err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index,
839 DEVLINK_CMD_SB_POOL_NEW,
840 info->snd_portid, info->snd_seq, 0);
841 if (err) {
842 nlmsg_free(msg);
843 return err;
844 }
845
846 return genlmsg_reply(msg, info);
847}
848
849static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
850 struct devlink *devlink,
851 struct devlink_sb *devlink_sb,
852 u32 portid, u32 seq)
853{
854 u16 pool_count = devlink_sb_pool_count(devlink_sb);
855 u16 pool_index;
856 int err;
857
858 for (pool_index = 0; pool_index < pool_count; pool_index++) {
859 if (*p_idx < start) {
860 (*p_idx)++;
861 continue;
862 }
863 err = devlink_nl_sb_pool_fill(msg, devlink,
864 devlink_sb,
865 pool_index,
866 DEVLINK_CMD_SB_POOL_NEW,
867 portid, seq, NLM_F_MULTI);
868 if (err)
869 return err;
870 (*p_idx)++;
871 }
872 return 0;
873}
874
875static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg,
876 struct netlink_callback *cb)
877{
878 struct devlink *devlink;
879 struct devlink_sb *devlink_sb;
880 int start = cb->args[0];
881 int idx = 0;
882 int err;
883
884 mutex_lock(&devlink_mutex);
885 list_for_each_entry(devlink, &devlink_list, list) {
886 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
887 !devlink->ops || !devlink->ops->sb_pool_get)
888 continue;
889 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
890 err = __sb_pool_get_dumpit(msg, start, &idx, devlink,
891 devlink_sb,
892 NETLINK_CB(cb->skb).portid,
893 cb->nlh->nlmsg_seq);
894 if (err && err != -EOPNOTSUPP)
895 goto out;
896 }
897 }
898out:
899 mutex_unlock(&devlink_mutex);
900
901 cb->args[0] = idx;
902 return msg->len;
903}
904
905static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index,
906 u16 pool_index, u32 size,
907 enum devlink_sb_threshold_type threshold_type)
908
909{
910 const struct devlink_ops *ops = devlink->ops;
911
912 if (ops && ops->sb_pool_set)
913 return ops->sb_pool_set(devlink, sb_index, pool_index,
914 size, threshold_type);
915 return -EOPNOTSUPP;
916}
917
918static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb,
919 struct genl_info *info)
920{
921 struct devlink *devlink = info->user_ptr[0];
922 struct devlink_sb *devlink_sb = info->user_ptr[1];
923 enum devlink_sb_threshold_type threshold_type;
924 u16 pool_index;
925 u32 size;
926 int err;
927
928 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
929 &pool_index);
930 if (err)
931 return err;
932
933 err = devlink_sb_th_type_get_from_info(info, &threshold_type);
934 if (err)
935 return err;
936
937 if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE])
938 return -EINVAL;
939
940 size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]);
941 return devlink_sb_pool_set(devlink, devlink_sb->index,
942 pool_index, size, threshold_type);
943}
944
945static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg,
946 struct devlink *devlink,
947 struct devlink_port *devlink_port,
948 struct devlink_sb *devlink_sb,
949 u16 pool_index,
950 enum devlink_command cmd,
951 u32 portid, u32 seq, int flags)
952{
Jiri Pirkodf38daf2016-04-14 18:19:14 +0200953 const struct devlink_ops *ops = devlink->ops;
Jiri Pirkobf797472016-04-14 18:19:13 +0200954 u32 threshold;
955 void *hdr;
956 int err;
957
Jiri Pirkodf38daf2016-04-14 18:19:14 +0200958 err = ops->sb_port_pool_get(devlink_port, devlink_sb->index,
959 pool_index, &threshold);
Jiri Pirkobf797472016-04-14 18:19:13 +0200960 if (err)
961 return err;
962
963 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
964 if (!hdr)
965 return -EMSGSIZE;
966
967 if (devlink_nl_put_handle(msg, devlink))
968 goto nla_put_failure;
969 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
970 goto nla_put_failure;
971 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
972 goto nla_put_failure;
973 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
974 goto nla_put_failure;
975 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
976 goto nla_put_failure;
977
Jiri Pirkodf38daf2016-04-14 18:19:14 +0200978 if (ops->sb_occ_port_pool_get) {
979 u32 cur;
980 u32 max;
981
982 err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index,
983 pool_index, &cur, &max);
984 if (err && err != -EOPNOTSUPP)
985 return err;
986 if (!err) {
987 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
988 goto nla_put_failure;
989 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
990 goto nla_put_failure;
991 }
992 }
993
Jiri Pirkobf797472016-04-14 18:19:13 +0200994 genlmsg_end(msg, hdr);
995 return 0;
996
997nla_put_failure:
998 genlmsg_cancel(msg, hdr);
999 return -EMSGSIZE;
1000}
1001
1002static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb,
1003 struct genl_info *info)
1004{
1005 struct devlink_port *devlink_port = info->user_ptr[0];
1006 struct devlink *devlink = devlink_port->devlink;
1007 struct devlink_sb *devlink_sb = info->user_ptr[1];
1008 struct sk_buff *msg;
1009 u16 pool_index;
1010 int err;
1011
1012 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1013 &pool_index);
1014 if (err)
1015 return err;
1016
1017 if (!devlink->ops || !devlink->ops->sb_port_pool_get)
1018 return -EOPNOTSUPP;
1019
1020 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1021 if (!msg)
1022 return -ENOMEM;
1023
1024 err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port,
1025 devlink_sb, pool_index,
1026 DEVLINK_CMD_SB_PORT_POOL_NEW,
1027 info->snd_portid, info->snd_seq, 0);
1028 if (err) {
1029 nlmsg_free(msg);
1030 return err;
1031 }
1032
1033 return genlmsg_reply(msg, info);
1034}
1035
1036static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx,
1037 struct devlink *devlink,
1038 struct devlink_sb *devlink_sb,
1039 u32 portid, u32 seq)
1040{
1041 struct devlink_port *devlink_port;
1042 u16 pool_count = devlink_sb_pool_count(devlink_sb);
1043 u16 pool_index;
1044 int err;
1045
1046 list_for_each_entry(devlink_port, &devlink->port_list, list) {
1047 for (pool_index = 0; pool_index < pool_count; pool_index++) {
1048 if (*p_idx < start) {
1049 (*p_idx)++;
1050 continue;
1051 }
1052 err = devlink_nl_sb_port_pool_fill(msg, devlink,
1053 devlink_port,
1054 devlink_sb,
1055 pool_index,
1056 DEVLINK_CMD_SB_PORT_POOL_NEW,
1057 portid, seq,
1058 NLM_F_MULTI);
1059 if (err)
1060 return err;
1061 (*p_idx)++;
1062 }
1063 }
1064 return 0;
1065}
1066
1067static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg,
1068 struct netlink_callback *cb)
1069{
1070 struct devlink *devlink;
1071 struct devlink_sb *devlink_sb;
1072 int start = cb->args[0];
1073 int idx = 0;
1074 int err;
1075
1076 mutex_lock(&devlink_mutex);
1077 mutex_lock(&devlink_port_mutex);
1078 list_for_each_entry(devlink, &devlink_list, list) {
1079 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1080 !devlink->ops || !devlink->ops->sb_port_pool_get)
1081 continue;
1082 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1083 err = __sb_port_pool_get_dumpit(msg, start, &idx,
1084 devlink, devlink_sb,
1085 NETLINK_CB(cb->skb).portid,
1086 cb->nlh->nlmsg_seq);
1087 if (err && err != -EOPNOTSUPP)
1088 goto out;
1089 }
1090 }
1091out:
1092 mutex_unlock(&devlink_port_mutex);
1093 mutex_unlock(&devlink_mutex);
1094
1095 cb->args[0] = idx;
1096 return msg->len;
1097}
1098
1099static int devlink_sb_port_pool_set(struct devlink_port *devlink_port,
1100 unsigned int sb_index, u16 pool_index,
1101 u32 threshold)
1102
1103{
1104 const struct devlink_ops *ops = devlink_port->devlink->ops;
1105
1106 if (ops && ops->sb_port_pool_set)
1107 return ops->sb_port_pool_set(devlink_port, sb_index,
1108 pool_index, threshold);
1109 return -EOPNOTSUPP;
1110}
1111
1112static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb,
1113 struct genl_info *info)
1114{
1115 struct devlink_port *devlink_port = info->user_ptr[0];
1116 struct devlink_sb *devlink_sb = info->user_ptr[1];
1117 u16 pool_index;
1118 u32 threshold;
1119 int err;
1120
1121 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1122 &pool_index);
1123 if (err)
1124 return err;
1125
1126 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1127 return -EINVAL;
1128
1129 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1130 return devlink_sb_port_pool_set(devlink_port, devlink_sb->index,
1131 pool_index, threshold);
1132}
1133
1134static int
1135devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink,
1136 struct devlink_port *devlink_port,
1137 struct devlink_sb *devlink_sb, u16 tc_index,
1138 enum devlink_sb_pool_type pool_type,
1139 enum devlink_command cmd,
1140 u32 portid, u32 seq, int flags)
1141{
Jiri Pirkodf38daf2016-04-14 18:19:14 +02001142 const struct devlink_ops *ops = devlink->ops;
Jiri Pirkobf797472016-04-14 18:19:13 +02001143 u16 pool_index;
1144 u32 threshold;
1145 void *hdr;
1146 int err;
1147
Jiri Pirkodf38daf2016-04-14 18:19:14 +02001148 err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index,
1149 tc_index, pool_type,
1150 &pool_index, &threshold);
Jiri Pirkobf797472016-04-14 18:19:13 +02001151 if (err)
1152 return err;
1153
1154 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1155 if (!hdr)
1156 return -EMSGSIZE;
1157
1158 if (devlink_nl_put_handle(msg, devlink))
1159 goto nla_put_failure;
1160 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
1161 goto nla_put_failure;
1162 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index))
1163 goto nla_put_failure;
1164 if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index))
1165 goto nla_put_failure;
1166 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type))
1167 goto nla_put_failure;
1168 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index))
1169 goto nla_put_failure;
1170 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold))
1171 goto nla_put_failure;
1172
Jiri Pirkodf38daf2016-04-14 18:19:14 +02001173 if (ops->sb_occ_tc_port_bind_get) {
1174 u32 cur;
1175 u32 max;
1176
1177 err = ops->sb_occ_tc_port_bind_get(devlink_port,
1178 devlink_sb->index,
1179 tc_index, pool_type,
1180 &cur, &max);
1181 if (err && err != -EOPNOTSUPP)
1182 return err;
1183 if (!err) {
1184 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur))
1185 goto nla_put_failure;
1186 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max))
1187 goto nla_put_failure;
1188 }
1189 }
1190
Jiri Pirkobf797472016-04-14 18:19:13 +02001191 genlmsg_end(msg, hdr);
1192 return 0;
1193
1194nla_put_failure:
1195 genlmsg_cancel(msg, hdr);
1196 return -EMSGSIZE;
1197}
1198
1199static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb,
1200 struct genl_info *info)
1201{
1202 struct devlink_port *devlink_port = info->user_ptr[0];
1203 struct devlink *devlink = devlink_port->devlink;
1204 struct devlink_sb *devlink_sb = info->user_ptr[1];
1205 struct sk_buff *msg;
1206 enum devlink_sb_pool_type pool_type;
1207 u16 tc_index;
1208 int err;
1209
1210 err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1211 if (err)
1212 return err;
1213
1214 err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1215 pool_type, &tc_index);
1216 if (err)
1217 return err;
1218
1219 if (!devlink->ops || !devlink->ops->sb_tc_pool_bind_get)
1220 return -EOPNOTSUPP;
1221
1222 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1223 if (!msg)
1224 return -ENOMEM;
1225
1226 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port,
1227 devlink_sb, tc_index, pool_type,
1228 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1229 info->snd_portid,
1230 info->snd_seq, 0);
1231 if (err) {
1232 nlmsg_free(msg);
1233 return err;
1234 }
1235
1236 return genlmsg_reply(msg, info);
1237}
1238
1239static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1240 int start, int *p_idx,
1241 struct devlink *devlink,
1242 struct devlink_sb *devlink_sb,
1243 u32 portid, u32 seq)
1244{
1245 struct devlink_port *devlink_port;
1246 u16 tc_index;
1247 int err;
1248
1249 list_for_each_entry(devlink_port, &devlink->port_list, list) {
1250 for (tc_index = 0;
1251 tc_index < devlink_sb->ingress_tc_count; tc_index++) {
1252 if (*p_idx < start) {
1253 (*p_idx)++;
1254 continue;
1255 }
1256 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1257 devlink_port,
1258 devlink_sb,
1259 tc_index,
1260 DEVLINK_SB_POOL_TYPE_INGRESS,
1261 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1262 portid, seq,
1263 NLM_F_MULTI);
1264 if (err)
1265 return err;
1266 (*p_idx)++;
1267 }
1268 for (tc_index = 0;
1269 tc_index < devlink_sb->egress_tc_count; tc_index++) {
1270 if (*p_idx < start) {
1271 (*p_idx)++;
1272 continue;
1273 }
1274 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink,
1275 devlink_port,
1276 devlink_sb,
1277 tc_index,
1278 DEVLINK_SB_POOL_TYPE_EGRESS,
1279 DEVLINK_CMD_SB_TC_POOL_BIND_NEW,
1280 portid, seq,
1281 NLM_F_MULTI);
1282 if (err)
1283 return err;
1284 (*p_idx)++;
1285 }
1286 }
1287 return 0;
1288}
1289
1290static int
1291devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg,
1292 struct netlink_callback *cb)
1293{
1294 struct devlink *devlink;
1295 struct devlink_sb *devlink_sb;
1296 int start = cb->args[0];
1297 int idx = 0;
1298 int err;
1299
1300 mutex_lock(&devlink_mutex);
1301 mutex_lock(&devlink_port_mutex);
1302 list_for_each_entry(devlink, &devlink_list, list) {
1303 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) ||
1304 !devlink->ops || !devlink->ops->sb_tc_pool_bind_get)
1305 continue;
1306 list_for_each_entry(devlink_sb, &devlink->sb_list, list) {
1307 err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx,
1308 devlink,
1309 devlink_sb,
1310 NETLINK_CB(cb->skb).portid,
1311 cb->nlh->nlmsg_seq);
1312 if (err && err != -EOPNOTSUPP)
1313 goto out;
1314 }
1315 }
1316out:
1317 mutex_unlock(&devlink_port_mutex);
1318 mutex_unlock(&devlink_mutex);
1319
1320 cb->args[0] = idx;
1321 return msg->len;
1322}
1323
1324static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port,
1325 unsigned int sb_index, u16 tc_index,
1326 enum devlink_sb_pool_type pool_type,
1327 u16 pool_index, u32 threshold)
1328
1329{
1330 const struct devlink_ops *ops = devlink_port->devlink->ops;
1331
1332 if (ops && ops->sb_tc_pool_bind_set)
1333 return ops->sb_tc_pool_bind_set(devlink_port, sb_index,
1334 tc_index, pool_type,
1335 pool_index, threshold);
1336 return -EOPNOTSUPP;
1337}
1338
1339static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb,
1340 struct genl_info *info)
1341{
1342 struct devlink_port *devlink_port = info->user_ptr[0];
1343 struct devlink_sb *devlink_sb = info->user_ptr[1];
1344 enum devlink_sb_pool_type pool_type;
1345 u16 tc_index;
1346 u16 pool_index;
1347 u32 threshold;
1348 int err;
1349
1350 err = devlink_sb_pool_type_get_from_info(info, &pool_type);
1351 if (err)
1352 return err;
1353
1354 err = devlink_sb_tc_index_get_from_info(devlink_sb, info,
1355 pool_type, &tc_index);
1356 if (err)
1357 return err;
1358
1359 err = devlink_sb_pool_index_get_from_info(devlink_sb, info,
1360 &pool_index);
1361 if (err)
1362 return err;
1363
1364 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD])
1365 return -EINVAL;
1366
1367 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]);
1368 return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index,
1369 tc_index, pool_type,
1370 pool_index, threshold);
1371}
1372
Jiri Pirkodf38daf2016-04-14 18:19:14 +02001373static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb,
1374 struct genl_info *info)
1375{
1376 struct devlink *devlink = info->user_ptr[0];
1377 struct devlink_sb *devlink_sb = info->user_ptr[1];
1378 const struct devlink_ops *ops = devlink->ops;
1379
1380 if (ops && ops->sb_occ_snapshot)
1381 return ops->sb_occ_snapshot(devlink, devlink_sb->index);
1382 return -EOPNOTSUPP;
1383}
1384
1385static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb,
1386 struct genl_info *info)
1387{
1388 struct devlink *devlink = info->user_ptr[0];
1389 struct devlink_sb *devlink_sb = info->user_ptr[1];
1390 const struct devlink_ops *ops = devlink->ops;
1391
1392 if (ops && ops->sb_occ_max_clear)
1393 return ops->sb_occ_max_clear(devlink, devlink_sb->index);
1394 return -EOPNOTSUPP;
1395}
1396
Or Gerlitz08f4b592016-07-01 14:51:01 +03001397static int devlink_eswitch_fill(struct sk_buff *msg, struct devlink *devlink,
1398 enum devlink_command cmd, u32 portid,
1399 u32 seq, int flags, u16 mode)
1400{
1401 void *hdr;
1402
1403 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
1404 if (!hdr)
1405 return -EMSGSIZE;
1406
1407 if (devlink_nl_put_handle(msg, devlink))
1408 goto nla_put_failure;
1409
1410 if (nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode))
1411 goto nla_put_failure;
1412
1413 genlmsg_end(msg, hdr);
1414 return 0;
1415
1416nla_put_failure:
1417 genlmsg_cancel(msg, hdr);
1418 return -EMSGSIZE;
1419}
1420
1421static int devlink_nl_cmd_eswitch_mode_get_doit(struct sk_buff *skb,
1422 struct genl_info *info)
1423{
1424 struct devlink *devlink = info->user_ptr[0];
1425 const struct devlink_ops *ops = devlink->ops;
1426 struct sk_buff *msg;
1427 u16 mode;
1428 int err;
1429
1430 if (!ops || !ops->eswitch_mode_get)
1431 return -EOPNOTSUPP;
1432
1433 err = ops->eswitch_mode_get(devlink, &mode);
1434 if (err)
1435 return err;
1436
1437 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
1438 if (!msg)
1439 return -ENOMEM;
1440
1441 err = devlink_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_MODE_GET,
1442 info->snd_portid, info->snd_seq, 0, mode);
1443
1444 if (err) {
1445 nlmsg_free(msg);
1446 return err;
1447 }
1448
1449 return genlmsg_reply(msg, info);
1450}
1451
1452static int devlink_nl_cmd_eswitch_mode_set_doit(struct sk_buff *skb,
1453 struct genl_info *info)
1454{
1455 struct devlink *devlink = info->user_ptr[0];
1456 const struct devlink_ops *ops = devlink->ops;
1457 u16 mode;
1458
1459 if (!info->attrs[DEVLINK_ATTR_ESWITCH_MODE])
1460 return -EINVAL;
1461
1462 mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]);
1463
1464 if (ops && ops->eswitch_mode_set)
1465 return ops->eswitch_mode_set(devlink, mode);
1466 return -EOPNOTSUPP;
1467}
1468
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001469static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
1470 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
1471 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
1472 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 },
1473 [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 },
1474 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 },
Jiri Pirkobf797472016-04-14 18:19:13 +02001475 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 },
1476 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 },
1477 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 },
1478 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 },
1479 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 },
1480 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 },
1481 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 },
Or Gerlitz08f4b592016-07-01 14:51:01 +03001482 [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 },
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001483};
1484
1485static const struct genl_ops devlink_nl_ops[] = {
1486 {
1487 .cmd = DEVLINK_CMD_GET,
1488 .doit = devlink_nl_cmd_get_doit,
1489 .dumpit = devlink_nl_cmd_get_dumpit,
1490 .policy = devlink_nl_policy,
Jiri Pirko1fc22572016-04-08 19:12:48 +02001491 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001492 /* can be retrieved by unprivileged users */
1493 },
1494 {
1495 .cmd = DEVLINK_CMD_PORT_GET,
1496 .doit = devlink_nl_cmd_port_get_doit,
1497 .dumpit = devlink_nl_cmd_port_get_dumpit,
1498 .policy = devlink_nl_policy,
1499 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
1500 /* can be retrieved by unprivileged users */
1501 },
1502 {
1503 .cmd = DEVLINK_CMD_PORT_SET,
1504 .doit = devlink_nl_cmd_port_set_doit,
1505 .policy = devlink_nl_policy,
1506 .flags = GENL_ADMIN_PERM,
1507 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
1508 },
1509 {
1510 .cmd = DEVLINK_CMD_PORT_SPLIT,
1511 .doit = devlink_nl_cmd_port_split_doit,
1512 .policy = devlink_nl_policy,
1513 .flags = GENL_ADMIN_PERM,
Jiri Pirko1fc22572016-04-08 19:12:48 +02001514 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001515 },
1516 {
1517 .cmd = DEVLINK_CMD_PORT_UNSPLIT,
1518 .doit = devlink_nl_cmd_port_unsplit_doit,
1519 .policy = devlink_nl_policy,
1520 .flags = GENL_ADMIN_PERM,
Jiri Pirko1fc22572016-04-08 19:12:48 +02001521 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001522 },
Jiri Pirkobf797472016-04-14 18:19:13 +02001523 {
1524 .cmd = DEVLINK_CMD_SB_GET,
1525 .doit = devlink_nl_cmd_sb_get_doit,
1526 .dumpit = devlink_nl_cmd_sb_get_dumpit,
1527 .policy = devlink_nl_policy,
1528 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
1529 DEVLINK_NL_FLAG_NEED_SB,
1530 /* can be retrieved by unprivileged users */
1531 },
1532 {
1533 .cmd = DEVLINK_CMD_SB_POOL_GET,
1534 .doit = devlink_nl_cmd_sb_pool_get_doit,
1535 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit,
1536 .policy = devlink_nl_policy,
1537 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
1538 DEVLINK_NL_FLAG_NEED_SB,
1539 /* can be retrieved by unprivileged users */
1540 },
1541 {
1542 .cmd = DEVLINK_CMD_SB_POOL_SET,
1543 .doit = devlink_nl_cmd_sb_pool_set_doit,
1544 .policy = devlink_nl_policy,
1545 .flags = GENL_ADMIN_PERM,
1546 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
1547 DEVLINK_NL_FLAG_NEED_SB,
1548 },
1549 {
1550 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET,
1551 .doit = devlink_nl_cmd_sb_port_pool_get_doit,
1552 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit,
1553 .policy = devlink_nl_policy,
1554 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
1555 DEVLINK_NL_FLAG_NEED_SB,
1556 /* can be retrieved by unprivileged users */
1557 },
1558 {
1559 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET,
1560 .doit = devlink_nl_cmd_sb_port_pool_set_doit,
1561 .policy = devlink_nl_policy,
1562 .flags = GENL_ADMIN_PERM,
1563 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
1564 DEVLINK_NL_FLAG_NEED_SB,
1565 },
1566 {
1567 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET,
1568 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit,
1569 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit,
1570 .policy = devlink_nl_policy,
1571 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
1572 DEVLINK_NL_FLAG_NEED_SB,
1573 /* can be retrieved by unprivileged users */
1574 },
1575 {
1576 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET,
1577 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit,
1578 .policy = devlink_nl_policy,
1579 .flags = GENL_ADMIN_PERM,
1580 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT |
1581 DEVLINK_NL_FLAG_NEED_SB,
1582 },
Jiri Pirkodf38daf2016-04-14 18:19:14 +02001583 {
1584 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT,
1585 .doit = devlink_nl_cmd_sb_occ_snapshot_doit,
1586 .policy = devlink_nl_policy,
1587 .flags = GENL_ADMIN_PERM,
1588 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
1589 DEVLINK_NL_FLAG_NEED_SB |
1590 DEVLINK_NL_FLAG_LOCK_PORTS,
1591 },
1592 {
1593 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR,
1594 .doit = devlink_nl_cmd_sb_occ_max_clear_doit,
1595 .policy = devlink_nl_policy,
1596 .flags = GENL_ADMIN_PERM,
1597 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK |
1598 DEVLINK_NL_FLAG_NEED_SB |
1599 DEVLINK_NL_FLAG_LOCK_PORTS,
1600 },
Or Gerlitz08f4b592016-07-01 14:51:01 +03001601 {
1602 .cmd = DEVLINK_CMD_ESWITCH_MODE_GET,
1603 .doit = devlink_nl_cmd_eswitch_mode_get_doit,
1604 .policy = devlink_nl_policy,
1605 .flags = GENL_ADMIN_PERM,
1606 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
1607 },
1608 {
1609 .cmd = DEVLINK_CMD_ESWITCH_MODE_SET,
1610 .doit = devlink_nl_cmd_eswitch_mode_set_doit,
1611 .policy = devlink_nl_policy,
1612 .flags = GENL_ADMIN_PERM,
1613 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK,
1614 },
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001615};
1616
1617/**
1618 * devlink_alloc - Allocate new devlink instance resources
1619 *
1620 * @ops: ops
1621 * @priv_size: size of user private data
1622 *
1623 * Allocate new devlink instance resources, including devlink index
1624 * and name.
1625 */
1626struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
1627{
1628 struct devlink *devlink;
1629
1630 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL);
1631 if (!devlink)
1632 return NULL;
1633 devlink->ops = ops;
1634 devlink_net_set(devlink, &init_net);
1635 INIT_LIST_HEAD(&devlink->port_list);
Jiri Pirkobf797472016-04-14 18:19:13 +02001636 INIT_LIST_HEAD(&devlink->sb_list);
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001637 return devlink;
1638}
1639EXPORT_SYMBOL_GPL(devlink_alloc);
1640
1641/**
1642 * devlink_register - Register devlink instance
1643 *
1644 * @devlink: devlink
1645 */
1646int devlink_register(struct devlink *devlink, struct device *dev)
1647{
1648 mutex_lock(&devlink_mutex);
1649 devlink->dev = dev;
1650 list_add_tail(&devlink->list, &devlink_list);
1651 devlink_notify(devlink, DEVLINK_CMD_NEW);
1652 mutex_unlock(&devlink_mutex);
1653 return 0;
1654}
1655EXPORT_SYMBOL_GPL(devlink_register);
1656
1657/**
1658 * devlink_unregister - Unregister devlink instance
1659 *
1660 * @devlink: devlink
1661 */
1662void devlink_unregister(struct devlink *devlink)
1663{
1664 mutex_lock(&devlink_mutex);
1665 devlink_notify(devlink, DEVLINK_CMD_DEL);
1666 list_del(&devlink->list);
1667 mutex_unlock(&devlink_mutex);
1668}
1669EXPORT_SYMBOL_GPL(devlink_unregister);
1670
1671/**
1672 * devlink_free - Free devlink instance resources
1673 *
1674 * @devlink: devlink
1675 */
1676void devlink_free(struct devlink *devlink)
1677{
1678 kfree(devlink);
1679}
1680EXPORT_SYMBOL_GPL(devlink_free);
1681
1682/**
1683 * devlink_port_register - Register devlink port
1684 *
1685 * @devlink: devlink
1686 * @devlink_port: devlink port
1687 * @port_index
1688 *
1689 * Register devlink port with provided port index. User can use
1690 * any indexing, even hw-related one. devlink_port structure
1691 * is convenient to be embedded inside user driver private structure.
1692 * Note that the caller should take care of zeroing the devlink_port
1693 * structure.
1694 */
1695int devlink_port_register(struct devlink *devlink,
1696 struct devlink_port *devlink_port,
1697 unsigned int port_index)
1698{
1699 mutex_lock(&devlink_port_mutex);
1700 if (devlink_port_index_exists(devlink, port_index)) {
1701 mutex_unlock(&devlink_port_mutex);
1702 return -EEXIST;
1703 }
1704 devlink_port->devlink = devlink;
1705 devlink_port->index = port_index;
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001706 devlink_port->registered = true;
1707 list_add_tail(&devlink_port->list, &devlink->port_list);
1708 mutex_unlock(&devlink_port_mutex);
1709 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
1710 return 0;
1711}
1712EXPORT_SYMBOL_GPL(devlink_port_register);
1713
1714/**
1715 * devlink_port_unregister - Unregister devlink port
1716 *
1717 * @devlink_port: devlink port
1718 */
1719void devlink_port_unregister(struct devlink_port *devlink_port)
1720{
1721 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
1722 mutex_lock(&devlink_port_mutex);
1723 list_del(&devlink_port->list);
1724 mutex_unlock(&devlink_port_mutex);
1725}
1726EXPORT_SYMBOL_GPL(devlink_port_unregister);
1727
1728static void __devlink_port_type_set(struct devlink_port *devlink_port,
1729 enum devlink_port_type type,
1730 void *type_dev)
1731{
1732 devlink_port->type = type;
1733 devlink_port->type_dev = type_dev;
1734 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
1735}
1736
1737/**
1738 * devlink_port_type_eth_set - Set port type to Ethernet
1739 *
1740 * @devlink_port: devlink port
1741 * @netdev: related netdevice
1742 */
1743void devlink_port_type_eth_set(struct devlink_port *devlink_port,
1744 struct net_device *netdev)
1745{
1746 return __devlink_port_type_set(devlink_port,
1747 DEVLINK_PORT_TYPE_ETH, netdev);
1748}
1749EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
1750
1751/**
1752 * devlink_port_type_ib_set - Set port type to InfiniBand
1753 *
1754 * @devlink_port: devlink port
1755 * @ibdev: related IB device
1756 */
1757void devlink_port_type_ib_set(struct devlink_port *devlink_port,
1758 struct ib_device *ibdev)
1759{
1760 return __devlink_port_type_set(devlink_port,
1761 DEVLINK_PORT_TYPE_IB, ibdev);
1762}
1763EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
1764
1765/**
1766 * devlink_port_type_clear - Clear port type
1767 *
1768 * @devlink_port: devlink port
1769 */
1770void devlink_port_type_clear(struct devlink_port *devlink_port)
1771{
1772 return __devlink_port_type_set(devlink_port,
1773 DEVLINK_PORT_TYPE_NOTSET, NULL);
1774}
1775EXPORT_SYMBOL_GPL(devlink_port_type_clear);
1776
1777/**
1778 * devlink_port_split_set - Set port is split
1779 *
1780 * @devlink_port: devlink port
1781 * @split_group: split group - identifies group split port is part of
1782 */
1783void devlink_port_split_set(struct devlink_port *devlink_port,
1784 u32 split_group)
1785{
1786 devlink_port->split = true;
1787 devlink_port->split_group = split_group;
1788 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
1789}
1790EXPORT_SYMBOL_GPL(devlink_port_split_set);
1791
Jiri Pirkobf797472016-04-14 18:19:13 +02001792int devlink_sb_register(struct devlink *devlink, unsigned int sb_index,
1793 u32 size, u16 ingress_pools_count,
1794 u16 egress_pools_count, u16 ingress_tc_count,
1795 u16 egress_tc_count)
1796{
1797 struct devlink_sb *devlink_sb;
1798 int err = 0;
1799
1800 mutex_lock(&devlink_mutex);
1801 if (devlink_sb_index_exists(devlink, sb_index)) {
1802 err = -EEXIST;
1803 goto unlock;
1804 }
1805
1806 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL);
1807 if (!devlink_sb) {
1808 err = -ENOMEM;
1809 goto unlock;
1810 }
1811 devlink_sb->index = sb_index;
1812 devlink_sb->size = size;
1813 devlink_sb->ingress_pools_count = ingress_pools_count;
1814 devlink_sb->egress_pools_count = egress_pools_count;
1815 devlink_sb->ingress_tc_count = ingress_tc_count;
1816 devlink_sb->egress_tc_count = egress_tc_count;
1817 list_add_tail(&devlink_sb->list, &devlink->sb_list);
1818unlock:
1819 mutex_unlock(&devlink_mutex);
1820 return err;
1821}
1822EXPORT_SYMBOL_GPL(devlink_sb_register);
1823
1824void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index)
1825{
1826 struct devlink_sb *devlink_sb;
1827
1828 mutex_lock(&devlink_mutex);
1829 devlink_sb = devlink_sb_get_by_index(devlink, sb_index);
1830 WARN_ON(!devlink_sb);
1831 list_del(&devlink_sb->list);
1832 mutex_unlock(&devlink_mutex);
1833 kfree(devlink_sb);
1834}
1835EXPORT_SYMBOL_GPL(devlink_sb_unregister);
1836
Jiri Pirkobfcd3a42016-02-26 17:32:23 +01001837static int __init devlink_module_init(void)
1838{
1839 return genl_register_family_with_ops_groups(&devlink_nl_family,
1840 devlink_nl_ops,
1841 devlink_nl_mcgrps);
1842}
1843
1844static void __exit devlink_module_exit(void)
1845{
1846 genl_unregister_family(&devlink_nl_family);
1847}
1848
1849module_init(devlink_module_init);
1850module_exit(devlink_module_exit);
1851
1852MODULE_LICENSE("GPL v2");
1853MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
1854MODULE_DESCRIPTION("Network physical device Netlink interface");
1855MODULE_ALIAS_GENL_FAMILY(DEVLINK_GENL_NAME);