at v4.6 19 kB view raw
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);