linux/net/core/devlink.c
<<
>>
Prefs
   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
  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
 122#define DEVLINK_NL_FLAG_NEED_PORT       BIT(0)
 123
 124static int devlink_nl_pre_doit(const struct genl_ops *ops,
 125                               struct sk_buff *skb, struct genl_info *info)
 126{
 127        struct devlink *devlink;
 128
 129        mutex_lock(&devlink_mutex);
 130        devlink = devlink_get_from_info(info);
 131        if (IS_ERR(devlink)) {
 132                mutex_unlock(&devlink_mutex);
 133                return PTR_ERR(devlink);
 134        }
 135        info->user_ptr[0] = devlink;
 136        if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) {
 137                struct devlink_port *devlink_port;
 138
 139                mutex_lock(&devlink_port_mutex);
 140                devlink_port = devlink_port_get_from_info(devlink, info);
 141                if (IS_ERR(devlink_port)) {
 142                        mutex_unlock(&devlink_port_mutex);
 143                        mutex_unlock(&devlink_mutex);
 144                        return PTR_ERR(devlink_port);
 145                }
 146                info->user_ptr[1] = devlink_port;
 147        }
 148        return 0;
 149}
 150
 151static void devlink_nl_post_doit(const struct genl_ops *ops,
 152                                 struct sk_buff *skb, struct genl_info *info)
 153{
 154        if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT)
 155                mutex_unlock(&devlink_port_mutex);
 156        mutex_unlock(&devlink_mutex);
 157}
 158
 159static struct genl_family devlink_nl_family = {
 160        .id             = GENL_ID_GENERATE,
 161        .name           = DEVLINK_GENL_NAME,
 162        .version        = DEVLINK_GENL_VERSION,
 163        .maxattr        = DEVLINK_ATTR_MAX,
 164        .netnsok        = true,
 165        .pre_doit       = devlink_nl_pre_doit,
 166        .post_doit      = devlink_nl_post_doit,
 167};
 168
 169enum devlink_multicast_groups {
 170        DEVLINK_MCGRP_CONFIG,
 171};
 172
 173static const struct genl_multicast_group devlink_nl_mcgrps[] = {
 174        [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME },
 175};
 176
 177static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink)
 178{
 179        if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name))
 180                return -EMSGSIZE;
 181        if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev)))
 182                return -EMSGSIZE;
 183        return 0;
 184}
 185
 186static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink,
 187                           enum devlink_command cmd, u32 portid,
 188                           u32 seq, int flags)
 189{
 190        void *hdr;
 191
 192        hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
 193        if (!hdr)
 194                return -EMSGSIZE;
 195
 196        if (devlink_nl_put_handle(msg, devlink))
 197                goto nla_put_failure;
 198
 199        genlmsg_end(msg, hdr);
 200        return 0;
 201
 202nla_put_failure:
 203        genlmsg_cancel(msg, hdr);
 204        return -EMSGSIZE;
 205}
 206
 207static void devlink_notify(struct devlink *devlink, enum devlink_command cmd)
 208{
 209        struct sk_buff *msg;
 210        int err;
 211
 212        WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL);
 213
 214        msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 215        if (!msg)
 216                return;
 217
 218        err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0);
 219        if (err) {
 220                nlmsg_free(msg);
 221                return;
 222        }
 223
 224        genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
 225                                msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
 226}
 227
 228static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink,
 229                                struct devlink_port *devlink_port,
 230                                enum devlink_command cmd, u32 portid,
 231                                u32 seq, int flags)
 232{
 233        void *hdr;
 234
 235        hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd);
 236        if (!hdr)
 237                return -EMSGSIZE;
 238
 239        if (devlink_nl_put_handle(msg, devlink))
 240                goto nla_put_failure;
 241        if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
 242                goto nla_put_failure;
 243        if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type))
 244                goto nla_put_failure;
 245        if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET &&
 246            nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE,
 247                        devlink_port->desired_type))
 248                goto nla_put_failure;
 249        if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) {
 250                struct net_device *netdev = devlink_port->type_dev;
 251
 252                if (netdev &&
 253                    (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX,
 254                                 netdev->ifindex) ||
 255                     nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME,
 256                                    netdev->name)))
 257                        goto nla_put_failure;
 258        }
 259        if (devlink_port->type == DEVLINK_PORT_TYPE_IB) {
 260                struct ib_device *ibdev = devlink_port->type_dev;
 261
 262                if (ibdev &&
 263                    nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME,
 264                                   ibdev->name))
 265                        goto nla_put_failure;
 266        }
 267        if (devlink_port->split &&
 268            nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP,
 269                        devlink_port->split_group))
 270                goto nla_put_failure;
 271
 272        genlmsg_end(msg, hdr);
 273        return 0;
 274
 275nla_put_failure:
 276        genlmsg_cancel(msg, hdr);
 277        return -EMSGSIZE;
 278}
 279
 280static void devlink_port_notify(struct devlink_port *devlink_port,
 281                                enum devlink_command cmd)
 282{
 283        struct devlink *devlink = devlink_port->devlink;
 284        struct sk_buff *msg;
 285        int err;
 286
 287        if (!devlink_port->registered)
 288                return;
 289
 290        WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL);
 291
 292        msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 293        if (!msg)
 294                return;
 295
 296        err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0);
 297        if (err) {
 298                nlmsg_free(msg);
 299                return;
 300        }
 301
 302        genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink),
 303                                msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL);
 304}
 305
 306static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info)
 307{
 308        struct devlink *devlink = info->user_ptr[0];
 309        struct sk_buff *msg;
 310        int err;
 311
 312        msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 313        if (!msg)
 314                return -ENOMEM;
 315
 316        err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
 317                              info->snd_portid, info->snd_seq, 0);
 318        if (err) {
 319                nlmsg_free(msg);
 320                return err;
 321        }
 322
 323        return genlmsg_reply(msg, info);
 324}
 325
 326static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg,
 327                                     struct netlink_callback *cb)
 328{
 329        struct devlink *devlink;
 330        int start = cb->args[0];
 331        int idx = 0;
 332        int err;
 333
 334        mutex_lock(&devlink_mutex);
 335        list_for_each_entry(devlink, &devlink_list, list) {
 336                if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
 337                        continue;
 338                if (idx < start) {
 339                        idx++;
 340                        continue;
 341                }
 342                err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW,
 343                                      NETLINK_CB(cb->skb).portid,
 344                                      cb->nlh->nlmsg_seq, NLM_F_MULTI);
 345                if (err)
 346                        goto out;
 347                idx++;
 348        }
 349out:
 350        mutex_unlock(&devlink_mutex);
 351
 352        cb->args[0] = idx;
 353        return msg->len;
 354}
 355
 356static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb,
 357                                        struct genl_info *info)
 358{
 359        struct devlink *devlink = info->user_ptr[0];
 360        struct devlink_port *devlink_port = info->user_ptr[1];
 361        struct sk_buff *msg;
 362        int err;
 363
 364        msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
 365        if (!msg)
 366                return -ENOMEM;
 367
 368        err = devlink_nl_port_fill(msg, devlink, devlink_port,
 369                                   DEVLINK_CMD_PORT_NEW,
 370                                   info->snd_portid, info->snd_seq, 0);
 371        if (err) {
 372                nlmsg_free(msg);
 373                return err;
 374        }
 375
 376        return genlmsg_reply(msg, info);
 377}
 378
 379static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg,
 380                                          struct netlink_callback *cb)
 381{
 382        struct devlink *devlink;
 383        struct devlink_port *devlink_port;
 384        int start = cb->args[0];
 385        int idx = 0;
 386        int err;
 387
 388        mutex_lock(&devlink_mutex);
 389        mutex_lock(&devlink_port_mutex);
 390        list_for_each_entry(devlink, &devlink_list, list) {
 391                if (!net_eq(devlink_net(devlink), sock_net(msg->sk)))
 392                        continue;
 393                list_for_each_entry(devlink_port, &devlink->port_list, list) {
 394                        if (idx < start) {
 395                                idx++;
 396                                continue;
 397                        }
 398                        err = devlink_nl_port_fill(msg, devlink, devlink_port,
 399                                                   DEVLINK_CMD_NEW,
 400                                                   NETLINK_CB(cb->skb).portid,
 401                                                   cb->nlh->nlmsg_seq,
 402                                                   NLM_F_MULTI);
 403                        if (err)
 404                                goto out;
 405                        idx++;
 406                }
 407        }
 408out:
 409        mutex_unlock(&devlink_port_mutex);
 410        mutex_unlock(&devlink_mutex);
 411
 412        cb->args[0] = idx;
 413        return msg->len;
 414}
 415
 416static int devlink_port_type_set(struct devlink *devlink,
 417                                 struct devlink_port *devlink_port,
 418                                 enum devlink_port_type port_type)
 419
 420{
 421        int err;
 422
 423        if (devlink->ops && devlink->ops->port_type_set) {
 424                if (port_type == DEVLINK_PORT_TYPE_NOTSET)
 425                        return -EINVAL;
 426                err = devlink->ops->port_type_set(devlink_port, port_type);
 427                if (err)
 428                        return err;
 429                devlink_port->desired_type = port_type;
 430                devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
 431                return 0;
 432        }
 433        return -EOPNOTSUPP;
 434}
 435
 436static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb,
 437                                        struct genl_info *info)
 438{
 439        struct devlink *devlink = info->user_ptr[0];
 440        struct devlink_port *devlink_port = info->user_ptr[1];
 441        int err;
 442
 443        if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) {
 444                enum devlink_port_type port_type;
 445
 446                port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]);
 447                err = devlink_port_type_set(devlink, devlink_port, port_type);
 448                if (err)
 449                        return err;
 450        }
 451        return 0;
 452}
 453
 454static int devlink_port_split(struct devlink *devlink,
 455                              u32 port_index, u32 count)
 456
 457{
 458        if (devlink->ops && devlink->ops->port_split)
 459                return devlink->ops->port_split(devlink, port_index, count);
 460        return -EOPNOTSUPP;
 461}
 462
 463static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb,
 464                                          struct genl_info *info)
 465{
 466        struct devlink *devlink = info->user_ptr[0];
 467        u32 port_index;
 468        u32 count;
 469
 470        if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] ||
 471            !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT])
 472                return -EINVAL;
 473
 474        port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
 475        count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]);
 476        return devlink_port_split(devlink, port_index, count);
 477}
 478
 479static int devlink_port_unsplit(struct devlink *devlink, u32 port_index)
 480
 481{
 482        if (devlink->ops && devlink->ops->port_unsplit)
 483                return devlink->ops->port_unsplit(devlink, port_index);
 484        return -EOPNOTSUPP;
 485}
 486
 487static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb,
 488                                            struct genl_info *info)
 489{
 490        struct devlink *devlink = info->user_ptr[0];
 491        u32 port_index;
 492
 493        if (!info->attrs[DEVLINK_ATTR_PORT_INDEX])
 494                return -EINVAL;
 495
 496        port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]);
 497        return devlink_port_unsplit(devlink, port_index);
 498}
 499
 500static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = {
 501        [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING },
 502        [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING },
 503        [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 },
 504        [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 },
 505        [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 },
 506};
 507
 508static const struct genl_ops devlink_nl_ops[] = {
 509        {
 510                .cmd = DEVLINK_CMD_GET,
 511                .doit = devlink_nl_cmd_get_doit,
 512                .dumpit = devlink_nl_cmd_get_dumpit,
 513                .policy = devlink_nl_policy,
 514                /* can be retrieved by unprivileged users */
 515        },
 516        {
 517                .cmd = DEVLINK_CMD_PORT_GET,
 518                .doit = devlink_nl_cmd_port_get_doit,
 519                .dumpit = devlink_nl_cmd_port_get_dumpit,
 520                .policy = devlink_nl_policy,
 521                .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
 522                /* can be retrieved by unprivileged users */
 523        },
 524        {
 525                .cmd = DEVLINK_CMD_PORT_SET,
 526                .doit = devlink_nl_cmd_port_set_doit,
 527                .policy = devlink_nl_policy,
 528                .flags = GENL_ADMIN_PERM,
 529                .internal_flags = DEVLINK_NL_FLAG_NEED_PORT,
 530        },
 531        {
 532                .cmd = DEVLINK_CMD_PORT_SPLIT,
 533                .doit = devlink_nl_cmd_port_split_doit,
 534                .policy = devlink_nl_policy,
 535                .flags = GENL_ADMIN_PERM,
 536        },
 537        {
 538                .cmd = DEVLINK_CMD_PORT_UNSPLIT,
 539                .doit = devlink_nl_cmd_port_unsplit_doit,
 540                .policy = devlink_nl_policy,
 541                .flags = GENL_ADMIN_PERM,
 542        },
 543};
 544
 545/**
 546 *      devlink_alloc - Allocate new devlink instance resources
 547 *
 548 *      @ops: ops
 549 *      @priv_size: size of user private data
 550 *
 551 *      Allocate new devlink instance resources, including devlink index
 552 *      and name.
 553 */
 554struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size)
 555{
 556        struct devlink *devlink;
 557
 558        devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL);
 559        if (!devlink)
 560                return NULL;
 561        devlink->ops = ops;
 562        devlink_net_set(devlink, &init_net);
 563        INIT_LIST_HEAD(&devlink->port_list);
 564        return devlink;
 565}
 566EXPORT_SYMBOL_GPL(devlink_alloc);
 567
 568/**
 569 *      devlink_register - Register devlink instance
 570 *
 571 *      @devlink: devlink
 572 */
 573int devlink_register(struct devlink *devlink, struct device *dev)
 574{
 575        mutex_lock(&devlink_mutex);
 576        devlink->dev = dev;
 577        list_add_tail(&devlink->list, &devlink_list);
 578        devlink_notify(devlink, DEVLINK_CMD_NEW);
 579        mutex_unlock(&devlink_mutex);
 580        return 0;
 581}
 582EXPORT_SYMBOL_GPL(devlink_register);
 583
 584/**
 585 *      devlink_unregister - Unregister devlink instance
 586 *
 587 *      @devlink: devlink
 588 */
 589void devlink_unregister(struct devlink *devlink)
 590{
 591        mutex_lock(&devlink_mutex);
 592        devlink_notify(devlink, DEVLINK_CMD_DEL);
 593        list_del(&devlink->list);
 594        mutex_unlock(&devlink_mutex);
 595}
 596EXPORT_SYMBOL_GPL(devlink_unregister);
 597
 598/**
 599 *      devlink_free - Free devlink instance resources
 600 *
 601 *      @devlink: devlink
 602 */
 603void devlink_free(struct devlink *devlink)
 604{
 605        kfree(devlink);
 606}
 607EXPORT_SYMBOL_GPL(devlink_free);
 608
 609/**
 610 *      devlink_port_register - Register devlink port
 611 *
 612 *      @devlink: devlink
 613 *      @devlink_port: devlink port
 614 *      @port_index
 615 *
 616 *      Register devlink port with provided port index. User can use
 617 *      any indexing, even hw-related one. devlink_port structure
 618 *      is convenient to be embedded inside user driver private structure.
 619 *      Note that the caller should take care of zeroing the devlink_port
 620 *      structure.
 621 */
 622int devlink_port_register(struct devlink *devlink,
 623                          struct devlink_port *devlink_port,
 624                          unsigned int port_index)
 625{
 626        mutex_lock(&devlink_port_mutex);
 627        if (devlink_port_index_exists(devlink, port_index)) {
 628                mutex_unlock(&devlink_port_mutex);
 629                return -EEXIST;
 630        }
 631        devlink_port->devlink = devlink;
 632        devlink_port->index = port_index;
 633        devlink_port->type = DEVLINK_PORT_TYPE_NOTSET;
 634        devlink_port->registered = true;
 635        list_add_tail(&devlink_port->list, &devlink->port_list);
 636        mutex_unlock(&devlink_port_mutex);
 637        devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
 638        return 0;
 639}
 640EXPORT_SYMBOL_GPL(devlink_port_register);
 641
 642/**
 643 *      devlink_port_unregister - Unregister devlink port
 644 *
 645 *      @devlink_port: devlink port
 646 */
 647void devlink_port_unregister(struct devlink_port *devlink_port)
 648{
 649        devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL);
 650        mutex_lock(&devlink_port_mutex);
 651        list_del(&devlink_port->list);
 652        mutex_unlock(&devlink_port_mutex);
 653}
 654EXPORT_SYMBOL_GPL(devlink_port_unregister);
 655
 656static void __devlink_port_type_set(struct devlink_port *devlink_port,
 657                                    enum devlink_port_type type,
 658                                    void *type_dev)
 659{
 660        devlink_port->type = type;
 661        devlink_port->type_dev = type_dev;
 662        devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
 663}
 664
 665/**
 666 *      devlink_port_type_eth_set - Set port type to Ethernet
 667 *
 668 *      @devlink_port: devlink port
 669 *      @netdev: related netdevice
 670 */
 671void devlink_port_type_eth_set(struct devlink_port *devlink_port,
 672                               struct net_device *netdev)
 673{
 674        return __devlink_port_type_set(devlink_port,
 675                                       DEVLINK_PORT_TYPE_ETH, netdev);
 676}
 677EXPORT_SYMBOL_GPL(devlink_port_type_eth_set);
 678
 679/**
 680 *      devlink_port_type_ib_set - Set port type to InfiniBand
 681 *
 682 *      @devlink_port: devlink port
 683 *      @ibdev: related IB device
 684 */
 685void devlink_port_type_ib_set(struct devlink_port *devlink_port,
 686                              struct ib_device *ibdev)
 687{
 688        return __devlink_port_type_set(devlink_port,
 689                                       DEVLINK_PORT_TYPE_IB, ibdev);
 690}
 691EXPORT_SYMBOL_GPL(devlink_port_type_ib_set);
 692
 693/**
 694 *      devlink_port_type_clear - Clear port type
 695 *
 696 *      @devlink_port: devlink port
 697 */
 698void devlink_port_type_clear(struct devlink_port *devlink_port)
 699{
 700        return __devlink_port_type_set(devlink_port,
 701                                       DEVLINK_PORT_TYPE_NOTSET, NULL);
 702}
 703EXPORT_SYMBOL_GPL(devlink_port_type_clear);
 704
 705/**
 706 *      devlink_port_split_set - Set port is split
 707 *
 708 *      @devlink_port: devlink port
 709 *      @split_group: split group - identifies group split port is part of
 710 */
 711void devlink_port_split_set(struct devlink_port *devlink_port,
 712                            u32 split_group)
 713{
 714        devlink_port->split = true;
 715        devlink_port->split_group = split_group;
 716        devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW);
 717}
 718EXPORT_SYMBOL_GPL(devlink_port_split_set);
 719
 720static int __init devlink_module_init(void)
 721{
 722        return genl_register_family_with_ops_groups(&devlink_nl_family,
 723                                                    devlink_nl_ops,
 724                                                    devlink_nl_mcgrps);
 725}
 726
 727static void __exit devlink_module_exit(void)
 728{
 729        genl_unregister_family(&devlink_nl_family);
 730}
 731
 732module_init(devlink_module_init);
 733module_exit(devlink_module_exit);
 734
 735MODULE_LICENSE("GPL v2");
 736MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
 737MODULE_DESCRIPTION("Network physical device Netlink interface");
 738MODULE_ALIAS_GENL_FAMILY(DEVLINK_GENL_NAME);
 739