at v4.16 86 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#define CREATE_TRACE_POINTS 30#include <trace/events/devlink.h> 31 32static struct devlink_dpipe_field devlink_dpipe_fields_ethernet[] = { 33 { 34 .name = "destination mac", 35 .id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC, 36 .bitwidth = 48, 37 }, 38}; 39 40struct devlink_dpipe_header devlink_dpipe_header_ethernet = { 41 .name = "ethernet", 42 .id = DEVLINK_DPIPE_HEADER_ETHERNET, 43 .fields = devlink_dpipe_fields_ethernet, 44 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ethernet), 45 .global = true, 46}; 47EXPORT_SYMBOL(devlink_dpipe_header_ethernet); 48 49static struct devlink_dpipe_field devlink_dpipe_fields_ipv4[] = { 50 { 51 .name = "destination ip", 52 .id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP, 53 .bitwidth = 32, 54 }, 55}; 56 57struct devlink_dpipe_header devlink_dpipe_header_ipv4 = { 58 .name = "ipv4", 59 .id = DEVLINK_DPIPE_HEADER_IPV4, 60 .fields = devlink_dpipe_fields_ipv4, 61 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv4), 62 .global = true, 63}; 64EXPORT_SYMBOL(devlink_dpipe_header_ipv4); 65 66static struct devlink_dpipe_field devlink_dpipe_fields_ipv6[] = { 67 { 68 .name = "destination ip", 69 .id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP, 70 .bitwidth = 128, 71 }, 72}; 73 74struct devlink_dpipe_header devlink_dpipe_header_ipv6 = { 75 .name = "ipv6", 76 .id = DEVLINK_DPIPE_HEADER_IPV6, 77 .fields = devlink_dpipe_fields_ipv6, 78 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv6), 79 .global = true, 80}; 81EXPORT_SYMBOL(devlink_dpipe_header_ipv6); 82 83EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg); 84 85static LIST_HEAD(devlink_list); 86 87/* devlink_mutex 88 * 89 * An overall lock guarding every operation coming from userspace. 90 * It also guards devlink devices list and it is taken when 91 * driver registers/unregisters it. 92 */ 93static DEFINE_MUTEX(devlink_mutex); 94 95static struct net *devlink_net(const struct devlink *devlink) 96{ 97 return read_pnet(&devlink->_net); 98} 99 100static void devlink_net_set(struct devlink *devlink, struct net *net) 101{ 102 write_pnet(&devlink->_net, net); 103} 104 105static struct devlink *devlink_get_from_attrs(struct net *net, 106 struct nlattr **attrs) 107{ 108 struct devlink *devlink; 109 char *busname; 110 char *devname; 111 112 if (!attrs[DEVLINK_ATTR_BUS_NAME] || !attrs[DEVLINK_ATTR_DEV_NAME]) 113 return ERR_PTR(-EINVAL); 114 115 busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]); 116 devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]); 117 118 list_for_each_entry(devlink, &devlink_list, list) { 119 if (strcmp(devlink->dev->bus->name, busname) == 0 && 120 strcmp(dev_name(devlink->dev), devname) == 0 && 121 net_eq(devlink_net(devlink), net)) 122 return devlink; 123 } 124 125 return ERR_PTR(-ENODEV); 126} 127 128static struct devlink *devlink_get_from_info(struct genl_info *info) 129{ 130 return devlink_get_from_attrs(genl_info_net(info), info->attrs); 131} 132 133static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink, 134 int port_index) 135{ 136 struct devlink_port *devlink_port; 137 138 list_for_each_entry(devlink_port, &devlink->port_list, list) { 139 if (devlink_port->index == port_index) 140 return devlink_port; 141 } 142 return NULL; 143} 144 145static bool devlink_port_index_exists(struct devlink *devlink, int port_index) 146{ 147 return devlink_port_get_by_index(devlink, port_index); 148} 149 150static struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink, 151 struct nlattr **attrs) 152{ 153 if (attrs[DEVLINK_ATTR_PORT_INDEX]) { 154 u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]); 155 struct devlink_port *devlink_port; 156 157 devlink_port = devlink_port_get_by_index(devlink, port_index); 158 if (!devlink_port) 159 return ERR_PTR(-ENODEV); 160 return devlink_port; 161 } 162 return ERR_PTR(-EINVAL); 163} 164 165static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink, 166 struct genl_info *info) 167{ 168 return devlink_port_get_from_attrs(devlink, info->attrs); 169} 170 171struct devlink_sb { 172 struct list_head list; 173 unsigned int index; 174 u32 size; 175 u16 ingress_pools_count; 176 u16 egress_pools_count; 177 u16 ingress_tc_count; 178 u16 egress_tc_count; 179}; 180 181static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb) 182{ 183 return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count; 184} 185 186static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink, 187 unsigned int sb_index) 188{ 189 struct devlink_sb *devlink_sb; 190 191 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 192 if (devlink_sb->index == sb_index) 193 return devlink_sb; 194 } 195 return NULL; 196} 197 198static bool devlink_sb_index_exists(struct devlink *devlink, 199 unsigned int sb_index) 200{ 201 return devlink_sb_get_by_index(devlink, sb_index); 202} 203 204static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink, 205 struct nlattr **attrs) 206{ 207 if (attrs[DEVLINK_ATTR_SB_INDEX]) { 208 u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]); 209 struct devlink_sb *devlink_sb; 210 211 devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 212 if (!devlink_sb) 213 return ERR_PTR(-ENODEV); 214 return devlink_sb; 215 } 216 return ERR_PTR(-EINVAL); 217} 218 219static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink, 220 struct genl_info *info) 221{ 222 return devlink_sb_get_from_attrs(devlink, info->attrs); 223} 224 225static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb, 226 struct nlattr **attrs, 227 u16 *p_pool_index) 228{ 229 u16 val; 230 231 if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX]) 232 return -EINVAL; 233 234 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]); 235 if (val >= devlink_sb_pool_count(devlink_sb)) 236 return -EINVAL; 237 *p_pool_index = val; 238 return 0; 239} 240 241static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb, 242 struct genl_info *info, 243 u16 *p_pool_index) 244{ 245 return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs, 246 p_pool_index); 247} 248 249static int 250devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs, 251 enum devlink_sb_pool_type *p_pool_type) 252{ 253 u8 val; 254 255 if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE]) 256 return -EINVAL; 257 258 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]); 259 if (val != DEVLINK_SB_POOL_TYPE_INGRESS && 260 val != DEVLINK_SB_POOL_TYPE_EGRESS) 261 return -EINVAL; 262 *p_pool_type = val; 263 return 0; 264} 265 266static int 267devlink_sb_pool_type_get_from_info(struct genl_info *info, 268 enum devlink_sb_pool_type *p_pool_type) 269{ 270 return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type); 271} 272 273static int 274devlink_sb_th_type_get_from_attrs(struct nlattr **attrs, 275 enum devlink_sb_threshold_type *p_th_type) 276{ 277 u8 val; 278 279 if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]) 280 return -EINVAL; 281 282 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]); 283 if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC && 284 val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC) 285 return -EINVAL; 286 *p_th_type = val; 287 return 0; 288} 289 290static int 291devlink_sb_th_type_get_from_info(struct genl_info *info, 292 enum devlink_sb_threshold_type *p_th_type) 293{ 294 return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type); 295} 296 297static int 298devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb, 299 struct nlattr **attrs, 300 enum devlink_sb_pool_type pool_type, 301 u16 *p_tc_index) 302{ 303 u16 val; 304 305 if (!attrs[DEVLINK_ATTR_SB_TC_INDEX]) 306 return -EINVAL; 307 308 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]); 309 if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS && 310 val >= devlink_sb->ingress_tc_count) 311 return -EINVAL; 312 if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS && 313 val >= devlink_sb->egress_tc_count) 314 return -EINVAL; 315 *p_tc_index = val; 316 return 0; 317} 318 319static int 320devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb, 321 struct genl_info *info, 322 enum devlink_sb_pool_type pool_type, 323 u16 *p_tc_index) 324{ 325 return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs, 326 pool_type, p_tc_index); 327} 328 329#define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0) 330#define DEVLINK_NL_FLAG_NEED_PORT BIT(1) 331#define DEVLINK_NL_FLAG_NEED_SB BIT(2) 332 333/* The per devlink instance lock is taken by default in the pre-doit 334 * operation, yet several commands do not require this. The global 335 * devlink lock is taken and protects from disruption by user-calls. 336 */ 337#define DEVLINK_NL_FLAG_NO_LOCK BIT(3) 338 339static int devlink_nl_pre_doit(const struct genl_ops *ops, 340 struct sk_buff *skb, struct genl_info *info) 341{ 342 struct devlink *devlink; 343 int err; 344 345 mutex_lock(&devlink_mutex); 346 devlink = devlink_get_from_info(info); 347 if (IS_ERR(devlink)) { 348 mutex_unlock(&devlink_mutex); 349 return PTR_ERR(devlink); 350 } 351 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 352 mutex_lock(&devlink->lock); 353 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) { 354 info->user_ptr[0] = devlink; 355 } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) { 356 struct devlink_port *devlink_port; 357 358 devlink_port = devlink_port_get_from_info(devlink, info); 359 if (IS_ERR(devlink_port)) { 360 err = PTR_ERR(devlink_port); 361 goto unlock; 362 } 363 info->user_ptr[0] = devlink_port; 364 } 365 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) { 366 struct devlink_sb *devlink_sb; 367 368 devlink_sb = devlink_sb_get_from_info(devlink, info); 369 if (IS_ERR(devlink_sb)) { 370 err = PTR_ERR(devlink_sb); 371 goto unlock; 372 } 373 info->user_ptr[1] = devlink_sb; 374 } 375 return 0; 376 377unlock: 378 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 379 mutex_unlock(&devlink->lock); 380 mutex_unlock(&devlink_mutex); 381 return err; 382} 383 384static void devlink_nl_post_doit(const struct genl_ops *ops, 385 struct sk_buff *skb, struct genl_info *info) 386{ 387 struct devlink *devlink; 388 389 devlink = devlink_get_from_info(info); 390 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 391 mutex_unlock(&devlink->lock); 392 mutex_unlock(&devlink_mutex); 393} 394 395static struct genl_family devlink_nl_family; 396 397enum devlink_multicast_groups { 398 DEVLINK_MCGRP_CONFIG, 399}; 400 401static const struct genl_multicast_group devlink_nl_mcgrps[] = { 402 [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME }, 403}; 404 405static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink) 406{ 407 if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name)) 408 return -EMSGSIZE; 409 if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev))) 410 return -EMSGSIZE; 411 return 0; 412} 413 414static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink, 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 427 genlmsg_end(msg, hdr); 428 return 0; 429 430nla_put_failure: 431 genlmsg_cancel(msg, hdr); 432 return -EMSGSIZE; 433} 434 435static void devlink_notify(struct devlink *devlink, enum devlink_command cmd) 436{ 437 struct sk_buff *msg; 438 int err; 439 440 WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL); 441 442 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 443 if (!msg) 444 return; 445 446 err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0); 447 if (err) { 448 nlmsg_free(msg); 449 return; 450 } 451 452 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 453 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 454} 455 456static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink, 457 struct devlink_port *devlink_port, 458 enum devlink_command cmd, u32 portid, 459 u32 seq, int flags) 460{ 461 void *hdr; 462 463 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 464 if (!hdr) 465 return -EMSGSIZE; 466 467 if (devlink_nl_put_handle(msg, devlink)) 468 goto nla_put_failure; 469 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 470 goto nla_put_failure; 471 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type)) 472 goto nla_put_failure; 473 if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET && 474 nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE, 475 devlink_port->desired_type)) 476 goto nla_put_failure; 477 if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) { 478 struct net_device *netdev = devlink_port->type_dev; 479 480 if (netdev && 481 (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX, 482 netdev->ifindex) || 483 nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME, 484 netdev->name))) 485 goto nla_put_failure; 486 } 487 if (devlink_port->type == DEVLINK_PORT_TYPE_IB) { 488 struct ib_device *ibdev = devlink_port->type_dev; 489 490 if (ibdev && 491 nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME, 492 ibdev->name)) 493 goto nla_put_failure; 494 } 495 if (devlink_port->split && 496 nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP, 497 devlink_port->split_group)) 498 goto nla_put_failure; 499 500 genlmsg_end(msg, hdr); 501 return 0; 502 503nla_put_failure: 504 genlmsg_cancel(msg, hdr); 505 return -EMSGSIZE; 506} 507 508static void devlink_port_notify(struct devlink_port *devlink_port, 509 enum devlink_command cmd) 510{ 511 struct devlink *devlink = devlink_port->devlink; 512 struct sk_buff *msg; 513 int err; 514 515 if (!devlink_port->registered) 516 return; 517 518 WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL); 519 520 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 521 if (!msg) 522 return; 523 524 err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0); 525 if (err) { 526 nlmsg_free(msg); 527 return; 528 } 529 530 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 531 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 532} 533 534static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info) 535{ 536 struct devlink *devlink = info->user_ptr[0]; 537 struct sk_buff *msg; 538 int err; 539 540 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 541 if (!msg) 542 return -ENOMEM; 543 544 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW, 545 info->snd_portid, info->snd_seq, 0); 546 if (err) { 547 nlmsg_free(msg); 548 return err; 549 } 550 551 return genlmsg_reply(msg, info); 552} 553 554static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg, 555 struct netlink_callback *cb) 556{ 557 struct devlink *devlink; 558 int start = cb->args[0]; 559 int idx = 0; 560 int err; 561 562 mutex_lock(&devlink_mutex); 563 list_for_each_entry(devlink, &devlink_list, list) { 564 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 565 continue; 566 if (idx < start) { 567 idx++; 568 continue; 569 } 570 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW, 571 NETLINK_CB(cb->skb).portid, 572 cb->nlh->nlmsg_seq, NLM_F_MULTI); 573 if (err) 574 goto out; 575 idx++; 576 } 577out: 578 mutex_unlock(&devlink_mutex); 579 580 cb->args[0] = idx; 581 return msg->len; 582} 583 584static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb, 585 struct genl_info *info) 586{ 587 struct devlink_port *devlink_port = info->user_ptr[0]; 588 struct devlink *devlink = devlink_port->devlink; 589 struct sk_buff *msg; 590 int err; 591 592 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 593 if (!msg) 594 return -ENOMEM; 595 596 err = devlink_nl_port_fill(msg, devlink, devlink_port, 597 DEVLINK_CMD_PORT_NEW, 598 info->snd_portid, info->snd_seq, 0); 599 if (err) { 600 nlmsg_free(msg); 601 return err; 602 } 603 604 return genlmsg_reply(msg, info); 605} 606 607static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg, 608 struct netlink_callback *cb) 609{ 610 struct devlink *devlink; 611 struct devlink_port *devlink_port; 612 int start = cb->args[0]; 613 int idx = 0; 614 int err; 615 616 mutex_lock(&devlink_mutex); 617 list_for_each_entry(devlink, &devlink_list, list) { 618 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 619 continue; 620 mutex_lock(&devlink->lock); 621 list_for_each_entry(devlink_port, &devlink->port_list, list) { 622 if (idx < start) { 623 idx++; 624 continue; 625 } 626 err = devlink_nl_port_fill(msg, devlink, devlink_port, 627 DEVLINK_CMD_NEW, 628 NETLINK_CB(cb->skb).portid, 629 cb->nlh->nlmsg_seq, 630 NLM_F_MULTI); 631 if (err) { 632 mutex_unlock(&devlink->lock); 633 goto out; 634 } 635 idx++; 636 } 637 mutex_unlock(&devlink->lock); 638 } 639out: 640 mutex_unlock(&devlink_mutex); 641 642 cb->args[0] = idx; 643 return msg->len; 644} 645 646static int devlink_port_type_set(struct devlink *devlink, 647 struct devlink_port *devlink_port, 648 enum devlink_port_type port_type) 649 650{ 651 int err; 652 653 if (devlink->ops && devlink->ops->port_type_set) { 654 if (port_type == DEVLINK_PORT_TYPE_NOTSET) 655 return -EINVAL; 656 if (port_type == devlink_port->type) 657 return 0; 658 err = devlink->ops->port_type_set(devlink_port, port_type); 659 if (err) 660 return err; 661 devlink_port->desired_type = port_type; 662 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 663 return 0; 664 } 665 return -EOPNOTSUPP; 666} 667 668static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb, 669 struct genl_info *info) 670{ 671 struct devlink_port *devlink_port = info->user_ptr[0]; 672 struct devlink *devlink = devlink_port->devlink; 673 int err; 674 675 if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) { 676 enum devlink_port_type port_type; 677 678 port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]); 679 err = devlink_port_type_set(devlink, devlink_port, port_type); 680 if (err) 681 return err; 682 } 683 return 0; 684} 685 686static int devlink_port_split(struct devlink *devlink, 687 u32 port_index, u32 count) 688 689{ 690 if (devlink->ops && devlink->ops->port_split) 691 return devlink->ops->port_split(devlink, port_index, count); 692 return -EOPNOTSUPP; 693} 694 695static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb, 696 struct genl_info *info) 697{ 698 struct devlink *devlink = info->user_ptr[0]; 699 u32 port_index; 700 u32 count; 701 702 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] || 703 !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]) 704 return -EINVAL; 705 706 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 707 count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]); 708 return devlink_port_split(devlink, port_index, count); 709} 710 711static int devlink_port_unsplit(struct devlink *devlink, u32 port_index) 712 713{ 714 if (devlink->ops && devlink->ops->port_unsplit) 715 return devlink->ops->port_unsplit(devlink, port_index); 716 return -EOPNOTSUPP; 717} 718 719static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb, 720 struct genl_info *info) 721{ 722 struct devlink *devlink = info->user_ptr[0]; 723 u32 port_index; 724 725 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX]) 726 return -EINVAL; 727 728 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 729 return devlink_port_unsplit(devlink, port_index); 730} 731 732static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink, 733 struct devlink_sb *devlink_sb, 734 enum devlink_command cmd, u32 portid, 735 u32 seq, int flags) 736{ 737 void *hdr; 738 739 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 740 if (!hdr) 741 return -EMSGSIZE; 742 743 if (devlink_nl_put_handle(msg, devlink)) 744 goto nla_put_failure; 745 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 746 goto nla_put_failure; 747 if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size)) 748 goto nla_put_failure; 749 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT, 750 devlink_sb->ingress_pools_count)) 751 goto nla_put_failure; 752 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT, 753 devlink_sb->egress_pools_count)) 754 goto nla_put_failure; 755 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT, 756 devlink_sb->ingress_tc_count)) 757 goto nla_put_failure; 758 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT, 759 devlink_sb->egress_tc_count)) 760 goto nla_put_failure; 761 762 genlmsg_end(msg, hdr); 763 return 0; 764 765nla_put_failure: 766 genlmsg_cancel(msg, hdr); 767 return -EMSGSIZE; 768} 769 770static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb, 771 struct genl_info *info) 772{ 773 struct devlink *devlink = info->user_ptr[0]; 774 struct devlink_sb *devlink_sb = info->user_ptr[1]; 775 struct sk_buff *msg; 776 int err; 777 778 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 779 if (!msg) 780 return -ENOMEM; 781 782 err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 783 DEVLINK_CMD_SB_NEW, 784 info->snd_portid, info->snd_seq, 0); 785 if (err) { 786 nlmsg_free(msg); 787 return err; 788 } 789 790 return genlmsg_reply(msg, info); 791} 792 793static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg, 794 struct netlink_callback *cb) 795{ 796 struct devlink *devlink; 797 struct devlink_sb *devlink_sb; 798 int start = cb->args[0]; 799 int idx = 0; 800 int err; 801 802 mutex_lock(&devlink_mutex); 803 list_for_each_entry(devlink, &devlink_list, list) { 804 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 805 continue; 806 mutex_lock(&devlink->lock); 807 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 808 if (idx < start) { 809 idx++; 810 continue; 811 } 812 err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 813 DEVLINK_CMD_SB_NEW, 814 NETLINK_CB(cb->skb).portid, 815 cb->nlh->nlmsg_seq, 816 NLM_F_MULTI); 817 if (err) { 818 mutex_unlock(&devlink->lock); 819 goto out; 820 } 821 idx++; 822 } 823 mutex_unlock(&devlink->lock); 824 } 825out: 826 mutex_unlock(&devlink_mutex); 827 828 cb->args[0] = idx; 829 return msg->len; 830} 831 832static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink, 833 struct devlink_sb *devlink_sb, 834 u16 pool_index, enum devlink_command cmd, 835 u32 portid, u32 seq, int flags) 836{ 837 struct devlink_sb_pool_info pool_info; 838 void *hdr; 839 int err; 840 841 err = devlink->ops->sb_pool_get(devlink, devlink_sb->index, 842 pool_index, &pool_info); 843 if (err) 844 return err; 845 846 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 847 if (!hdr) 848 return -EMSGSIZE; 849 850 if (devlink_nl_put_handle(msg, devlink)) 851 goto nla_put_failure; 852 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 853 goto nla_put_failure; 854 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 855 goto nla_put_failure; 856 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type)) 857 goto nla_put_failure; 858 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size)) 859 goto nla_put_failure; 860 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, 861 pool_info.threshold_type)) 862 goto nla_put_failure; 863 864 genlmsg_end(msg, hdr); 865 return 0; 866 867nla_put_failure: 868 genlmsg_cancel(msg, hdr); 869 return -EMSGSIZE; 870} 871 872static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb, 873 struct genl_info *info) 874{ 875 struct devlink *devlink = info->user_ptr[0]; 876 struct devlink_sb *devlink_sb = info->user_ptr[1]; 877 struct sk_buff *msg; 878 u16 pool_index; 879 int err; 880 881 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 882 &pool_index); 883 if (err) 884 return err; 885 886 if (!devlink->ops || !devlink->ops->sb_pool_get) 887 return -EOPNOTSUPP; 888 889 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 890 if (!msg) 891 return -ENOMEM; 892 893 err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index, 894 DEVLINK_CMD_SB_POOL_NEW, 895 info->snd_portid, info->snd_seq, 0); 896 if (err) { 897 nlmsg_free(msg); 898 return err; 899 } 900 901 return genlmsg_reply(msg, info); 902} 903 904static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 905 struct devlink *devlink, 906 struct devlink_sb *devlink_sb, 907 u32 portid, u32 seq) 908{ 909 u16 pool_count = devlink_sb_pool_count(devlink_sb); 910 u16 pool_index; 911 int err; 912 913 for (pool_index = 0; pool_index < pool_count; pool_index++) { 914 if (*p_idx < start) { 915 (*p_idx)++; 916 continue; 917 } 918 err = devlink_nl_sb_pool_fill(msg, devlink, 919 devlink_sb, 920 pool_index, 921 DEVLINK_CMD_SB_POOL_NEW, 922 portid, seq, NLM_F_MULTI); 923 if (err) 924 return err; 925 (*p_idx)++; 926 } 927 return 0; 928} 929 930static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg, 931 struct netlink_callback *cb) 932{ 933 struct devlink *devlink; 934 struct devlink_sb *devlink_sb; 935 int start = cb->args[0]; 936 int idx = 0; 937 int err; 938 939 mutex_lock(&devlink_mutex); 940 list_for_each_entry(devlink, &devlink_list, list) { 941 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 942 !devlink->ops || !devlink->ops->sb_pool_get) 943 continue; 944 mutex_lock(&devlink->lock); 945 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 946 err = __sb_pool_get_dumpit(msg, start, &idx, devlink, 947 devlink_sb, 948 NETLINK_CB(cb->skb).portid, 949 cb->nlh->nlmsg_seq); 950 if (err && err != -EOPNOTSUPP) { 951 mutex_unlock(&devlink->lock); 952 goto out; 953 } 954 } 955 mutex_unlock(&devlink->lock); 956 } 957out: 958 mutex_unlock(&devlink_mutex); 959 960 cb->args[0] = idx; 961 return msg->len; 962} 963 964static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index, 965 u16 pool_index, u32 size, 966 enum devlink_sb_threshold_type threshold_type) 967 968{ 969 const struct devlink_ops *ops = devlink->ops; 970 971 if (ops && ops->sb_pool_set) 972 return ops->sb_pool_set(devlink, sb_index, pool_index, 973 size, threshold_type); 974 return -EOPNOTSUPP; 975} 976 977static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb, 978 struct genl_info *info) 979{ 980 struct devlink *devlink = info->user_ptr[0]; 981 struct devlink_sb *devlink_sb = info->user_ptr[1]; 982 enum devlink_sb_threshold_type threshold_type; 983 u16 pool_index; 984 u32 size; 985 int err; 986 987 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 988 &pool_index); 989 if (err) 990 return err; 991 992 err = devlink_sb_th_type_get_from_info(info, &threshold_type); 993 if (err) 994 return err; 995 996 if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]) 997 return -EINVAL; 998 999 size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]); 1000 return devlink_sb_pool_set(devlink, devlink_sb->index, 1001 pool_index, size, threshold_type); 1002} 1003 1004static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg, 1005 struct devlink *devlink, 1006 struct devlink_port *devlink_port, 1007 struct devlink_sb *devlink_sb, 1008 u16 pool_index, 1009 enum devlink_command cmd, 1010 u32 portid, u32 seq, int flags) 1011{ 1012 const struct devlink_ops *ops = devlink->ops; 1013 u32 threshold; 1014 void *hdr; 1015 int err; 1016 1017 err = ops->sb_port_pool_get(devlink_port, devlink_sb->index, 1018 pool_index, &threshold); 1019 if (err) 1020 return err; 1021 1022 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1023 if (!hdr) 1024 return -EMSGSIZE; 1025 1026 if (devlink_nl_put_handle(msg, devlink)) 1027 goto nla_put_failure; 1028 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 1029 goto nla_put_failure; 1030 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 1031 goto nla_put_failure; 1032 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 1033 goto nla_put_failure; 1034 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 1035 goto nla_put_failure; 1036 1037 if (ops->sb_occ_port_pool_get) { 1038 u32 cur; 1039 u32 max; 1040 1041 err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index, 1042 pool_index, &cur, &max); 1043 if (err && err != -EOPNOTSUPP) 1044 return err; 1045 if (!err) { 1046 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 1047 goto nla_put_failure; 1048 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 1049 goto nla_put_failure; 1050 } 1051 } 1052 1053 genlmsg_end(msg, hdr); 1054 return 0; 1055 1056nla_put_failure: 1057 genlmsg_cancel(msg, hdr); 1058 return -EMSGSIZE; 1059} 1060 1061static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb, 1062 struct genl_info *info) 1063{ 1064 struct devlink_port *devlink_port = info->user_ptr[0]; 1065 struct devlink *devlink = devlink_port->devlink; 1066 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1067 struct sk_buff *msg; 1068 u16 pool_index; 1069 int err; 1070 1071 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1072 &pool_index); 1073 if (err) 1074 return err; 1075 1076 if (!devlink->ops || !devlink->ops->sb_port_pool_get) 1077 return -EOPNOTSUPP; 1078 1079 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1080 if (!msg) 1081 return -ENOMEM; 1082 1083 err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port, 1084 devlink_sb, pool_index, 1085 DEVLINK_CMD_SB_PORT_POOL_NEW, 1086 info->snd_portid, info->snd_seq, 0); 1087 if (err) { 1088 nlmsg_free(msg); 1089 return err; 1090 } 1091 1092 return genlmsg_reply(msg, info); 1093} 1094 1095static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 1096 struct devlink *devlink, 1097 struct devlink_sb *devlink_sb, 1098 u32 portid, u32 seq) 1099{ 1100 struct devlink_port *devlink_port; 1101 u16 pool_count = devlink_sb_pool_count(devlink_sb); 1102 u16 pool_index; 1103 int err; 1104 1105 list_for_each_entry(devlink_port, &devlink->port_list, list) { 1106 for (pool_index = 0; pool_index < pool_count; pool_index++) { 1107 if (*p_idx < start) { 1108 (*p_idx)++; 1109 continue; 1110 } 1111 err = devlink_nl_sb_port_pool_fill(msg, devlink, 1112 devlink_port, 1113 devlink_sb, 1114 pool_index, 1115 DEVLINK_CMD_SB_PORT_POOL_NEW, 1116 portid, seq, 1117 NLM_F_MULTI); 1118 if (err) 1119 return err; 1120 (*p_idx)++; 1121 } 1122 } 1123 return 0; 1124} 1125 1126static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg, 1127 struct netlink_callback *cb) 1128{ 1129 struct devlink *devlink; 1130 struct devlink_sb *devlink_sb; 1131 int start = cb->args[0]; 1132 int idx = 0; 1133 int err; 1134 1135 mutex_lock(&devlink_mutex); 1136 list_for_each_entry(devlink, &devlink_list, list) { 1137 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 1138 !devlink->ops || !devlink->ops->sb_port_pool_get) 1139 continue; 1140 mutex_lock(&devlink->lock); 1141 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 1142 err = __sb_port_pool_get_dumpit(msg, start, &idx, 1143 devlink, devlink_sb, 1144 NETLINK_CB(cb->skb).portid, 1145 cb->nlh->nlmsg_seq); 1146 if (err && err != -EOPNOTSUPP) { 1147 mutex_unlock(&devlink->lock); 1148 goto out; 1149 } 1150 } 1151 mutex_unlock(&devlink->lock); 1152 } 1153out: 1154 mutex_unlock(&devlink_mutex); 1155 1156 cb->args[0] = idx; 1157 return msg->len; 1158} 1159 1160static int devlink_sb_port_pool_set(struct devlink_port *devlink_port, 1161 unsigned int sb_index, u16 pool_index, 1162 u32 threshold) 1163 1164{ 1165 const struct devlink_ops *ops = devlink_port->devlink->ops; 1166 1167 if (ops && ops->sb_port_pool_set) 1168 return ops->sb_port_pool_set(devlink_port, sb_index, 1169 pool_index, threshold); 1170 return -EOPNOTSUPP; 1171} 1172 1173static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb, 1174 struct genl_info *info) 1175{ 1176 struct devlink_port *devlink_port = info->user_ptr[0]; 1177 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1178 u16 pool_index; 1179 u32 threshold; 1180 int err; 1181 1182 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1183 &pool_index); 1184 if (err) 1185 return err; 1186 1187 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD]) 1188 return -EINVAL; 1189 1190 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 1191 return devlink_sb_port_pool_set(devlink_port, devlink_sb->index, 1192 pool_index, threshold); 1193} 1194 1195static int 1196devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink, 1197 struct devlink_port *devlink_port, 1198 struct devlink_sb *devlink_sb, u16 tc_index, 1199 enum devlink_sb_pool_type pool_type, 1200 enum devlink_command cmd, 1201 u32 portid, u32 seq, int flags) 1202{ 1203 const struct devlink_ops *ops = devlink->ops; 1204 u16 pool_index; 1205 u32 threshold; 1206 void *hdr; 1207 int err; 1208 1209 err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index, 1210 tc_index, pool_type, 1211 &pool_index, &threshold); 1212 if (err) 1213 return err; 1214 1215 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1216 if (!hdr) 1217 return -EMSGSIZE; 1218 1219 if (devlink_nl_put_handle(msg, devlink)) 1220 goto nla_put_failure; 1221 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 1222 goto nla_put_failure; 1223 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 1224 goto nla_put_failure; 1225 if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index)) 1226 goto nla_put_failure; 1227 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type)) 1228 goto nla_put_failure; 1229 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 1230 goto nla_put_failure; 1231 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 1232 goto nla_put_failure; 1233 1234 if (ops->sb_occ_tc_port_bind_get) { 1235 u32 cur; 1236 u32 max; 1237 1238 err = ops->sb_occ_tc_port_bind_get(devlink_port, 1239 devlink_sb->index, 1240 tc_index, pool_type, 1241 &cur, &max); 1242 if (err && err != -EOPNOTSUPP) 1243 return err; 1244 if (!err) { 1245 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 1246 goto nla_put_failure; 1247 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 1248 goto nla_put_failure; 1249 } 1250 } 1251 1252 genlmsg_end(msg, hdr); 1253 return 0; 1254 1255nla_put_failure: 1256 genlmsg_cancel(msg, hdr); 1257 return -EMSGSIZE; 1258} 1259 1260static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb, 1261 struct genl_info *info) 1262{ 1263 struct devlink_port *devlink_port = info->user_ptr[0]; 1264 struct devlink *devlink = devlink_port->devlink; 1265 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1266 struct sk_buff *msg; 1267 enum devlink_sb_pool_type pool_type; 1268 u16 tc_index; 1269 int err; 1270 1271 err = devlink_sb_pool_type_get_from_info(info, &pool_type); 1272 if (err) 1273 return err; 1274 1275 err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 1276 pool_type, &tc_index); 1277 if (err) 1278 return err; 1279 1280 if (!devlink->ops || !devlink->ops->sb_tc_pool_bind_get) 1281 return -EOPNOTSUPP; 1282 1283 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1284 if (!msg) 1285 return -ENOMEM; 1286 1287 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port, 1288 devlink_sb, tc_index, pool_type, 1289 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1290 info->snd_portid, 1291 info->snd_seq, 0); 1292 if (err) { 1293 nlmsg_free(msg); 1294 return err; 1295 } 1296 1297 return genlmsg_reply(msg, info); 1298} 1299 1300static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, 1301 int start, int *p_idx, 1302 struct devlink *devlink, 1303 struct devlink_sb *devlink_sb, 1304 u32 portid, u32 seq) 1305{ 1306 struct devlink_port *devlink_port; 1307 u16 tc_index; 1308 int err; 1309 1310 list_for_each_entry(devlink_port, &devlink->port_list, list) { 1311 for (tc_index = 0; 1312 tc_index < devlink_sb->ingress_tc_count; tc_index++) { 1313 if (*p_idx < start) { 1314 (*p_idx)++; 1315 continue; 1316 } 1317 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 1318 devlink_port, 1319 devlink_sb, 1320 tc_index, 1321 DEVLINK_SB_POOL_TYPE_INGRESS, 1322 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1323 portid, seq, 1324 NLM_F_MULTI); 1325 if (err) 1326 return err; 1327 (*p_idx)++; 1328 } 1329 for (tc_index = 0; 1330 tc_index < devlink_sb->egress_tc_count; tc_index++) { 1331 if (*p_idx < start) { 1332 (*p_idx)++; 1333 continue; 1334 } 1335 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 1336 devlink_port, 1337 devlink_sb, 1338 tc_index, 1339 DEVLINK_SB_POOL_TYPE_EGRESS, 1340 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1341 portid, seq, 1342 NLM_F_MULTI); 1343 if (err) 1344 return err; 1345 (*p_idx)++; 1346 } 1347 } 1348 return 0; 1349} 1350 1351static int 1352devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, 1353 struct netlink_callback *cb) 1354{ 1355 struct devlink *devlink; 1356 struct devlink_sb *devlink_sb; 1357 int start = cb->args[0]; 1358 int idx = 0; 1359 int err; 1360 1361 mutex_lock(&devlink_mutex); 1362 list_for_each_entry(devlink, &devlink_list, list) { 1363 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 1364 !devlink->ops || !devlink->ops->sb_tc_pool_bind_get) 1365 continue; 1366 1367 mutex_lock(&devlink->lock); 1368 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 1369 err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx, 1370 devlink, 1371 devlink_sb, 1372 NETLINK_CB(cb->skb).portid, 1373 cb->nlh->nlmsg_seq); 1374 if (err && err != -EOPNOTSUPP) { 1375 mutex_unlock(&devlink->lock); 1376 goto out; 1377 } 1378 } 1379 mutex_unlock(&devlink->lock); 1380 } 1381out: 1382 mutex_unlock(&devlink_mutex); 1383 1384 cb->args[0] = idx; 1385 return msg->len; 1386} 1387 1388static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port, 1389 unsigned int sb_index, u16 tc_index, 1390 enum devlink_sb_pool_type pool_type, 1391 u16 pool_index, u32 threshold) 1392 1393{ 1394 const struct devlink_ops *ops = devlink_port->devlink->ops; 1395 1396 if (ops && ops->sb_tc_pool_bind_set) 1397 return ops->sb_tc_pool_bind_set(devlink_port, sb_index, 1398 tc_index, pool_type, 1399 pool_index, threshold); 1400 return -EOPNOTSUPP; 1401} 1402 1403static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb, 1404 struct genl_info *info) 1405{ 1406 struct devlink_port *devlink_port = info->user_ptr[0]; 1407 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1408 enum devlink_sb_pool_type pool_type; 1409 u16 tc_index; 1410 u16 pool_index; 1411 u32 threshold; 1412 int err; 1413 1414 err = devlink_sb_pool_type_get_from_info(info, &pool_type); 1415 if (err) 1416 return err; 1417 1418 err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 1419 pool_type, &tc_index); 1420 if (err) 1421 return err; 1422 1423 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1424 &pool_index); 1425 if (err) 1426 return err; 1427 1428 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD]) 1429 return -EINVAL; 1430 1431 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 1432 return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index, 1433 tc_index, pool_type, 1434 pool_index, threshold); 1435} 1436 1437static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb, 1438 struct genl_info *info) 1439{ 1440 struct devlink *devlink = info->user_ptr[0]; 1441 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1442 const struct devlink_ops *ops = devlink->ops; 1443 1444 if (ops && ops->sb_occ_snapshot) 1445 return ops->sb_occ_snapshot(devlink, devlink_sb->index); 1446 return -EOPNOTSUPP; 1447} 1448 1449static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb, 1450 struct genl_info *info) 1451{ 1452 struct devlink *devlink = info->user_ptr[0]; 1453 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1454 const struct devlink_ops *ops = devlink->ops; 1455 1456 if (ops && ops->sb_occ_max_clear) 1457 return ops->sb_occ_max_clear(devlink, devlink_sb->index); 1458 return -EOPNOTSUPP; 1459} 1460 1461static int devlink_nl_eswitch_fill(struct sk_buff *msg, struct devlink *devlink, 1462 enum devlink_command cmd, u32 portid, 1463 u32 seq, int flags) 1464{ 1465 const struct devlink_ops *ops = devlink->ops; 1466 u8 inline_mode, encap_mode; 1467 void *hdr; 1468 int err = 0; 1469 u16 mode; 1470 1471 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1472 if (!hdr) 1473 return -EMSGSIZE; 1474 1475 err = devlink_nl_put_handle(msg, devlink); 1476 if (err) 1477 goto nla_put_failure; 1478 1479 if (ops->eswitch_mode_get) { 1480 err = ops->eswitch_mode_get(devlink, &mode); 1481 if (err) 1482 goto nla_put_failure; 1483 err = nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode); 1484 if (err) 1485 goto nla_put_failure; 1486 } 1487 1488 if (ops->eswitch_inline_mode_get) { 1489 err = ops->eswitch_inline_mode_get(devlink, &inline_mode); 1490 if (err) 1491 goto nla_put_failure; 1492 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE, 1493 inline_mode); 1494 if (err) 1495 goto nla_put_failure; 1496 } 1497 1498 if (ops->eswitch_encap_mode_get) { 1499 err = ops->eswitch_encap_mode_get(devlink, &encap_mode); 1500 if (err) 1501 goto nla_put_failure; 1502 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, encap_mode); 1503 if (err) 1504 goto nla_put_failure; 1505 } 1506 1507 genlmsg_end(msg, hdr); 1508 return 0; 1509 1510nla_put_failure: 1511 genlmsg_cancel(msg, hdr); 1512 return err; 1513} 1514 1515static int devlink_nl_cmd_eswitch_get_doit(struct sk_buff *skb, 1516 struct genl_info *info) 1517{ 1518 struct devlink *devlink = info->user_ptr[0]; 1519 const struct devlink_ops *ops = devlink->ops; 1520 struct sk_buff *msg; 1521 int err; 1522 1523 if (!ops) 1524 return -EOPNOTSUPP; 1525 1526 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1527 if (!msg) 1528 return -ENOMEM; 1529 1530 err = devlink_nl_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_GET, 1531 info->snd_portid, info->snd_seq, 0); 1532 1533 if (err) { 1534 nlmsg_free(msg); 1535 return err; 1536 } 1537 1538 return genlmsg_reply(msg, info); 1539} 1540 1541static int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb, 1542 struct genl_info *info) 1543{ 1544 struct devlink *devlink = info->user_ptr[0]; 1545 const struct devlink_ops *ops = devlink->ops; 1546 u8 inline_mode, encap_mode; 1547 int err = 0; 1548 u16 mode; 1549 1550 if (!ops) 1551 return -EOPNOTSUPP; 1552 1553 if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) { 1554 if (!ops->eswitch_mode_set) 1555 return -EOPNOTSUPP; 1556 mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]); 1557 err = ops->eswitch_mode_set(devlink, mode); 1558 if (err) 1559 return err; 1560 } 1561 1562 if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) { 1563 if (!ops->eswitch_inline_mode_set) 1564 return -EOPNOTSUPP; 1565 inline_mode = nla_get_u8( 1566 info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]); 1567 err = ops->eswitch_inline_mode_set(devlink, inline_mode); 1568 if (err) 1569 return err; 1570 } 1571 1572 if (info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]) { 1573 if (!ops->eswitch_encap_mode_set) 1574 return -EOPNOTSUPP; 1575 encap_mode = nla_get_u8(info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]); 1576 err = ops->eswitch_encap_mode_set(devlink, encap_mode); 1577 if (err) 1578 return err; 1579 } 1580 1581 return 0; 1582} 1583 1584int devlink_dpipe_match_put(struct sk_buff *skb, 1585 struct devlink_dpipe_match *match) 1586{ 1587 struct devlink_dpipe_header *header = match->header; 1588 struct devlink_dpipe_field *field = &header->fields[match->field_id]; 1589 struct nlattr *match_attr; 1590 1591 match_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_MATCH); 1592 if (!match_attr) 1593 return -EMSGSIZE; 1594 1595 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_MATCH_TYPE, match->type) || 1596 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, match->header_index) || 1597 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 1598 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 1599 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 1600 goto nla_put_failure; 1601 1602 nla_nest_end(skb, match_attr); 1603 return 0; 1604 1605nla_put_failure: 1606 nla_nest_cancel(skb, match_attr); 1607 return -EMSGSIZE; 1608} 1609EXPORT_SYMBOL_GPL(devlink_dpipe_match_put); 1610 1611static int devlink_dpipe_matches_put(struct devlink_dpipe_table *table, 1612 struct sk_buff *skb) 1613{ 1614 struct nlattr *matches_attr; 1615 1616 matches_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLE_MATCHES); 1617 if (!matches_attr) 1618 return -EMSGSIZE; 1619 1620 if (table->table_ops->matches_dump(table->priv, skb)) 1621 goto nla_put_failure; 1622 1623 nla_nest_end(skb, matches_attr); 1624 return 0; 1625 1626nla_put_failure: 1627 nla_nest_cancel(skb, matches_attr); 1628 return -EMSGSIZE; 1629} 1630 1631int devlink_dpipe_action_put(struct sk_buff *skb, 1632 struct devlink_dpipe_action *action) 1633{ 1634 struct devlink_dpipe_header *header = action->header; 1635 struct devlink_dpipe_field *field = &header->fields[action->field_id]; 1636 struct nlattr *action_attr; 1637 1638 action_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_ACTION); 1639 if (!action_attr) 1640 return -EMSGSIZE; 1641 1642 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_ACTION_TYPE, action->type) || 1643 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, action->header_index) || 1644 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 1645 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 1646 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 1647 goto nla_put_failure; 1648 1649 nla_nest_end(skb, action_attr); 1650 return 0; 1651 1652nla_put_failure: 1653 nla_nest_cancel(skb, action_attr); 1654 return -EMSGSIZE; 1655} 1656EXPORT_SYMBOL_GPL(devlink_dpipe_action_put); 1657 1658static int devlink_dpipe_actions_put(struct devlink_dpipe_table *table, 1659 struct sk_buff *skb) 1660{ 1661 struct nlattr *actions_attr; 1662 1663 actions_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLE_ACTIONS); 1664 if (!actions_attr) 1665 return -EMSGSIZE; 1666 1667 if (table->table_ops->actions_dump(table->priv, skb)) 1668 goto nla_put_failure; 1669 1670 nla_nest_end(skb, actions_attr); 1671 return 0; 1672 1673nla_put_failure: 1674 nla_nest_cancel(skb, actions_attr); 1675 return -EMSGSIZE; 1676} 1677 1678static int devlink_dpipe_table_put(struct sk_buff *skb, 1679 struct devlink_dpipe_table *table) 1680{ 1681 struct nlattr *table_attr; 1682 u64 table_size; 1683 1684 table_size = table->table_ops->size_get(table->priv); 1685 table_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLE); 1686 if (!table_attr) 1687 return -EMSGSIZE; 1688 1689 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) || 1690 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table_size, 1691 DEVLINK_ATTR_PAD)) 1692 goto nla_put_failure; 1693 if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED, 1694 table->counters_enabled)) 1695 goto nla_put_failure; 1696 1697 if (table->resource_valid) { 1698 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID, 1699 table->resource_id, DEVLINK_ATTR_PAD) || 1700 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS, 1701 table->resource_units, DEVLINK_ATTR_PAD)) 1702 goto nla_put_failure; 1703 } 1704 if (devlink_dpipe_matches_put(table, skb)) 1705 goto nla_put_failure; 1706 1707 if (devlink_dpipe_actions_put(table, skb)) 1708 goto nla_put_failure; 1709 1710 nla_nest_end(skb, table_attr); 1711 return 0; 1712 1713nla_put_failure: 1714 nla_nest_cancel(skb, table_attr); 1715 return -EMSGSIZE; 1716} 1717 1718static int devlink_dpipe_send_and_alloc_skb(struct sk_buff **pskb, 1719 struct genl_info *info) 1720{ 1721 int err; 1722 1723 if (*pskb) { 1724 err = genlmsg_reply(*pskb, info); 1725 if (err) 1726 return err; 1727 } 1728 *pskb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 1729 if (!*pskb) 1730 return -ENOMEM; 1731 return 0; 1732} 1733 1734static int devlink_dpipe_tables_fill(struct genl_info *info, 1735 enum devlink_command cmd, int flags, 1736 struct list_head *dpipe_tables, 1737 const char *table_name) 1738{ 1739 struct devlink *devlink = info->user_ptr[0]; 1740 struct devlink_dpipe_table *table; 1741 struct nlattr *tables_attr; 1742 struct sk_buff *skb = NULL; 1743 struct nlmsghdr *nlh; 1744 bool incomplete; 1745 void *hdr; 1746 int i; 1747 int err; 1748 1749 table = list_first_entry(dpipe_tables, 1750 struct devlink_dpipe_table, list); 1751start_again: 1752 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 1753 if (err) 1754 return err; 1755 1756 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 1757 &devlink_nl_family, NLM_F_MULTI, cmd); 1758 if (!hdr) { 1759 nlmsg_free(skb); 1760 return -EMSGSIZE; 1761 } 1762 1763 if (devlink_nl_put_handle(skb, devlink)) 1764 goto nla_put_failure; 1765 tables_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLES); 1766 if (!tables_attr) 1767 goto nla_put_failure; 1768 1769 i = 0; 1770 incomplete = false; 1771 list_for_each_entry_from(table, dpipe_tables, list) { 1772 if (!table_name) { 1773 err = devlink_dpipe_table_put(skb, table); 1774 if (err) { 1775 if (!i) 1776 goto err_table_put; 1777 incomplete = true; 1778 break; 1779 } 1780 } else { 1781 if (!strcmp(table->name, table_name)) { 1782 err = devlink_dpipe_table_put(skb, table); 1783 if (err) 1784 break; 1785 } 1786 } 1787 i++; 1788 } 1789 1790 nla_nest_end(skb, tables_attr); 1791 genlmsg_end(skb, hdr); 1792 if (incomplete) 1793 goto start_again; 1794 1795send_done: 1796 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 1797 NLMSG_DONE, 0, flags | NLM_F_MULTI); 1798 if (!nlh) { 1799 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 1800 if (err) 1801 return err; 1802 goto send_done; 1803 } 1804 1805 return genlmsg_reply(skb, info); 1806 1807nla_put_failure: 1808 err = -EMSGSIZE; 1809err_table_put: 1810 genlmsg_cancel(skb, hdr); 1811 nlmsg_free(skb); 1812 return err; 1813} 1814 1815static int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb, 1816 struct genl_info *info) 1817{ 1818 struct devlink *devlink = info->user_ptr[0]; 1819 const char *table_name = NULL; 1820 1821 if (info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]) 1822 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 1823 1824 return devlink_dpipe_tables_fill(info, DEVLINK_CMD_DPIPE_TABLE_GET, 0, 1825 &devlink->dpipe_table_list, 1826 table_name); 1827} 1828 1829static int devlink_dpipe_value_put(struct sk_buff *skb, 1830 struct devlink_dpipe_value *value) 1831{ 1832 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE, 1833 value->value_size, value->value)) 1834 return -EMSGSIZE; 1835 if (value->mask) 1836 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE_MASK, 1837 value->value_size, value->mask)) 1838 return -EMSGSIZE; 1839 if (value->mapping_valid) 1840 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_VALUE_MAPPING, 1841 value->mapping_value)) 1842 return -EMSGSIZE; 1843 return 0; 1844} 1845 1846static int devlink_dpipe_action_value_put(struct sk_buff *skb, 1847 struct devlink_dpipe_value *value) 1848{ 1849 if (!value->action) 1850 return -EINVAL; 1851 if (devlink_dpipe_action_put(skb, value->action)) 1852 return -EMSGSIZE; 1853 if (devlink_dpipe_value_put(skb, value)) 1854 return -EMSGSIZE; 1855 return 0; 1856} 1857 1858static int devlink_dpipe_action_values_put(struct sk_buff *skb, 1859 struct devlink_dpipe_value *values, 1860 unsigned int values_count) 1861{ 1862 struct nlattr *action_attr; 1863 int i; 1864 int err; 1865 1866 for (i = 0; i < values_count; i++) { 1867 action_attr = nla_nest_start(skb, 1868 DEVLINK_ATTR_DPIPE_ACTION_VALUE); 1869 if (!action_attr) 1870 return -EMSGSIZE; 1871 err = devlink_dpipe_action_value_put(skb, &values[i]); 1872 if (err) 1873 goto err_action_value_put; 1874 nla_nest_end(skb, action_attr); 1875 } 1876 return 0; 1877 1878err_action_value_put: 1879 nla_nest_cancel(skb, action_attr); 1880 return err; 1881} 1882 1883static int devlink_dpipe_match_value_put(struct sk_buff *skb, 1884 struct devlink_dpipe_value *value) 1885{ 1886 if (!value->match) 1887 return -EINVAL; 1888 if (devlink_dpipe_match_put(skb, value->match)) 1889 return -EMSGSIZE; 1890 if (devlink_dpipe_value_put(skb, value)) 1891 return -EMSGSIZE; 1892 return 0; 1893} 1894 1895static int devlink_dpipe_match_values_put(struct sk_buff *skb, 1896 struct devlink_dpipe_value *values, 1897 unsigned int values_count) 1898{ 1899 struct nlattr *match_attr; 1900 int i; 1901 int err; 1902 1903 for (i = 0; i < values_count; i++) { 1904 match_attr = nla_nest_start(skb, 1905 DEVLINK_ATTR_DPIPE_MATCH_VALUE); 1906 if (!match_attr) 1907 return -EMSGSIZE; 1908 err = devlink_dpipe_match_value_put(skb, &values[i]); 1909 if (err) 1910 goto err_match_value_put; 1911 nla_nest_end(skb, match_attr); 1912 } 1913 return 0; 1914 1915err_match_value_put: 1916 nla_nest_cancel(skb, match_attr); 1917 return err; 1918} 1919 1920static int devlink_dpipe_entry_put(struct sk_buff *skb, 1921 struct devlink_dpipe_entry *entry) 1922{ 1923 struct nlattr *entry_attr, *matches_attr, *actions_attr; 1924 int err; 1925 1926 entry_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_ENTRY); 1927 if (!entry_attr) 1928 return -EMSGSIZE; 1929 1930 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_INDEX, entry->index, 1931 DEVLINK_ATTR_PAD)) 1932 goto nla_put_failure; 1933 if (entry->counter_valid) 1934 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_COUNTER, 1935 entry->counter, DEVLINK_ATTR_PAD)) 1936 goto nla_put_failure; 1937 1938 matches_attr = nla_nest_start(skb, 1939 DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES); 1940 if (!matches_attr) 1941 goto nla_put_failure; 1942 1943 err = devlink_dpipe_match_values_put(skb, entry->match_values, 1944 entry->match_values_count); 1945 if (err) { 1946 nla_nest_cancel(skb, matches_attr); 1947 goto err_match_values_put; 1948 } 1949 nla_nest_end(skb, matches_attr); 1950 1951 actions_attr = nla_nest_start(skb, 1952 DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES); 1953 if (!actions_attr) 1954 goto nla_put_failure; 1955 1956 err = devlink_dpipe_action_values_put(skb, entry->action_values, 1957 entry->action_values_count); 1958 if (err) { 1959 nla_nest_cancel(skb, actions_attr); 1960 goto err_action_values_put; 1961 } 1962 nla_nest_end(skb, actions_attr); 1963 1964 nla_nest_end(skb, entry_attr); 1965 return 0; 1966 1967nla_put_failure: 1968 err = -EMSGSIZE; 1969err_match_values_put: 1970err_action_values_put: 1971 nla_nest_cancel(skb, entry_attr); 1972 return err; 1973} 1974 1975static struct devlink_dpipe_table * 1976devlink_dpipe_table_find(struct list_head *dpipe_tables, 1977 const char *table_name) 1978{ 1979 struct devlink_dpipe_table *table; 1980 1981 list_for_each_entry_rcu(table, dpipe_tables, list) { 1982 if (!strcmp(table->name, table_name)) 1983 return table; 1984 } 1985 return NULL; 1986} 1987 1988int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx) 1989{ 1990 struct devlink *devlink; 1991 int err; 1992 1993 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx->skb, 1994 dump_ctx->info); 1995 if (err) 1996 return err; 1997 1998 dump_ctx->hdr = genlmsg_put(dump_ctx->skb, 1999 dump_ctx->info->snd_portid, 2000 dump_ctx->info->snd_seq, 2001 &devlink_nl_family, NLM_F_MULTI, 2002 dump_ctx->cmd); 2003 if (!dump_ctx->hdr) 2004 goto nla_put_failure; 2005 2006 devlink = dump_ctx->info->user_ptr[0]; 2007 if (devlink_nl_put_handle(dump_ctx->skb, devlink)) 2008 goto nla_put_failure; 2009 dump_ctx->nest = nla_nest_start(dump_ctx->skb, 2010 DEVLINK_ATTR_DPIPE_ENTRIES); 2011 if (!dump_ctx->nest) 2012 goto nla_put_failure; 2013 return 0; 2014 2015nla_put_failure: 2016 genlmsg_cancel(dump_ctx->skb, dump_ctx->hdr); 2017 nlmsg_free(dump_ctx->skb); 2018 return -EMSGSIZE; 2019} 2020EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_prepare); 2021 2022int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx, 2023 struct devlink_dpipe_entry *entry) 2024{ 2025 return devlink_dpipe_entry_put(dump_ctx->skb, entry); 2026} 2027EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_append); 2028 2029int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx) 2030{ 2031 nla_nest_end(dump_ctx->skb, dump_ctx->nest); 2032 genlmsg_end(dump_ctx->skb, dump_ctx->hdr); 2033 return 0; 2034} 2035EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close); 2036 2037void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry) 2038 2039{ 2040 unsigned int value_count, value_index; 2041 struct devlink_dpipe_value *value; 2042 2043 value = entry->action_values; 2044 value_count = entry->action_values_count; 2045 for (value_index = 0; value_index < value_count; value_index++) { 2046 kfree(value[value_index].value); 2047 kfree(value[value_index].mask); 2048 } 2049 2050 value = entry->match_values; 2051 value_count = entry->match_values_count; 2052 for (value_index = 0; value_index < value_count; value_index++) { 2053 kfree(value[value_index].value); 2054 kfree(value[value_index].mask); 2055 } 2056} 2057EXPORT_SYMBOL(devlink_dpipe_entry_clear); 2058 2059static int devlink_dpipe_entries_fill(struct genl_info *info, 2060 enum devlink_command cmd, int flags, 2061 struct devlink_dpipe_table *table) 2062{ 2063 struct devlink_dpipe_dump_ctx dump_ctx; 2064 struct nlmsghdr *nlh; 2065 int err; 2066 2067 dump_ctx.skb = NULL; 2068 dump_ctx.cmd = cmd; 2069 dump_ctx.info = info; 2070 2071 err = table->table_ops->entries_dump(table->priv, 2072 table->counters_enabled, 2073 &dump_ctx); 2074 if (err) 2075 return err; 2076 2077send_done: 2078 nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq, 2079 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2080 if (!nlh) { 2081 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info); 2082 if (err) 2083 return err; 2084 goto send_done; 2085 } 2086 return genlmsg_reply(dump_ctx.skb, info); 2087} 2088 2089static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb, 2090 struct genl_info *info) 2091{ 2092 struct devlink *devlink = info->user_ptr[0]; 2093 struct devlink_dpipe_table *table; 2094 const char *table_name; 2095 2096 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]) 2097 return -EINVAL; 2098 2099 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 2100 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 2101 table_name); 2102 if (!table) 2103 return -EINVAL; 2104 2105 if (!table->table_ops->entries_dump) 2106 return -EINVAL; 2107 2108 return devlink_dpipe_entries_fill(info, DEVLINK_CMD_DPIPE_ENTRIES_GET, 2109 0, table); 2110} 2111 2112static int devlink_dpipe_fields_put(struct sk_buff *skb, 2113 const struct devlink_dpipe_header *header) 2114{ 2115 struct devlink_dpipe_field *field; 2116 struct nlattr *field_attr; 2117 int i; 2118 2119 for (i = 0; i < header->fields_count; i++) { 2120 field = &header->fields[i]; 2121 field_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_FIELD); 2122 if (!field_attr) 2123 return -EMSGSIZE; 2124 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_FIELD_NAME, field->name) || 2125 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 2126 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, field->bitwidth) || 2127 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, field->mapping_type)) 2128 goto nla_put_failure; 2129 nla_nest_end(skb, field_attr); 2130 } 2131 return 0; 2132 2133nla_put_failure: 2134 nla_nest_cancel(skb, field_attr); 2135 return -EMSGSIZE; 2136} 2137 2138static int devlink_dpipe_header_put(struct sk_buff *skb, 2139 struct devlink_dpipe_header *header) 2140{ 2141 struct nlattr *fields_attr, *header_attr; 2142 int err; 2143 2144 header_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADER); 2145 if (!header_attr) 2146 return -EMSGSIZE; 2147 2148 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_HEADER_NAME, header->name) || 2149 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 2150 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 2151 goto nla_put_failure; 2152 2153 fields_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADER_FIELDS); 2154 if (!fields_attr) 2155 goto nla_put_failure; 2156 2157 err = devlink_dpipe_fields_put(skb, header); 2158 if (err) { 2159 nla_nest_cancel(skb, fields_attr); 2160 goto nla_put_failure; 2161 } 2162 nla_nest_end(skb, fields_attr); 2163 nla_nest_end(skb, header_attr); 2164 return 0; 2165 2166nla_put_failure: 2167 err = -EMSGSIZE; 2168 nla_nest_cancel(skb, header_attr); 2169 return err; 2170} 2171 2172static int devlink_dpipe_headers_fill(struct genl_info *info, 2173 enum devlink_command cmd, int flags, 2174 struct devlink_dpipe_headers * 2175 dpipe_headers) 2176{ 2177 struct devlink *devlink = info->user_ptr[0]; 2178 struct nlattr *headers_attr; 2179 struct sk_buff *skb = NULL; 2180 struct nlmsghdr *nlh; 2181 void *hdr; 2182 int i, j; 2183 int err; 2184 2185 i = 0; 2186start_again: 2187 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2188 if (err) 2189 return err; 2190 2191 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 2192 &devlink_nl_family, NLM_F_MULTI, cmd); 2193 if (!hdr) { 2194 nlmsg_free(skb); 2195 return -EMSGSIZE; 2196 } 2197 2198 if (devlink_nl_put_handle(skb, devlink)) 2199 goto nla_put_failure; 2200 headers_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADERS); 2201 if (!headers_attr) 2202 goto nla_put_failure; 2203 2204 j = 0; 2205 for (; i < dpipe_headers->headers_count; i++) { 2206 err = devlink_dpipe_header_put(skb, dpipe_headers->headers[i]); 2207 if (err) { 2208 if (!j) 2209 goto err_table_put; 2210 break; 2211 } 2212 j++; 2213 } 2214 nla_nest_end(skb, headers_attr); 2215 genlmsg_end(skb, hdr); 2216 if (i != dpipe_headers->headers_count) 2217 goto start_again; 2218 2219send_done: 2220 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 2221 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2222 if (!nlh) { 2223 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2224 if (err) 2225 return err; 2226 goto send_done; 2227 } 2228 return genlmsg_reply(skb, info); 2229 2230nla_put_failure: 2231 err = -EMSGSIZE; 2232err_table_put: 2233 genlmsg_cancel(skb, hdr); 2234 nlmsg_free(skb); 2235 return err; 2236} 2237 2238static int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb, 2239 struct genl_info *info) 2240{ 2241 struct devlink *devlink = info->user_ptr[0]; 2242 2243 if (!devlink->dpipe_headers) 2244 return -EOPNOTSUPP; 2245 return devlink_dpipe_headers_fill(info, DEVLINK_CMD_DPIPE_HEADERS_GET, 2246 0, devlink->dpipe_headers); 2247} 2248 2249static int devlink_dpipe_table_counters_set(struct devlink *devlink, 2250 const char *table_name, 2251 bool enable) 2252{ 2253 struct devlink_dpipe_table *table; 2254 2255 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 2256 table_name); 2257 if (!table) 2258 return -EINVAL; 2259 2260 if (table->counter_control_extern) 2261 return -EOPNOTSUPP; 2262 2263 if (!(table->counters_enabled ^ enable)) 2264 return 0; 2265 2266 table->counters_enabled = enable; 2267 if (table->table_ops->counters_set_update) 2268 table->table_ops->counters_set_update(table->priv, enable); 2269 return 0; 2270} 2271 2272static int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb, 2273 struct genl_info *info) 2274{ 2275 struct devlink *devlink = info->user_ptr[0]; 2276 const char *table_name; 2277 bool counters_enable; 2278 2279 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME] || 2280 !info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]) 2281 return -EINVAL; 2282 2283 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 2284 counters_enable = !!nla_get_u8(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]); 2285 2286 return devlink_dpipe_table_counters_set(devlink, table_name, 2287 counters_enable); 2288} 2289 2290static struct devlink_resource * 2291devlink_resource_find(struct devlink *devlink, 2292 struct devlink_resource *resource, u64 resource_id) 2293{ 2294 struct list_head *resource_list; 2295 2296 if (resource) 2297 resource_list = &resource->resource_list; 2298 else 2299 resource_list = &devlink->resource_list; 2300 2301 list_for_each_entry(resource, resource_list, list) { 2302 struct devlink_resource *child_resource; 2303 2304 if (resource->id == resource_id) 2305 return resource; 2306 2307 child_resource = devlink_resource_find(devlink, resource, 2308 resource_id); 2309 if (child_resource) 2310 return child_resource; 2311 } 2312 return NULL; 2313} 2314 2315static void 2316devlink_resource_validate_children(struct devlink_resource *resource) 2317{ 2318 struct devlink_resource *child_resource; 2319 bool size_valid = true; 2320 u64 parts_size = 0; 2321 2322 if (list_empty(&resource->resource_list)) 2323 goto out; 2324 2325 list_for_each_entry(child_resource, &resource->resource_list, list) 2326 parts_size += child_resource->size_new; 2327 2328 if (parts_size > resource->size_new) 2329 size_valid = false; 2330out: 2331 resource->size_valid = size_valid; 2332} 2333 2334static int devlink_nl_cmd_resource_set(struct sk_buff *skb, 2335 struct genl_info *info) 2336{ 2337 struct devlink *devlink = info->user_ptr[0]; 2338 struct devlink_resource *resource; 2339 u64 resource_id; 2340 u64 size; 2341 int err; 2342 2343 if (!info->attrs[DEVLINK_ATTR_RESOURCE_ID] || 2344 !info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]) 2345 return -EINVAL; 2346 resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]); 2347 2348 resource = devlink_resource_find(devlink, NULL, resource_id); 2349 if (!resource) 2350 return -EINVAL; 2351 2352 if (!resource->resource_ops->size_validate) 2353 return -EINVAL; 2354 2355 size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]); 2356 err = resource->resource_ops->size_validate(devlink, size, 2357 info->extack); 2358 if (err) 2359 return err; 2360 2361 resource->size_new = size; 2362 devlink_resource_validate_children(resource); 2363 if (resource->parent) 2364 devlink_resource_validate_children(resource->parent); 2365 return 0; 2366} 2367 2368static int 2369devlink_resource_size_params_put(struct devlink_resource *resource, 2370 struct sk_buff *skb) 2371{ 2372 struct devlink_resource_size_params *size_params; 2373 2374 size_params = &resource->size_params; 2375 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN, 2376 size_params->size_granularity, DEVLINK_ATTR_PAD) || 2377 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX, 2378 size_params->size_max, DEVLINK_ATTR_PAD) || 2379 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN, 2380 size_params->size_min, DEVLINK_ATTR_PAD) || 2381 nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit)) 2382 return -EMSGSIZE; 2383 return 0; 2384} 2385 2386static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb, 2387 struct devlink_resource *resource) 2388{ 2389 struct devlink_resource *child_resource; 2390 struct nlattr *child_resource_attr; 2391 struct nlattr *resource_attr; 2392 2393 resource_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE); 2394 if (!resource_attr) 2395 return -EMSGSIZE; 2396 2397 if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) || 2398 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size, 2399 DEVLINK_ATTR_PAD) || 2400 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id, 2401 DEVLINK_ATTR_PAD)) 2402 goto nla_put_failure; 2403 if (resource->size != resource->size_new) 2404 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW, 2405 resource->size_new, DEVLINK_ATTR_PAD); 2406 if (resource->resource_ops && resource->resource_ops->occ_get) 2407 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC, 2408 resource->resource_ops->occ_get(devlink), 2409 DEVLINK_ATTR_PAD)) 2410 goto nla_put_failure; 2411 if (devlink_resource_size_params_put(resource, skb)) 2412 goto nla_put_failure; 2413 if (list_empty(&resource->resource_list)) 2414 goto out; 2415 2416 if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID, 2417 resource->size_valid)) 2418 goto nla_put_failure; 2419 2420 child_resource_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE_LIST); 2421 if (!child_resource_attr) 2422 goto nla_put_failure; 2423 2424 list_for_each_entry(child_resource, &resource->resource_list, list) { 2425 if (devlink_resource_put(devlink, skb, child_resource)) 2426 goto resource_put_failure; 2427 } 2428 2429 nla_nest_end(skb, child_resource_attr); 2430out: 2431 nla_nest_end(skb, resource_attr); 2432 return 0; 2433 2434resource_put_failure: 2435 nla_nest_cancel(skb, child_resource_attr); 2436nla_put_failure: 2437 nla_nest_cancel(skb, resource_attr); 2438 return -EMSGSIZE; 2439} 2440 2441static int devlink_resource_fill(struct genl_info *info, 2442 enum devlink_command cmd, int flags) 2443{ 2444 struct devlink *devlink = info->user_ptr[0]; 2445 struct devlink_resource *resource; 2446 struct nlattr *resources_attr; 2447 struct sk_buff *skb = NULL; 2448 struct nlmsghdr *nlh; 2449 bool incomplete; 2450 void *hdr; 2451 int i; 2452 int err; 2453 2454 resource = list_first_entry(&devlink->resource_list, 2455 struct devlink_resource, list); 2456start_again: 2457 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2458 if (err) 2459 return err; 2460 2461 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 2462 &devlink_nl_family, NLM_F_MULTI, cmd); 2463 if (!hdr) { 2464 nlmsg_free(skb); 2465 return -EMSGSIZE; 2466 } 2467 2468 if (devlink_nl_put_handle(skb, devlink)) 2469 goto nla_put_failure; 2470 2471 resources_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE_LIST); 2472 if (!resources_attr) 2473 goto nla_put_failure; 2474 2475 incomplete = false; 2476 i = 0; 2477 list_for_each_entry_from(resource, &devlink->resource_list, list) { 2478 err = devlink_resource_put(devlink, skb, resource); 2479 if (err) { 2480 if (!i) 2481 goto err_resource_put; 2482 incomplete = true; 2483 break; 2484 } 2485 i++; 2486 } 2487 nla_nest_end(skb, resources_attr); 2488 genlmsg_end(skb, hdr); 2489 if (incomplete) 2490 goto start_again; 2491send_done: 2492 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 2493 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2494 if (!nlh) { 2495 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2496 if (err) 2497 goto err_skb_send_alloc; 2498 goto send_done; 2499 } 2500 return genlmsg_reply(skb, info); 2501 2502nla_put_failure: 2503 err = -EMSGSIZE; 2504err_resource_put: 2505err_skb_send_alloc: 2506 genlmsg_cancel(skb, hdr); 2507 nlmsg_free(skb); 2508 return err; 2509} 2510 2511static int devlink_nl_cmd_resource_dump(struct sk_buff *skb, 2512 struct genl_info *info) 2513{ 2514 struct devlink *devlink = info->user_ptr[0]; 2515 2516 if (list_empty(&devlink->resource_list)) 2517 return -EOPNOTSUPP; 2518 2519 return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0); 2520} 2521 2522static int 2523devlink_resources_validate(struct devlink *devlink, 2524 struct devlink_resource *resource, 2525 struct genl_info *info) 2526{ 2527 struct list_head *resource_list; 2528 int err = 0; 2529 2530 if (resource) 2531 resource_list = &resource->resource_list; 2532 else 2533 resource_list = &devlink->resource_list; 2534 2535 list_for_each_entry(resource, resource_list, list) { 2536 if (!resource->size_valid) 2537 return -EINVAL; 2538 err = devlink_resources_validate(devlink, resource, info); 2539 if (err) 2540 return err; 2541 } 2542 return err; 2543} 2544 2545static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info) 2546{ 2547 struct devlink *devlink = info->user_ptr[0]; 2548 int err; 2549 2550 if (!devlink->ops->reload) 2551 return -EOPNOTSUPP; 2552 2553 err = devlink_resources_validate(devlink, NULL, info); 2554 if (err) { 2555 NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed"); 2556 return err; 2557 } 2558 return devlink->ops->reload(devlink); 2559} 2560 2561static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { 2562 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING }, 2563 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING }, 2564 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 }, 2565 [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 }, 2566 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 }, 2567 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 }, 2568 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 }, 2569 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 }, 2570 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 }, 2571 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 }, 2572 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 }, 2573 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 }, 2574 [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 }, 2575 [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 }, 2576 [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 }, 2577 [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING }, 2578 [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 }, 2579 [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64}, 2580 [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64}, 2581}; 2582 2583static const struct genl_ops devlink_nl_ops[] = { 2584 { 2585 .cmd = DEVLINK_CMD_GET, 2586 .doit = devlink_nl_cmd_get_doit, 2587 .dumpit = devlink_nl_cmd_get_dumpit, 2588 .policy = devlink_nl_policy, 2589 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2590 /* can be retrieved by unprivileged users */ 2591 }, 2592 { 2593 .cmd = DEVLINK_CMD_PORT_GET, 2594 .doit = devlink_nl_cmd_port_get_doit, 2595 .dumpit = devlink_nl_cmd_port_get_dumpit, 2596 .policy = devlink_nl_policy, 2597 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 2598 /* can be retrieved by unprivileged users */ 2599 }, 2600 { 2601 .cmd = DEVLINK_CMD_PORT_SET, 2602 .doit = devlink_nl_cmd_port_set_doit, 2603 .policy = devlink_nl_policy, 2604 .flags = GENL_ADMIN_PERM, 2605 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 2606 }, 2607 { 2608 .cmd = DEVLINK_CMD_PORT_SPLIT, 2609 .doit = devlink_nl_cmd_port_split_doit, 2610 .policy = devlink_nl_policy, 2611 .flags = GENL_ADMIN_PERM, 2612 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2613 DEVLINK_NL_FLAG_NO_LOCK, 2614 }, 2615 { 2616 .cmd = DEVLINK_CMD_PORT_UNSPLIT, 2617 .doit = devlink_nl_cmd_port_unsplit_doit, 2618 .policy = devlink_nl_policy, 2619 .flags = GENL_ADMIN_PERM, 2620 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2621 DEVLINK_NL_FLAG_NO_LOCK, 2622 }, 2623 { 2624 .cmd = DEVLINK_CMD_SB_GET, 2625 .doit = devlink_nl_cmd_sb_get_doit, 2626 .dumpit = devlink_nl_cmd_sb_get_dumpit, 2627 .policy = devlink_nl_policy, 2628 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2629 DEVLINK_NL_FLAG_NEED_SB, 2630 /* can be retrieved by unprivileged users */ 2631 }, 2632 { 2633 .cmd = DEVLINK_CMD_SB_POOL_GET, 2634 .doit = devlink_nl_cmd_sb_pool_get_doit, 2635 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit, 2636 .policy = devlink_nl_policy, 2637 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2638 DEVLINK_NL_FLAG_NEED_SB, 2639 /* can be retrieved by unprivileged users */ 2640 }, 2641 { 2642 .cmd = DEVLINK_CMD_SB_POOL_SET, 2643 .doit = devlink_nl_cmd_sb_pool_set_doit, 2644 .policy = devlink_nl_policy, 2645 .flags = GENL_ADMIN_PERM, 2646 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2647 DEVLINK_NL_FLAG_NEED_SB, 2648 }, 2649 { 2650 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET, 2651 .doit = devlink_nl_cmd_sb_port_pool_get_doit, 2652 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit, 2653 .policy = devlink_nl_policy, 2654 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 2655 DEVLINK_NL_FLAG_NEED_SB, 2656 /* can be retrieved by unprivileged users */ 2657 }, 2658 { 2659 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET, 2660 .doit = devlink_nl_cmd_sb_port_pool_set_doit, 2661 .policy = devlink_nl_policy, 2662 .flags = GENL_ADMIN_PERM, 2663 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 2664 DEVLINK_NL_FLAG_NEED_SB, 2665 }, 2666 { 2667 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET, 2668 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit, 2669 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit, 2670 .policy = devlink_nl_policy, 2671 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 2672 DEVLINK_NL_FLAG_NEED_SB, 2673 /* can be retrieved by unprivileged users */ 2674 }, 2675 { 2676 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET, 2677 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit, 2678 .policy = devlink_nl_policy, 2679 .flags = GENL_ADMIN_PERM, 2680 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 2681 DEVLINK_NL_FLAG_NEED_SB, 2682 }, 2683 { 2684 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT, 2685 .doit = devlink_nl_cmd_sb_occ_snapshot_doit, 2686 .policy = devlink_nl_policy, 2687 .flags = GENL_ADMIN_PERM, 2688 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2689 DEVLINK_NL_FLAG_NEED_SB, 2690 }, 2691 { 2692 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR, 2693 .doit = devlink_nl_cmd_sb_occ_max_clear_doit, 2694 .policy = devlink_nl_policy, 2695 .flags = GENL_ADMIN_PERM, 2696 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2697 DEVLINK_NL_FLAG_NEED_SB, 2698 }, 2699 { 2700 .cmd = DEVLINK_CMD_ESWITCH_GET, 2701 .doit = devlink_nl_cmd_eswitch_get_doit, 2702 .policy = devlink_nl_policy, 2703 .flags = GENL_ADMIN_PERM, 2704 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2705 }, 2706 { 2707 .cmd = DEVLINK_CMD_ESWITCH_SET, 2708 .doit = devlink_nl_cmd_eswitch_set_doit, 2709 .policy = devlink_nl_policy, 2710 .flags = GENL_ADMIN_PERM, 2711 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2712 }, 2713 { 2714 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET, 2715 .doit = devlink_nl_cmd_dpipe_table_get, 2716 .policy = devlink_nl_policy, 2717 .flags = GENL_ADMIN_PERM, 2718 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2719 }, 2720 { 2721 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET, 2722 .doit = devlink_nl_cmd_dpipe_entries_get, 2723 .policy = devlink_nl_policy, 2724 .flags = GENL_ADMIN_PERM, 2725 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2726 }, 2727 { 2728 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET, 2729 .doit = devlink_nl_cmd_dpipe_headers_get, 2730 .policy = devlink_nl_policy, 2731 .flags = GENL_ADMIN_PERM, 2732 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2733 }, 2734 { 2735 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET, 2736 .doit = devlink_nl_cmd_dpipe_table_counters_set, 2737 .policy = devlink_nl_policy, 2738 .flags = GENL_ADMIN_PERM, 2739 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2740 }, 2741 { 2742 .cmd = DEVLINK_CMD_RESOURCE_SET, 2743 .doit = devlink_nl_cmd_resource_set, 2744 .policy = devlink_nl_policy, 2745 .flags = GENL_ADMIN_PERM, 2746 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2747 }, 2748 { 2749 .cmd = DEVLINK_CMD_RESOURCE_DUMP, 2750 .doit = devlink_nl_cmd_resource_dump, 2751 .policy = devlink_nl_policy, 2752 .flags = GENL_ADMIN_PERM, 2753 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 2754 }, 2755 { 2756 .cmd = DEVLINK_CMD_RELOAD, 2757 .doit = devlink_nl_cmd_reload, 2758 .policy = devlink_nl_policy, 2759 .flags = GENL_ADMIN_PERM, 2760 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 2761 DEVLINK_NL_FLAG_NO_LOCK, 2762 }, 2763}; 2764 2765static struct genl_family devlink_nl_family __ro_after_init = { 2766 .name = DEVLINK_GENL_NAME, 2767 .version = DEVLINK_GENL_VERSION, 2768 .maxattr = DEVLINK_ATTR_MAX, 2769 .netnsok = true, 2770 .pre_doit = devlink_nl_pre_doit, 2771 .post_doit = devlink_nl_post_doit, 2772 .module = THIS_MODULE, 2773 .ops = devlink_nl_ops, 2774 .n_ops = ARRAY_SIZE(devlink_nl_ops), 2775 .mcgrps = devlink_nl_mcgrps, 2776 .n_mcgrps = ARRAY_SIZE(devlink_nl_mcgrps), 2777}; 2778 2779/** 2780 * devlink_alloc - Allocate new devlink instance resources 2781 * 2782 * @ops: ops 2783 * @priv_size: size of user private data 2784 * 2785 * Allocate new devlink instance resources, including devlink index 2786 * and name. 2787 */ 2788struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size) 2789{ 2790 struct devlink *devlink; 2791 2792 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL); 2793 if (!devlink) 2794 return NULL; 2795 devlink->ops = ops; 2796 devlink_net_set(devlink, &init_net); 2797 INIT_LIST_HEAD(&devlink->port_list); 2798 INIT_LIST_HEAD(&devlink->sb_list); 2799 INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list); 2800 INIT_LIST_HEAD(&devlink->resource_list); 2801 mutex_init(&devlink->lock); 2802 return devlink; 2803} 2804EXPORT_SYMBOL_GPL(devlink_alloc); 2805 2806/** 2807 * devlink_register - Register devlink instance 2808 * 2809 * @devlink: devlink 2810 */ 2811int devlink_register(struct devlink *devlink, struct device *dev) 2812{ 2813 mutex_lock(&devlink_mutex); 2814 devlink->dev = dev; 2815 list_add_tail(&devlink->list, &devlink_list); 2816 devlink_notify(devlink, DEVLINK_CMD_NEW); 2817 mutex_unlock(&devlink_mutex); 2818 return 0; 2819} 2820EXPORT_SYMBOL_GPL(devlink_register); 2821 2822/** 2823 * devlink_unregister - Unregister devlink instance 2824 * 2825 * @devlink: devlink 2826 */ 2827void devlink_unregister(struct devlink *devlink) 2828{ 2829 mutex_lock(&devlink_mutex); 2830 devlink_notify(devlink, DEVLINK_CMD_DEL); 2831 list_del(&devlink->list); 2832 mutex_unlock(&devlink_mutex); 2833} 2834EXPORT_SYMBOL_GPL(devlink_unregister); 2835 2836/** 2837 * devlink_free - Free devlink instance resources 2838 * 2839 * @devlink: devlink 2840 */ 2841void devlink_free(struct devlink *devlink) 2842{ 2843 kfree(devlink); 2844} 2845EXPORT_SYMBOL_GPL(devlink_free); 2846 2847/** 2848 * devlink_port_register - Register devlink port 2849 * 2850 * @devlink: devlink 2851 * @devlink_port: devlink port 2852 * @port_index 2853 * 2854 * Register devlink port with provided port index. User can use 2855 * any indexing, even hw-related one. devlink_port structure 2856 * is convenient to be embedded inside user driver private structure. 2857 * Note that the caller should take care of zeroing the devlink_port 2858 * structure. 2859 */ 2860int devlink_port_register(struct devlink *devlink, 2861 struct devlink_port *devlink_port, 2862 unsigned int port_index) 2863{ 2864 mutex_lock(&devlink->lock); 2865 if (devlink_port_index_exists(devlink, port_index)) { 2866 mutex_unlock(&devlink->lock); 2867 return -EEXIST; 2868 } 2869 devlink_port->devlink = devlink; 2870 devlink_port->index = port_index; 2871 devlink_port->registered = true; 2872 list_add_tail(&devlink_port->list, &devlink->port_list); 2873 mutex_unlock(&devlink->lock); 2874 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 2875 return 0; 2876} 2877EXPORT_SYMBOL_GPL(devlink_port_register); 2878 2879/** 2880 * devlink_port_unregister - Unregister devlink port 2881 * 2882 * @devlink_port: devlink port 2883 */ 2884void devlink_port_unregister(struct devlink_port *devlink_port) 2885{ 2886 struct devlink *devlink = devlink_port->devlink; 2887 2888 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL); 2889 mutex_lock(&devlink->lock); 2890 list_del(&devlink_port->list); 2891 mutex_unlock(&devlink->lock); 2892} 2893EXPORT_SYMBOL_GPL(devlink_port_unregister); 2894 2895static void __devlink_port_type_set(struct devlink_port *devlink_port, 2896 enum devlink_port_type type, 2897 void *type_dev) 2898{ 2899 devlink_port->type = type; 2900 devlink_port->type_dev = type_dev; 2901 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 2902} 2903 2904/** 2905 * devlink_port_type_eth_set - Set port type to Ethernet 2906 * 2907 * @devlink_port: devlink port 2908 * @netdev: related netdevice 2909 */ 2910void devlink_port_type_eth_set(struct devlink_port *devlink_port, 2911 struct net_device *netdev) 2912{ 2913 return __devlink_port_type_set(devlink_port, 2914 DEVLINK_PORT_TYPE_ETH, netdev); 2915} 2916EXPORT_SYMBOL_GPL(devlink_port_type_eth_set); 2917 2918/** 2919 * devlink_port_type_ib_set - Set port type to InfiniBand 2920 * 2921 * @devlink_port: devlink port 2922 * @ibdev: related IB device 2923 */ 2924void devlink_port_type_ib_set(struct devlink_port *devlink_port, 2925 struct ib_device *ibdev) 2926{ 2927 return __devlink_port_type_set(devlink_port, 2928 DEVLINK_PORT_TYPE_IB, ibdev); 2929} 2930EXPORT_SYMBOL_GPL(devlink_port_type_ib_set); 2931 2932/** 2933 * devlink_port_type_clear - Clear port type 2934 * 2935 * @devlink_port: devlink port 2936 */ 2937void devlink_port_type_clear(struct devlink_port *devlink_port) 2938{ 2939 return __devlink_port_type_set(devlink_port, 2940 DEVLINK_PORT_TYPE_NOTSET, NULL); 2941} 2942EXPORT_SYMBOL_GPL(devlink_port_type_clear); 2943 2944/** 2945 * devlink_port_split_set - Set port is split 2946 * 2947 * @devlink_port: devlink port 2948 * @split_group: split group - identifies group split port is part of 2949 */ 2950void devlink_port_split_set(struct devlink_port *devlink_port, 2951 u32 split_group) 2952{ 2953 devlink_port->split = true; 2954 devlink_port->split_group = split_group; 2955 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 2956} 2957EXPORT_SYMBOL_GPL(devlink_port_split_set); 2958 2959int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, 2960 u32 size, u16 ingress_pools_count, 2961 u16 egress_pools_count, u16 ingress_tc_count, 2962 u16 egress_tc_count) 2963{ 2964 struct devlink_sb *devlink_sb; 2965 int err = 0; 2966 2967 mutex_lock(&devlink->lock); 2968 if (devlink_sb_index_exists(devlink, sb_index)) { 2969 err = -EEXIST; 2970 goto unlock; 2971 } 2972 2973 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL); 2974 if (!devlink_sb) { 2975 err = -ENOMEM; 2976 goto unlock; 2977 } 2978 devlink_sb->index = sb_index; 2979 devlink_sb->size = size; 2980 devlink_sb->ingress_pools_count = ingress_pools_count; 2981 devlink_sb->egress_pools_count = egress_pools_count; 2982 devlink_sb->ingress_tc_count = ingress_tc_count; 2983 devlink_sb->egress_tc_count = egress_tc_count; 2984 list_add_tail(&devlink_sb->list, &devlink->sb_list); 2985unlock: 2986 mutex_unlock(&devlink->lock); 2987 return err; 2988} 2989EXPORT_SYMBOL_GPL(devlink_sb_register); 2990 2991void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index) 2992{ 2993 struct devlink_sb *devlink_sb; 2994 2995 mutex_lock(&devlink->lock); 2996 devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 2997 WARN_ON(!devlink_sb); 2998 list_del(&devlink_sb->list); 2999 mutex_unlock(&devlink->lock); 3000 kfree(devlink_sb); 3001} 3002EXPORT_SYMBOL_GPL(devlink_sb_unregister); 3003 3004/** 3005 * devlink_dpipe_headers_register - register dpipe headers 3006 * 3007 * @devlink: devlink 3008 * @dpipe_headers: dpipe header array 3009 * 3010 * Register the headers supported by hardware. 3011 */ 3012int devlink_dpipe_headers_register(struct devlink *devlink, 3013 struct devlink_dpipe_headers *dpipe_headers) 3014{ 3015 mutex_lock(&devlink->lock); 3016 devlink->dpipe_headers = dpipe_headers; 3017 mutex_unlock(&devlink->lock); 3018 return 0; 3019} 3020EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register); 3021 3022/** 3023 * devlink_dpipe_headers_unregister - unregister dpipe headers 3024 * 3025 * @devlink: devlink 3026 * 3027 * Unregister the headers supported by hardware. 3028 */ 3029void devlink_dpipe_headers_unregister(struct devlink *devlink) 3030{ 3031 mutex_lock(&devlink->lock); 3032 devlink->dpipe_headers = NULL; 3033 mutex_unlock(&devlink->lock); 3034} 3035EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister); 3036 3037/** 3038 * devlink_dpipe_table_counter_enabled - check if counter allocation 3039 * required 3040 * @devlink: devlink 3041 * @table_name: tables name 3042 * 3043 * Used by driver to check if counter allocation is required. 3044 * After counter allocation is turned on the table entries 3045 * are updated to include counter statistics. 3046 * 3047 * After that point on the driver must respect the counter 3048 * state so that each entry added to the table is added 3049 * with a counter. 3050 */ 3051bool devlink_dpipe_table_counter_enabled(struct devlink *devlink, 3052 const char *table_name) 3053{ 3054 struct devlink_dpipe_table *table; 3055 bool enabled; 3056 3057 rcu_read_lock(); 3058 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 3059 table_name); 3060 enabled = false; 3061 if (table) 3062 enabled = table->counters_enabled; 3063 rcu_read_unlock(); 3064 return enabled; 3065} 3066EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled); 3067 3068/** 3069 * devlink_dpipe_table_register - register dpipe table 3070 * 3071 * @devlink: devlink 3072 * @table_name: table name 3073 * @table_ops: table ops 3074 * @priv: priv 3075 * @counter_control_extern: external control for counters 3076 */ 3077int devlink_dpipe_table_register(struct devlink *devlink, 3078 const char *table_name, 3079 struct devlink_dpipe_table_ops *table_ops, 3080 void *priv, bool counter_control_extern) 3081{ 3082 struct devlink_dpipe_table *table; 3083 3084 if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name)) 3085 return -EEXIST; 3086 3087 if (WARN_ON(!table_ops->size_get)) 3088 return -EINVAL; 3089 3090 table = kzalloc(sizeof(*table), GFP_KERNEL); 3091 if (!table) 3092 return -ENOMEM; 3093 3094 table->name = table_name; 3095 table->table_ops = table_ops; 3096 table->priv = priv; 3097 table->counter_control_extern = counter_control_extern; 3098 3099 mutex_lock(&devlink->lock); 3100 list_add_tail_rcu(&table->list, &devlink->dpipe_table_list); 3101 mutex_unlock(&devlink->lock); 3102 return 0; 3103} 3104EXPORT_SYMBOL_GPL(devlink_dpipe_table_register); 3105 3106/** 3107 * devlink_dpipe_table_unregister - unregister dpipe table 3108 * 3109 * @devlink: devlink 3110 * @table_name: table name 3111 */ 3112void devlink_dpipe_table_unregister(struct devlink *devlink, 3113 const char *table_name) 3114{ 3115 struct devlink_dpipe_table *table; 3116 3117 mutex_lock(&devlink->lock); 3118 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 3119 table_name); 3120 if (!table) 3121 goto unlock; 3122 list_del_rcu(&table->list); 3123 mutex_unlock(&devlink->lock); 3124 kfree_rcu(table, rcu); 3125 return; 3126unlock: 3127 mutex_unlock(&devlink->lock); 3128} 3129EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister); 3130 3131/** 3132 * devlink_resource_register - devlink resource register 3133 * 3134 * @devlink: devlink 3135 * @resource_name: resource's name 3136 * @top_hierarchy: top hierarchy 3137 * @reload_required: reload is required for new configuration to 3138 * apply 3139 * @resource_size: resource's size 3140 * @resource_id: resource's id 3141 * @parent_reosurce_id: resource's parent id 3142 * @size params: size parameters 3143 * @resource_ops: resource ops 3144 */ 3145int devlink_resource_register(struct devlink *devlink, 3146 const char *resource_name, 3147 bool top_hierarchy, 3148 u64 resource_size, 3149 u64 resource_id, 3150 u64 parent_resource_id, 3151 const struct devlink_resource_size_params *size_params, 3152 const struct devlink_resource_ops *resource_ops) 3153{ 3154 struct devlink_resource *resource; 3155 struct list_head *resource_list; 3156 int err = 0; 3157 3158 mutex_lock(&devlink->lock); 3159 resource = devlink_resource_find(devlink, NULL, resource_id); 3160 if (resource) { 3161 err = -EINVAL; 3162 goto out; 3163 } 3164 3165 resource = kzalloc(sizeof(*resource), GFP_KERNEL); 3166 if (!resource) { 3167 err = -ENOMEM; 3168 goto out; 3169 } 3170 3171 if (top_hierarchy) { 3172 resource_list = &devlink->resource_list; 3173 } else { 3174 struct devlink_resource *parent_resource; 3175 3176 parent_resource = devlink_resource_find(devlink, NULL, 3177 parent_resource_id); 3178 if (parent_resource) { 3179 resource_list = &parent_resource->resource_list; 3180 resource->parent = parent_resource; 3181 } else { 3182 kfree(resource); 3183 err = -EINVAL; 3184 goto out; 3185 } 3186 } 3187 3188 resource->name = resource_name; 3189 resource->size = resource_size; 3190 resource->size_new = resource_size; 3191 resource->id = resource_id; 3192 resource->resource_ops = resource_ops; 3193 resource->size_valid = true; 3194 memcpy(&resource->size_params, size_params, 3195 sizeof(resource->size_params)); 3196 INIT_LIST_HEAD(&resource->resource_list); 3197 list_add_tail(&resource->list, resource_list); 3198out: 3199 mutex_unlock(&devlink->lock); 3200 return err; 3201} 3202EXPORT_SYMBOL_GPL(devlink_resource_register); 3203 3204/** 3205 * devlink_resources_unregister - free all resources 3206 * 3207 * @devlink: devlink 3208 * @resource: resource 3209 */ 3210void devlink_resources_unregister(struct devlink *devlink, 3211 struct devlink_resource *resource) 3212{ 3213 struct devlink_resource *tmp, *child_resource; 3214 struct list_head *resource_list; 3215 3216 if (resource) 3217 resource_list = &resource->resource_list; 3218 else 3219 resource_list = &devlink->resource_list; 3220 3221 if (!resource) 3222 mutex_lock(&devlink->lock); 3223 3224 list_for_each_entry_safe(child_resource, tmp, resource_list, list) { 3225 devlink_resources_unregister(devlink, child_resource); 3226 list_del(&child_resource->list); 3227 kfree(child_resource); 3228 } 3229 3230 if (!resource) 3231 mutex_unlock(&devlink->lock); 3232} 3233EXPORT_SYMBOL_GPL(devlink_resources_unregister); 3234 3235/** 3236 * devlink_resource_size_get - get and update size 3237 * 3238 * @devlink: devlink 3239 * @resource_id: the requested resource id 3240 * @p_resource_size: ptr to update 3241 */ 3242int devlink_resource_size_get(struct devlink *devlink, 3243 u64 resource_id, 3244 u64 *p_resource_size) 3245{ 3246 struct devlink_resource *resource; 3247 int err = 0; 3248 3249 mutex_lock(&devlink->lock); 3250 resource = devlink_resource_find(devlink, NULL, resource_id); 3251 if (!resource) { 3252 err = -EINVAL; 3253 goto out; 3254 } 3255 *p_resource_size = resource->size_new; 3256 resource->size = resource->size_new; 3257out: 3258 mutex_unlock(&devlink->lock); 3259 return err; 3260} 3261EXPORT_SYMBOL_GPL(devlink_resource_size_get); 3262 3263/** 3264 * devlink_dpipe_table_resource_set - set the resource id 3265 * 3266 * @devlink: devlink 3267 * @table_name: table name 3268 * @resource_id: resource id 3269 * @resource_units: number of resource's units consumed per table's entry 3270 */ 3271int devlink_dpipe_table_resource_set(struct devlink *devlink, 3272 const char *table_name, u64 resource_id, 3273 u64 resource_units) 3274{ 3275 struct devlink_dpipe_table *table; 3276 int err = 0; 3277 3278 mutex_lock(&devlink->lock); 3279 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 3280 table_name); 3281 if (!table) { 3282 err = -EINVAL; 3283 goto out; 3284 } 3285 table->resource_id = resource_id; 3286 table->resource_units = resource_units; 3287 table->resource_valid = true; 3288out: 3289 mutex_unlock(&devlink->lock); 3290 return err; 3291} 3292EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set); 3293 3294static int __init devlink_module_init(void) 3295{ 3296 return genl_register_family(&devlink_nl_family); 3297} 3298 3299static void __exit devlink_module_exit(void) 3300{ 3301 genl_unregister_family(&devlink_nl_family); 3302} 3303 3304module_init(devlink_module_init); 3305module_exit(devlink_module_exit); 3306 3307MODULE_LICENSE("GPL v2"); 3308MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>"); 3309MODULE_DESCRIPTION("Network physical device Netlink interface"); 3310MODULE_ALIAS_GENL_FAMILY(DEVLINK_GENL_NAME);