~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/net/core/devlink.c

Version: ~ [ linux-5.4-rc7 ] ~ [ linux-5.3.11 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.84 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.154 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.201 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.201 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.77 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp