at v5.0 125 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 329struct devlink_region { 330 struct devlink *devlink; 331 struct list_head list; 332 const char *name; 333 struct list_head snapshot_list; 334 u32 max_snapshots; 335 u32 cur_snapshots; 336 u64 size; 337}; 338 339struct devlink_snapshot { 340 struct list_head list; 341 struct devlink_region *region; 342 devlink_snapshot_data_dest_t *data_destructor; 343 u64 data_len; 344 u8 *data; 345 u32 id; 346}; 347 348static struct devlink_region * 349devlink_region_get_by_name(struct devlink *devlink, const char *region_name) 350{ 351 struct devlink_region *region; 352 353 list_for_each_entry(region, &devlink->region_list, list) 354 if (!strcmp(region->name, region_name)) 355 return region; 356 357 return NULL; 358} 359 360static struct devlink_snapshot * 361devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id) 362{ 363 struct devlink_snapshot *snapshot; 364 365 list_for_each_entry(snapshot, &region->snapshot_list, list) 366 if (snapshot->id == id) 367 return snapshot; 368 369 return NULL; 370} 371 372static void devlink_region_snapshot_del(struct devlink_snapshot *snapshot) 373{ 374 snapshot->region->cur_snapshots--; 375 list_del(&snapshot->list); 376 (*snapshot->data_destructor)(snapshot->data); 377 kfree(snapshot); 378} 379 380#define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0) 381#define DEVLINK_NL_FLAG_NEED_PORT BIT(1) 382#define DEVLINK_NL_FLAG_NEED_SB BIT(2) 383 384/* The per devlink instance lock is taken by default in the pre-doit 385 * operation, yet several commands do not require this. The global 386 * devlink lock is taken and protects from disruption by user-calls. 387 */ 388#define DEVLINK_NL_FLAG_NO_LOCK BIT(3) 389 390static int devlink_nl_pre_doit(const struct genl_ops *ops, 391 struct sk_buff *skb, struct genl_info *info) 392{ 393 struct devlink *devlink; 394 int err; 395 396 mutex_lock(&devlink_mutex); 397 devlink = devlink_get_from_info(info); 398 if (IS_ERR(devlink)) { 399 mutex_unlock(&devlink_mutex); 400 return PTR_ERR(devlink); 401 } 402 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 403 mutex_lock(&devlink->lock); 404 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) { 405 info->user_ptr[0] = devlink; 406 } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) { 407 struct devlink_port *devlink_port; 408 409 devlink_port = devlink_port_get_from_info(devlink, info); 410 if (IS_ERR(devlink_port)) { 411 err = PTR_ERR(devlink_port); 412 goto unlock; 413 } 414 info->user_ptr[0] = devlink_port; 415 } 416 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) { 417 struct devlink_sb *devlink_sb; 418 419 devlink_sb = devlink_sb_get_from_info(devlink, info); 420 if (IS_ERR(devlink_sb)) { 421 err = PTR_ERR(devlink_sb); 422 goto unlock; 423 } 424 info->user_ptr[1] = devlink_sb; 425 } 426 return 0; 427 428unlock: 429 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 430 mutex_unlock(&devlink->lock); 431 mutex_unlock(&devlink_mutex); 432 return err; 433} 434 435static void devlink_nl_post_doit(const struct genl_ops *ops, 436 struct sk_buff *skb, struct genl_info *info) 437{ 438 struct devlink *devlink; 439 440 devlink = devlink_get_from_info(info); 441 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 442 mutex_unlock(&devlink->lock); 443 mutex_unlock(&devlink_mutex); 444} 445 446static struct genl_family devlink_nl_family; 447 448enum devlink_multicast_groups { 449 DEVLINK_MCGRP_CONFIG, 450}; 451 452static const struct genl_multicast_group devlink_nl_mcgrps[] = { 453 [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME }, 454}; 455 456static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink) 457{ 458 if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name)) 459 return -EMSGSIZE; 460 if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev))) 461 return -EMSGSIZE; 462 return 0; 463} 464 465static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink, 466 enum devlink_command cmd, u32 portid, 467 u32 seq, int flags) 468{ 469 void *hdr; 470 471 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 472 if (!hdr) 473 return -EMSGSIZE; 474 475 if (devlink_nl_put_handle(msg, devlink)) 476 goto nla_put_failure; 477 478 genlmsg_end(msg, hdr); 479 return 0; 480 481nla_put_failure: 482 genlmsg_cancel(msg, hdr); 483 return -EMSGSIZE; 484} 485 486static void devlink_notify(struct devlink *devlink, enum devlink_command cmd) 487{ 488 struct sk_buff *msg; 489 int err; 490 491 WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL); 492 493 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 494 if (!msg) 495 return; 496 497 err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0); 498 if (err) { 499 nlmsg_free(msg); 500 return; 501 } 502 503 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 504 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 505} 506 507static int devlink_nl_port_attrs_put(struct sk_buff *msg, 508 struct devlink_port *devlink_port) 509{ 510 struct devlink_port_attrs *attrs = &devlink_port->attrs; 511 512 if (!attrs->set) 513 return 0; 514 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour)) 515 return -EMSGSIZE; 516 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER, attrs->port_number)) 517 return -EMSGSIZE; 518 if (!attrs->split) 519 return 0; 520 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP, attrs->port_number)) 521 return -EMSGSIZE; 522 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER, 523 attrs->split_subport_number)) 524 return -EMSGSIZE; 525 return 0; 526} 527 528static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink, 529 struct devlink_port *devlink_port, 530 enum devlink_command cmd, u32 portid, 531 u32 seq, int flags) 532{ 533 void *hdr; 534 535 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 536 if (!hdr) 537 return -EMSGSIZE; 538 539 if (devlink_nl_put_handle(msg, devlink)) 540 goto nla_put_failure; 541 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 542 goto nla_put_failure; 543 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type)) 544 goto nla_put_failure; 545 if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET && 546 nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE, 547 devlink_port->desired_type)) 548 goto nla_put_failure; 549 if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) { 550 struct net_device *netdev = devlink_port->type_dev; 551 552 if (netdev && 553 (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX, 554 netdev->ifindex) || 555 nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME, 556 netdev->name))) 557 goto nla_put_failure; 558 } 559 if (devlink_port->type == DEVLINK_PORT_TYPE_IB) { 560 struct ib_device *ibdev = devlink_port->type_dev; 561 562 if (ibdev && 563 nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME, 564 ibdev->name)) 565 goto nla_put_failure; 566 } 567 if (devlink_nl_port_attrs_put(msg, devlink_port)) 568 goto nla_put_failure; 569 570 genlmsg_end(msg, hdr); 571 return 0; 572 573nla_put_failure: 574 genlmsg_cancel(msg, hdr); 575 return -EMSGSIZE; 576} 577 578static void devlink_port_notify(struct devlink_port *devlink_port, 579 enum devlink_command cmd) 580{ 581 struct devlink *devlink = devlink_port->devlink; 582 struct sk_buff *msg; 583 int err; 584 585 if (!devlink_port->registered) 586 return; 587 588 WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL); 589 590 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 591 if (!msg) 592 return; 593 594 err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0); 595 if (err) { 596 nlmsg_free(msg); 597 return; 598 } 599 600 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 601 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 602} 603 604static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info) 605{ 606 struct devlink *devlink = info->user_ptr[0]; 607 struct sk_buff *msg; 608 int err; 609 610 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 611 if (!msg) 612 return -ENOMEM; 613 614 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW, 615 info->snd_portid, info->snd_seq, 0); 616 if (err) { 617 nlmsg_free(msg); 618 return err; 619 } 620 621 return genlmsg_reply(msg, info); 622} 623 624static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg, 625 struct netlink_callback *cb) 626{ 627 struct devlink *devlink; 628 int start = cb->args[0]; 629 int idx = 0; 630 int err; 631 632 mutex_lock(&devlink_mutex); 633 list_for_each_entry(devlink, &devlink_list, list) { 634 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 635 continue; 636 if (idx < start) { 637 idx++; 638 continue; 639 } 640 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW, 641 NETLINK_CB(cb->skb).portid, 642 cb->nlh->nlmsg_seq, NLM_F_MULTI); 643 if (err) 644 goto out; 645 idx++; 646 } 647out: 648 mutex_unlock(&devlink_mutex); 649 650 cb->args[0] = idx; 651 return msg->len; 652} 653 654static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb, 655 struct genl_info *info) 656{ 657 struct devlink_port *devlink_port = info->user_ptr[0]; 658 struct devlink *devlink = devlink_port->devlink; 659 struct sk_buff *msg; 660 int err; 661 662 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 663 if (!msg) 664 return -ENOMEM; 665 666 err = devlink_nl_port_fill(msg, devlink, devlink_port, 667 DEVLINK_CMD_PORT_NEW, 668 info->snd_portid, info->snd_seq, 0); 669 if (err) { 670 nlmsg_free(msg); 671 return err; 672 } 673 674 return genlmsg_reply(msg, info); 675} 676 677static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg, 678 struct netlink_callback *cb) 679{ 680 struct devlink *devlink; 681 struct devlink_port *devlink_port; 682 int start = cb->args[0]; 683 int idx = 0; 684 int err; 685 686 mutex_lock(&devlink_mutex); 687 list_for_each_entry(devlink, &devlink_list, list) { 688 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 689 continue; 690 mutex_lock(&devlink->lock); 691 list_for_each_entry(devlink_port, &devlink->port_list, list) { 692 if (idx < start) { 693 idx++; 694 continue; 695 } 696 err = devlink_nl_port_fill(msg, devlink, devlink_port, 697 DEVLINK_CMD_NEW, 698 NETLINK_CB(cb->skb).portid, 699 cb->nlh->nlmsg_seq, 700 NLM_F_MULTI); 701 if (err) { 702 mutex_unlock(&devlink->lock); 703 goto out; 704 } 705 idx++; 706 } 707 mutex_unlock(&devlink->lock); 708 } 709out: 710 mutex_unlock(&devlink_mutex); 711 712 cb->args[0] = idx; 713 return msg->len; 714} 715 716static int devlink_port_type_set(struct devlink *devlink, 717 struct devlink_port *devlink_port, 718 enum devlink_port_type port_type) 719 720{ 721 int err; 722 723 if (devlink->ops && devlink->ops->port_type_set) { 724 if (port_type == DEVLINK_PORT_TYPE_NOTSET) 725 return -EINVAL; 726 if (port_type == devlink_port->type) 727 return 0; 728 err = devlink->ops->port_type_set(devlink_port, port_type); 729 if (err) 730 return err; 731 devlink_port->desired_type = port_type; 732 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 733 return 0; 734 } 735 return -EOPNOTSUPP; 736} 737 738static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb, 739 struct genl_info *info) 740{ 741 struct devlink_port *devlink_port = info->user_ptr[0]; 742 struct devlink *devlink = devlink_port->devlink; 743 int err; 744 745 if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) { 746 enum devlink_port_type port_type; 747 748 port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]); 749 err = devlink_port_type_set(devlink, devlink_port, port_type); 750 if (err) 751 return err; 752 } 753 return 0; 754} 755 756static int devlink_port_split(struct devlink *devlink, u32 port_index, 757 u32 count, struct netlink_ext_ack *extack) 758 759{ 760 if (devlink->ops && devlink->ops->port_split) 761 return devlink->ops->port_split(devlink, port_index, count, 762 extack); 763 return -EOPNOTSUPP; 764} 765 766static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb, 767 struct genl_info *info) 768{ 769 struct devlink *devlink = info->user_ptr[0]; 770 u32 port_index; 771 u32 count; 772 773 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] || 774 !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]) 775 return -EINVAL; 776 777 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 778 count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]); 779 return devlink_port_split(devlink, port_index, count, info->extack); 780} 781 782static int devlink_port_unsplit(struct devlink *devlink, u32 port_index, 783 struct netlink_ext_ack *extack) 784 785{ 786 if (devlink->ops && devlink->ops->port_unsplit) 787 return devlink->ops->port_unsplit(devlink, port_index, extack); 788 return -EOPNOTSUPP; 789} 790 791static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb, 792 struct genl_info *info) 793{ 794 struct devlink *devlink = info->user_ptr[0]; 795 u32 port_index; 796 797 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX]) 798 return -EINVAL; 799 800 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 801 return devlink_port_unsplit(devlink, port_index, info->extack); 802} 803 804static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink, 805 struct devlink_sb *devlink_sb, 806 enum devlink_command cmd, u32 portid, 807 u32 seq, int flags) 808{ 809 void *hdr; 810 811 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 812 if (!hdr) 813 return -EMSGSIZE; 814 815 if (devlink_nl_put_handle(msg, devlink)) 816 goto nla_put_failure; 817 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 818 goto nla_put_failure; 819 if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size)) 820 goto nla_put_failure; 821 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT, 822 devlink_sb->ingress_pools_count)) 823 goto nla_put_failure; 824 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT, 825 devlink_sb->egress_pools_count)) 826 goto nla_put_failure; 827 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT, 828 devlink_sb->ingress_tc_count)) 829 goto nla_put_failure; 830 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT, 831 devlink_sb->egress_tc_count)) 832 goto nla_put_failure; 833 834 genlmsg_end(msg, hdr); 835 return 0; 836 837nla_put_failure: 838 genlmsg_cancel(msg, hdr); 839 return -EMSGSIZE; 840} 841 842static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb, 843 struct genl_info *info) 844{ 845 struct devlink *devlink = info->user_ptr[0]; 846 struct devlink_sb *devlink_sb = info->user_ptr[1]; 847 struct sk_buff *msg; 848 int err; 849 850 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 851 if (!msg) 852 return -ENOMEM; 853 854 err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 855 DEVLINK_CMD_SB_NEW, 856 info->snd_portid, info->snd_seq, 0); 857 if (err) { 858 nlmsg_free(msg); 859 return err; 860 } 861 862 return genlmsg_reply(msg, info); 863} 864 865static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg, 866 struct netlink_callback *cb) 867{ 868 struct devlink *devlink; 869 struct devlink_sb *devlink_sb; 870 int start = cb->args[0]; 871 int idx = 0; 872 int err; 873 874 mutex_lock(&devlink_mutex); 875 list_for_each_entry(devlink, &devlink_list, list) { 876 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 877 continue; 878 mutex_lock(&devlink->lock); 879 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 880 if (idx < start) { 881 idx++; 882 continue; 883 } 884 err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 885 DEVLINK_CMD_SB_NEW, 886 NETLINK_CB(cb->skb).portid, 887 cb->nlh->nlmsg_seq, 888 NLM_F_MULTI); 889 if (err) { 890 mutex_unlock(&devlink->lock); 891 goto out; 892 } 893 idx++; 894 } 895 mutex_unlock(&devlink->lock); 896 } 897out: 898 mutex_unlock(&devlink_mutex); 899 900 cb->args[0] = idx; 901 return msg->len; 902} 903 904static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink, 905 struct devlink_sb *devlink_sb, 906 u16 pool_index, enum devlink_command cmd, 907 u32 portid, u32 seq, int flags) 908{ 909 struct devlink_sb_pool_info pool_info; 910 void *hdr; 911 int err; 912 913 err = devlink->ops->sb_pool_get(devlink, devlink_sb->index, 914 pool_index, &pool_info); 915 if (err) 916 return err; 917 918 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 919 if (!hdr) 920 return -EMSGSIZE; 921 922 if (devlink_nl_put_handle(msg, devlink)) 923 goto nla_put_failure; 924 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 925 goto nla_put_failure; 926 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 927 goto nla_put_failure; 928 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type)) 929 goto nla_put_failure; 930 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size)) 931 goto nla_put_failure; 932 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, 933 pool_info.threshold_type)) 934 goto nla_put_failure; 935 936 genlmsg_end(msg, hdr); 937 return 0; 938 939nla_put_failure: 940 genlmsg_cancel(msg, hdr); 941 return -EMSGSIZE; 942} 943 944static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb, 945 struct genl_info *info) 946{ 947 struct devlink *devlink = info->user_ptr[0]; 948 struct devlink_sb *devlink_sb = info->user_ptr[1]; 949 struct sk_buff *msg; 950 u16 pool_index; 951 int err; 952 953 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 954 &pool_index); 955 if (err) 956 return err; 957 958 if (!devlink->ops || !devlink->ops->sb_pool_get) 959 return -EOPNOTSUPP; 960 961 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 962 if (!msg) 963 return -ENOMEM; 964 965 err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index, 966 DEVLINK_CMD_SB_POOL_NEW, 967 info->snd_portid, info->snd_seq, 0); 968 if (err) { 969 nlmsg_free(msg); 970 return err; 971 } 972 973 return genlmsg_reply(msg, info); 974} 975 976static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 977 struct devlink *devlink, 978 struct devlink_sb *devlink_sb, 979 u32 portid, u32 seq) 980{ 981 u16 pool_count = devlink_sb_pool_count(devlink_sb); 982 u16 pool_index; 983 int err; 984 985 for (pool_index = 0; pool_index < pool_count; pool_index++) { 986 if (*p_idx < start) { 987 (*p_idx)++; 988 continue; 989 } 990 err = devlink_nl_sb_pool_fill(msg, devlink, 991 devlink_sb, 992 pool_index, 993 DEVLINK_CMD_SB_POOL_NEW, 994 portid, seq, NLM_F_MULTI); 995 if (err) 996 return err; 997 (*p_idx)++; 998 } 999 return 0; 1000} 1001 1002static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg, 1003 struct netlink_callback *cb) 1004{ 1005 struct devlink *devlink; 1006 struct devlink_sb *devlink_sb; 1007 int start = cb->args[0]; 1008 int idx = 0; 1009 int err; 1010 1011 mutex_lock(&devlink_mutex); 1012 list_for_each_entry(devlink, &devlink_list, list) { 1013 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 1014 !devlink->ops || !devlink->ops->sb_pool_get) 1015 continue; 1016 mutex_lock(&devlink->lock); 1017 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 1018 err = __sb_pool_get_dumpit(msg, start, &idx, devlink, 1019 devlink_sb, 1020 NETLINK_CB(cb->skb).portid, 1021 cb->nlh->nlmsg_seq); 1022 if (err && err != -EOPNOTSUPP) { 1023 mutex_unlock(&devlink->lock); 1024 goto out; 1025 } 1026 } 1027 mutex_unlock(&devlink->lock); 1028 } 1029out: 1030 mutex_unlock(&devlink_mutex); 1031 1032 cb->args[0] = idx; 1033 return msg->len; 1034} 1035 1036static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index, 1037 u16 pool_index, u32 size, 1038 enum devlink_sb_threshold_type threshold_type) 1039 1040{ 1041 const struct devlink_ops *ops = devlink->ops; 1042 1043 if (ops && ops->sb_pool_set) 1044 return ops->sb_pool_set(devlink, sb_index, pool_index, 1045 size, threshold_type); 1046 return -EOPNOTSUPP; 1047} 1048 1049static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb, 1050 struct genl_info *info) 1051{ 1052 struct devlink *devlink = info->user_ptr[0]; 1053 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1054 enum devlink_sb_threshold_type threshold_type; 1055 u16 pool_index; 1056 u32 size; 1057 int err; 1058 1059 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1060 &pool_index); 1061 if (err) 1062 return err; 1063 1064 err = devlink_sb_th_type_get_from_info(info, &threshold_type); 1065 if (err) 1066 return err; 1067 1068 if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]) 1069 return -EINVAL; 1070 1071 size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]); 1072 return devlink_sb_pool_set(devlink, devlink_sb->index, 1073 pool_index, size, threshold_type); 1074} 1075 1076static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg, 1077 struct devlink *devlink, 1078 struct devlink_port *devlink_port, 1079 struct devlink_sb *devlink_sb, 1080 u16 pool_index, 1081 enum devlink_command cmd, 1082 u32 portid, u32 seq, int flags) 1083{ 1084 const struct devlink_ops *ops = devlink->ops; 1085 u32 threshold; 1086 void *hdr; 1087 int err; 1088 1089 err = ops->sb_port_pool_get(devlink_port, devlink_sb->index, 1090 pool_index, &threshold); 1091 if (err) 1092 return err; 1093 1094 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1095 if (!hdr) 1096 return -EMSGSIZE; 1097 1098 if (devlink_nl_put_handle(msg, devlink)) 1099 goto nla_put_failure; 1100 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 1101 goto nla_put_failure; 1102 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 1103 goto nla_put_failure; 1104 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 1105 goto nla_put_failure; 1106 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 1107 goto nla_put_failure; 1108 1109 if (ops->sb_occ_port_pool_get) { 1110 u32 cur; 1111 u32 max; 1112 1113 err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index, 1114 pool_index, &cur, &max); 1115 if (err && err != -EOPNOTSUPP) 1116 return err; 1117 if (!err) { 1118 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 1119 goto nla_put_failure; 1120 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 1121 goto nla_put_failure; 1122 } 1123 } 1124 1125 genlmsg_end(msg, hdr); 1126 return 0; 1127 1128nla_put_failure: 1129 genlmsg_cancel(msg, hdr); 1130 return -EMSGSIZE; 1131} 1132 1133static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb, 1134 struct genl_info *info) 1135{ 1136 struct devlink_port *devlink_port = info->user_ptr[0]; 1137 struct devlink *devlink = devlink_port->devlink; 1138 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1139 struct sk_buff *msg; 1140 u16 pool_index; 1141 int err; 1142 1143 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1144 &pool_index); 1145 if (err) 1146 return err; 1147 1148 if (!devlink->ops || !devlink->ops->sb_port_pool_get) 1149 return -EOPNOTSUPP; 1150 1151 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1152 if (!msg) 1153 return -ENOMEM; 1154 1155 err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port, 1156 devlink_sb, pool_index, 1157 DEVLINK_CMD_SB_PORT_POOL_NEW, 1158 info->snd_portid, info->snd_seq, 0); 1159 if (err) { 1160 nlmsg_free(msg); 1161 return err; 1162 } 1163 1164 return genlmsg_reply(msg, info); 1165} 1166 1167static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 1168 struct devlink *devlink, 1169 struct devlink_sb *devlink_sb, 1170 u32 portid, u32 seq) 1171{ 1172 struct devlink_port *devlink_port; 1173 u16 pool_count = devlink_sb_pool_count(devlink_sb); 1174 u16 pool_index; 1175 int err; 1176 1177 list_for_each_entry(devlink_port, &devlink->port_list, list) { 1178 for (pool_index = 0; pool_index < pool_count; pool_index++) { 1179 if (*p_idx < start) { 1180 (*p_idx)++; 1181 continue; 1182 } 1183 err = devlink_nl_sb_port_pool_fill(msg, devlink, 1184 devlink_port, 1185 devlink_sb, 1186 pool_index, 1187 DEVLINK_CMD_SB_PORT_POOL_NEW, 1188 portid, seq, 1189 NLM_F_MULTI); 1190 if (err) 1191 return err; 1192 (*p_idx)++; 1193 } 1194 } 1195 return 0; 1196} 1197 1198static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg, 1199 struct netlink_callback *cb) 1200{ 1201 struct devlink *devlink; 1202 struct devlink_sb *devlink_sb; 1203 int start = cb->args[0]; 1204 int idx = 0; 1205 int err; 1206 1207 mutex_lock(&devlink_mutex); 1208 list_for_each_entry(devlink, &devlink_list, list) { 1209 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 1210 !devlink->ops || !devlink->ops->sb_port_pool_get) 1211 continue; 1212 mutex_lock(&devlink->lock); 1213 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 1214 err = __sb_port_pool_get_dumpit(msg, start, &idx, 1215 devlink, devlink_sb, 1216 NETLINK_CB(cb->skb).portid, 1217 cb->nlh->nlmsg_seq); 1218 if (err && err != -EOPNOTSUPP) { 1219 mutex_unlock(&devlink->lock); 1220 goto out; 1221 } 1222 } 1223 mutex_unlock(&devlink->lock); 1224 } 1225out: 1226 mutex_unlock(&devlink_mutex); 1227 1228 cb->args[0] = idx; 1229 return msg->len; 1230} 1231 1232static int devlink_sb_port_pool_set(struct devlink_port *devlink_port, 1233 unsigned int sb_index, u16 pool_index, 1234 u32 threshold) 1235 1236{ 1237 const struct devlink_ops *ops = devlink_port->devlink->ops; 1238 1239 if (ops && ops->sb_port_pool_set) 1240 return ops->sb_port_pool_set(devlink_port, sb_index, 1241 pool_index, threshold); 1242 return -EOPNOTSUPP; 1243} 1244 1245static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb, 1246 struct genl_info *info) 1247{ 1248 struct devlink_port *devlink_port = info->user_ptr[0]; 1249 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1250 u16 pool_index; 1251 u32 threshold; 1252 int err; 1253 1254 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1255 &pool_index); 1256 if (err) 1257 return err; 1258 1259 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD]) 1260 return -EINVAL; 1261 1262 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 1263 return devlink_sb_port_pool_set(devlink_port, devlink_sb->index, 1264 pool_index, threshold); 1265} 1266 1267static int 1268devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink, 1269 struct devlink_port *devlink_port, 1270 struct devlink_sb *devlink_sb, u16 tc_index, 1271 enum devlink_sb_pool_type pool_type, 1272 enum devlink_command cmd, 1273 u32 portid, u32 seq, int flags) 1274{ 1275 const struct devlink_ops *ops = devlink->ops; 1276 u16 pool_index; 1277 u32 threshold; 1278 void *hdr; 1279 int err; 1280 1281 err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index, 1282 tc_index, pool_type, 1283 &pool_index, &threshold); 1284 if (err) 1285 return err; 1286 1287 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1288 if (!hdr) 1289 return -EMSGSIZE; 1290 1291 if (devlink_nl_put_handle(msg, devlink)) 1292 goto nla_put_failure; 1293 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 1294 goto nla_put_failure; 1295 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 1296 goto nla_put_failure; 1297 if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index)) 1298 goto nla_put_failure; 1299 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type)) 1300 goto nla_put_failure; 1301 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 1302 goto nla_put_failure; 1303 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 1304 goto nla_put_failure; 1305 1306 if (ops->sb_occ_tc_port_bind_get) { 1307 u32 cur; 1308 u32 max; 1309 1310 err = ops->sb_occ_tc_port_bind_get(devlink_port, 1311 devlink_sb->index, 1312 tc_index, pool_type, 1313 &cur, &max); 1314 if (err && err != -EOPNOTSUPP) 1315 return err; 1316 if (!err) { 1317 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 1318 goto nla_put_failure; 1319 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 1320 goto nla_put_failure; 1321 } 1322 } 1323 1324 genlmsg_end(msg, hdr); 1325 return 0; 1326 1327nla_put_failure: 1328 genlmsg_cancel(msg, hdr); 1329 return -EMSGSIZE; 1330} 1331 1332static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb, 1333 struct genl_info *info) 1334{ 1335 struct devlink_port *devlink_port = info->user_ptr[0]; 1336 struct devlink *devlink = devlink_port->devlink; 1337 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1338 struct sk_buff *msg; 1339 enum devlink_sb_pool_type pool_type; 1340 u16 tc_index; 1341 int err; 1342 1343 err = devlink_sb_pool_type_get_from_info(info, &pool_type); 1344 if (err) 1345 return err; 1346 1347 err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 1348 pool_type, &tc_index); 1349 if (err) 1350 return err; 1351 1352 if (!devlink->ops || !devlink->ops->sb_tc_pool_bind_get) 1353 return -EOPNOTSUPP; 1354 1355 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1356 if (!msg) 1357 return -ENOMEM; 1358 1359 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port, 1360 devlink_sb, tc_index, pool_type, 1361 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1362 info->snd_portid, 1363 info->snd_seq, 0); 1364 if (err) { 1365 nlmsg_free(msg); 1366 return err; 1367 } 1368 1369 return genlmsg_reply(msg, info); 1370} 1371 1372static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, 1373 int start, int *p_idx, 1374 struct devlink *devlink, 1375 struct devlink_sb *devlink_sb, 1376 u32 portid, u32 seq) 1377{ 1378 struct devlink_port *devlink_port; 1379 u16 tc_index; 1380 int err; 1381 1382 list_for_each_entry(devlink_port, &devlink->port_list, list) { 1383 for (tc_index = 0; 1384 tc_index < devlink_sb->ingress_tc_count; tc_index++) { 1385 if (*p_idx < start) { 1386 (*p_idx)++; 1387 continue; 1388 } 1389 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 1390 devlink_port, 1391 devlink_sb, 1392 tc_index, 1393 DEVLINK_SB_POOL_TYPE_INGRESS, 1394 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1395 portid, seq, 1396 NLM_F_MULTI); 1397 if (err) 1398 return err; 1399 (*p_idx)++; 1400 } 1401 for (tc_index = 0; 1402 tc_index < devlink_sb->egress_tc_count; tc_index++) { 1403 if (*p_idx < start) { 1404 (*p_idx)++; 1405 continue; 1406 } 1407 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 1408 devlink_port, 1409 devlink_sb, 1410 tc_index, 1411 DEVLINK_SB_POOL_TYPE_EGRESS, 1412 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1413 portid, seq, 1414 NLM_F_MULTI); 1415 if (err) 1416 return err; 1417 (*p_idx)++; 1418 } 1419 } 1420 return 0; 1421} 1422 1423static int 1424devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, 1425 struct netlink_callback *cb) 1426{ 1427 struct devlink *devlink; 1428 struct devlink_sb *devlink_sb; 1429 int start = cb->args[0]; 1430 int idx = 0; 1431 int err; 1432 1433 mutex_lock(&devlink_mutex); 1434 list_for_each_entry(devlink, &devlink_list, list) { 1435 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 1436 !devlink->ops || !devlink->ops->sb_tc_pool_bind_get) 1437 continue; 1438 1439 mutex_lock(&devlink->lock); 1440 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 1441 err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx, 1442 devlink, 1443 devlink_sb, 1444 NETLINK_CB(cb->skb).portid, 1445 cb->nlh->nlmsg_seq); 1446 if (err && err != -EOPNOTSUPP) { 1447 mutex_unlock(&devlink->lock); 1448 goto out; 1449 } 1450 } 1451 mutex_unlock(&devlink->lock); 1452 } 1453out: 1454 mutex_unlock(&devlink_mutex); 1455 1456 cb->args[0] = idx; 1457 return msg->len; 1458} 1459 1460static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port, 1461 unsigned int sb_index, u16 tc_index, 1462 enum devlink_sb_pool_type pool_type, 1463 u16 pool_index, u32 threshold) 1464 1465{ 1466 const struct devlink_ops *ops = devlink_port->devlink->ops; 1467 1468 if (ops && ops->sb_tc_pool_bind_set) 1469 return ops->sb_tc_pool_bind_set(devlink_port, sb_index, 1470 tc_index, pool_type, 1471 pool_index, threshold); 1472 return -EOPNOTSUPP; 1473} 1474 1475static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb, 1476 struct genl_info *info) 1477{ 1478 struct devlink_port *devlink_port = info->user_ptr[0]; 1479 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1480 enum devlink_sb_pool_type pool_type; 1481 u16 tc_index; 1482 u16 pool_index; 1483 u32 threshold; 1484 int err; 1485 1486 err = devlink_sb_pool_type_get_from_info(info, &pool_type); 1487 if (err) 1488 return err; 1489 1490 err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 1491 pool_type, &tc_index); 1492 if (err) 1493 return err; 1494 1495 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1496 &pool_index); 1497 if (err) 1498 return err; 1499 1500 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD]) 1501 return -EINVAL; 1502 1503 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 1504 return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index, 1505 tc_index, pool_type, 1506 pool_index, threshold); 1507} 1508 1509static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb, 1510 struct genl_info *info) 1511{ 1512 struct devlink *devlink = info->user_ptr[0]; 1513 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1514 const struct devlink_ops *ops = devlink->ops; 1515 1516 if (ops && ops->sb_occ_snapshot) 1517 return ops->sb_occ_snapshot(devlink, devlink_sb->index); 1518 return -EOPNOTSUPP; 1519} 1520 1521static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb, 1522 struct genl_info *info) 1523{ 1524 struct devlink *devlink = info->user_ptr[0]; 1525 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1526 const struct devlink_ops *ops = devlink->ops; 1527 1528 if (ops && ops->sb_occ_max_clear) 1529 return ops->sb_occ_max_clear(devlink, devlink_sb->index); 1530 return -EOPNOTSUPP; 1531} 1532 1533static int devlink_nl_eswitch_fill(struct sk_buff *msg, struct devlink *devlink, 1534 enum devlink_command cmd, u32 portid, 1535 u32 seq, int flags) 1536{ 1537 const struct devlink_ops *ops = devlink->ops; 1538 u8 inline_mode, encap_mode; 1539 void *hdr; 1540 int err = 0; 1541 u16 mode; 1542 1543 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1544 if (!hdr) 1545 return -EMSGSIZE; 1546 1547 err = devlink_nl_put_handle(msg, devlink); 1548 if (err) 1549 goto nla_put_failure; 1550 1551 if (ops->eswitch_mode_get) { 1552 err = ops->eswitch_mode_get(devlink, &mode); 1553 if (err) 1554 goto nla_put_failure; 1555 err = nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode); 1556 if (err) 1557 goto nla_put_failure; 1558 } 1559 1560 if (ops->eswitch_inline_mode_get) { 1561 err = ops->eswitch_inline_mode_get(devlink, &inline_mode); 1562 if (err) 1563 goto nla_put_failure; 1564 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE, 1565 inline_mode); 1566 if (err) 1567 goto nla_put_failure; 1568 } 1569 1570 if (ops->eswitch_encap_mode_get) { 1571 err = ops->eswitch_encap_mode_get(devlink, &encap_mode); 1572 if (err) 1573 goto nla_put_failure; 1574 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, encap_mode); 1575 if (err) 1576 goto nla_put_failure; 1577 } 1578 1579 genlmsg_end(msg, hdr); 1580 return 0; 1581 1582nla_put_failure: 1583 genlmsg_cancel(msg, hdr); 1584 return err; 1585} 1586 1587static int devlink_nl_cmd_eswitch_get_doit(struct sk_buff *skb, 1588 struct genl_info *info) 1589{ 1590 struct devlink *devlink = info->user_ptr[0]; 1591 const struct devlink_ops *ops = devlink->ops; 1592 struct sk_buff *msg; 1593 int err; 1594 1595 if (!ops) 1596 return -EOPNOTSUPP; 1597 1598 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1599 if (!msg) 1600 return -ENOMEM; 1601 1602 err = devlink_nl_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_GET, 1603 info->snd_portid, info->snd_seq, 0); 1604 1605 if (err) { 1606 nlmsg_free(msg); 1607 return err; 1608 } 1609 1610 return genlmsg_reply(msg, info); 1611} 1612 1613static int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb, 1614 struct genl_info *info) 1615{ 1616 struct devlink *devlink = info->user_ptr[0]; 1617 const struct devlink_ops *ops = devlink->ops; 1618 u8 inline_mode, encap_mode; 1619 int err = 0; 1620 u16 mode; 1621 1622 if (!ops) 1623 return -EOPNOTSUPP; 1624 1625 if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) { 1626 if (!ops->eswitch_mode_set) 1627 return -EOPNOTSUPP; 1628 mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]); 1629 err = ops->eswitch_mode_set(devlink, mode, info->extack); 1630 if (err) 1631 return err; 1632 } 1633 1634 if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) { 1635 if (!ops->eswitch_inline_mode_set) 1636 return -EOPNOTSUPP; 1637 inline_mode = nla_get_u8( 1638 info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]); 1639 err = ops->eswitch_inline_mode_set(devlink, inline_mode, 1640 info->extack); 1641 if (err) 1642 return err; 1643 } 1644 1645 if (info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]) { 1646 if (!ops->eswitch_encap_mode_set) 1647 return -EOPNOTSUPP; 1648 encap_mode = nla_get_u8(info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]); 1649 err = ops->eswitch_encap_mode_set(devlink, encap_mode, 1650 info->extack); 1651 if (err) 1652 return err; 1653 } 1654 1655 return 0; 1656} 1657 1658int devlink_dpipe_match_put(struct sk_buff *skb, 1659 struct devlink_dpipe_match *match) 1660{ 1661 struct devlink_dpipe_header *header = match->header; 1662 struct devlink_dpipe_field *field = &header->fields[match->field_id]; 1663 struct nlattr *match_attr; 1664 1665 match_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_MATCH); 1666 if (!match_attr) 1667 return -EMSGSIZE; 1668 1669 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_MATCH_TYPE, match->type) || 1670 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, match->header_index) || 1671 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 1672 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 1673 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 1674 goto nla_put_failure; 1675 1676 nla_nest_end(skb, match_attr); 1677 return 0; 1678 1679nla_put_failure: 1680 nla_nest_cancel(skb, match_attr); 1681 return -EMSGSIZE; 1682} 1683EXPORT_SYMBOL_GPL(devlink_dpipe_match_put); 1684 1685static int devlink_dpipe_matches_put(struct devlink_dpipe_table *table, 1686 struct sk_buff *skb) 1687{ 1688 struct nlattr *matches_attr; 1689 1690 matches_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLE_MATCHES); 1691 if (!matches_attr) 1692 return -EMSGSIZE; 1693 1694 if (table->table_ops->matches_dump(table->priv, skb)) 1695 goto nla_put_failure; 1696 1697 nla_nest_end(skb, matches_attr); 1698 return 0; 1699 1700nla_put_failure: 1701 nla_nest_cancel(skb, matches_attr); 1702 return -EMSGSIZE; 1703} 1704 1705int devlink_dpipe_action_put(struct sk_buff *skb, 1706 struct devlink_dpipe_action *action) 1707{ 1708 struct devlink_dpipe_header *header = action->header; 1709 struct devlink_dpipe_field *field = &header->fields[action->field_id]; 1710 struct nlattr *action_attr; 1711 1712 action_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_ACTION); 1713 if (!action_attr) 1714 return -EMSGSIZE; 1715 1716 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_ACTION_TYPE, action->type) || 1717 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, action->header_index) || 1718 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 1719 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 1720 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 1721 goto nla_put_failure; 1722 1723 nla_nest_end(skb, action_attr); 1724 return 0; 1725 1726nla_put_failure: 1727 nla_nest_cancel(skb, action_attr); 1728 return -EMSGSIZE; 1729} 1730EXPORT_SYMBOL_GPL(devlink_dpipe_action_put); 1731 1732static int devlink_dpipe_actions_put(struct devlink_dpipe_table *table, 1733 struct sk_buff *skb) 1734{ 1735 struct nlattr *actions_attr; 1736 1737 actions_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLE_ACTIONS); 1738 if (!actions_attr) 1739 return -EMSGSIZE; 1740 1741 if (table->table_ops->actions_dump(table->priv, skb)) 1742 goto nla_put_failure; 1743 1744 nla_nest_end(skb, actions_attr); 1745 return 0; 1746 1747nla_put_failure: 1748 nla_nest_cancel(skb, actions_attr); 1749 return -EMSGSIZE; 1750} 1751 1752static int devlink_dpipe_table_put(struct sk_buff *skb, 1753 struct devlink_dpipe_table *table) 1754{ 1755 struct nlattr *table_attr; 1756 u64 table_size; 1757 1758 table_size = table->table_ops->size_get(table->priv); 1759 table_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLE); 1760 if (!table_attr) 1761 return -EMSGSIZE; 1762 1763 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) || 1764 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table_size, 1765 DEVLINK_ATTR_PAD)) 1766 goto nla_put_failure; 1767 if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED, 1768 table->counters_enabled)) 1769 goto nla_put_failure; 1770 1771 if (table->resource_valid) { 1772 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID, 1773 table->resource_id, DEVLINK_ATTR_PAD) || 1774 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS, 1775 table->resource_units, DEVLINK_ATTR_PAD)) 1776 goto nla_put_failure; 1777 } 1778 if (devlink_dpipe_matches_put(table, skb)) 1779 goto nla_put_failure; 1780 1781 if (devlink_dpipe_actions_put(table, skb)) 1782 goto nla_put_failure; 1783 1784 nla_nest_end(skb, table_attr); 1785 return 0; 1786 1787nla_put_failure: 1788 nla_nest_cancel(skb, table_attr); 1789 return -EMSGSIZE; 1790} 1791 1792static int devlink_dpipe_send_and_alloc_skb(struct sk_buff **pskb, 1793 struct genl_info *info) 1794{ 1795 int err; 1796 1797 if (*pskb) { 1798 err = genlmsg_reply(*pskb, info); 1799 if (err) 1800 return err; 1801 } 1802 *pskb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 1803 if (!*pskb) 1804 return -ENOMEM; 1805 return 0; 1806} 1807 1808static int devlink_dpipe_tables_fill(struct genl_info *info, 1809 enum devlink_command cmd, int flags, 1810 struct list_head *dpipe_tables, 1811 const char *table_name) 1812{ 1813 struct devlink *devlink = info->user_ptr[0]; 1814 struct devlink_dpipe_table *table; 1815 struct nlattr *tables_attr; 1816 struct sk_buff *skb = NULL; 1817 struct nlmsghdr *nlh; 1818 bool incomplete; 1819 void *hdr; 1820 int i; 1821 int err; 1822 1823 table = list_first_entry(dpipe_tables, 1824 struct devlink_dpipe_table, list); 1825start_again: 1826 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 1827 if (err) 1828 return err; 1829 1830 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 1831 &devlink_nl_family, NLM_F_MULTI, cmd); 1832 if (!hdr) { 1833 nlmsg_free(skb); 1834 return -EMSGSIZE; 1835 } 1836 1837 if (devlink_nl_put_handle(skb, devlink)) 1838 goto nla_put_failure; 1839 tables_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLES); 1840 if (!tables_attr) 1841 goto nla_put_failure; 1842 1843 i = 0; 1844 incomplete = false; 1845 list_for_each_entry_from(table, dpipe_tables, list) { 1846 if (!table_name) { 1847 err = devlink_dpipe_table_put(skb, table); 1848 if (err) { 1849 if (!i) 1850 goto err_table_put; 1851 incomplete = true; 1852 break; 1853 } 1854 } else { 1855 if (!strcmp(table->name, table_name)) { 1856 err = devlink_dpipe_table_put(skb, table); 1857 if (err) 1858 break; 1859 } 1860 } 1861 i++; 1862 } 1863 1864 nla_nest_end(skb, tables_attr); 1865 genlmsg_end(skb, hdr); 1866 if (incomplete) 1867 goto start_again; 1868 1869send_done: 1870 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 1871 NLMSG_DONE, 0, flags | NLM_F_MULTI); 1872 if (!nlh) { 1873 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 1874 if (err) 1875 return err; 1876 goto send_done; 1877 } 1878 1879 return genlmsg_reply(skb, info); 1880 1881nla_put_failure: 1882 err = -EMSGSIZE; 1883err_table_put: 1884 nlmsg_free(skb); 1885 return err; 1886} 1887 1888static int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb, 1889 struct genl_info *info) 1890{ 1891 struct devlink *devlink = info->user_ptr[0]; 1892 const char *table_name = NULL; 1893 1894 if (info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]) 1895 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 1896 1897 return devlink_dpipe_tables_fill(info, DEVLINK_CMD_DPIPE_TABLE_GET, 0, 1898 &devlink->dpipe_table_list, 1899 table_name); 1900} 1901 1902static int devlink_dpipe_value_put(struct sk_buff *skb, 1903 struct devlink_dpipe_value *value) 1904{ 1905 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE, 1906 value->value_size, value->value)) 1907 return -EMSGSIZE; 1908 if (value->mask) 1909 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE_MASK, 1910 value->value_size, value->mask)) 1911 return -EMSGSIZE; 1912 if (value->mapping_valid) 1913 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_VALUE_MAPPING, 1914 value->mapping_value)) 1915 return -EMSGSIZE; 1916 return 0; 1917} 1918 1919static int devlink_dpipe_action_value_put(struct sk_buff *skb, 1920 struct devlink_dpipe_value *value) 1921{ 1922 if (!value->action) 1923 return -EINVAL; 1924 if (devlink_dpipe_action_put(skb, value->action)) 1925 return -EMSGSIZE; 1926 if (devlink_dpipe_value_put(skb, value)) 1927 return -EMSGSIZE; 1928 return 0; 1929} 1930 1931static int devlink_dpipe_action_values_put(struct sk_buff *skb, 1932 struct devlink_dpipe_value *values, 1933 unsigned int values_count) 1934{ 1935 struct nlattr *action_attr; 1936 int i; 1937 int err; 1938 1939 for (i = 0; i < values_count; i++) { 1940 action_attr = nla_nest_start(skb, 1941 DEVLINK_ATTR_DPIPE_ACTION_VALUE); 1942 if (!action_attr) 1943 return -EMSGSIZE; 1944 err = devlink_dpipe_action_value_put(skb, &values[i]); 1945 if (err) 1946 goto err_action_value_put; 1947 nla_nest_end(skb, action_attr); 1948 } 1949 return 0; 1950 1951err_action_value_put: 1952 nla_nest_cancel(skb, action_attr); 1953 return err; 1954} 1955 1956static int devlink_dpipe_match_value_put(struct sk_buff *skb, 1957 struct devlink_dpipe_value *value) 1958{ 1959 if (!value->match) 1960 return -EINVAL; 1961 if (devlink_dpipe_match_put(skb, value->match)) 1962 return -EMSGSIZE; 1963 if (devlink_dpipe_value_put(skb, value)) 1964 return -EMSGSIZE; 1965 return 0; 1966} 1967 1968static int devlink_dpipe_match_values_put(struct sk_buff *skb, 1969 struct devlink_dpipe_value *values, 1970 unsigned int values_count) 1971{ 1972 struct nlattr *match_attr; 1973 int i; 1974 int err; 1975 1976 for (i = 0; i < values_count; i++) { 1977 match_attr = nla_nest_start(skb, 1978 DEVLINK_ATTR_DPIPE_MATCH_VALUE); 1979 if (!match_attr) 1980 return -EMSGSIZE; 1981 err = devlink_dpipe_match_value_put(skb, &values[i]); 1982 if (err) 1983 goto err_match_value_put; 1984 nla_nest_end(skb, match_attr); 1985 } 1986 return 0; 1987 1988err_match_value_put: 1989 nla_nest_cancel(skb, match_attr); 1990 return err; 1991} 1992 1993static int devlink_dpipe_entry_put(struct sk_buff *skb, 1994 struct devlink_dpipe_entry *entry) 1995{ 1996 struct nlattr *entry_attr, *matches_attr, *actions_attr; 1997 int err; 1998 1999 entry_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_ENTRY); 2000 if (!entry_attr) 2001 return -EMSGSIZE; 2002 2003 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_INDEX, entry->index, 2004 DEVLINK_ATTR_PAD)) 2005 goto nla_put_failure; 2006 if (entry->counter_valid) 2007 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_COUNTER, 2008 entry->counter, DEVLINK_ATTR_PAD)) 2009 goto nla_put_failure; 2010 2011 matches_attr = nla_nest_start(skb, 2012 DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES); 2013 if (!matches_attr) 2014 goto nla_put_failure; 2015 2016 err = devlink_dpipe_match_values_put(skb, entry->match_values, 2017 entry->match_values_count); 2018 if (err) { 2019 nla_nest_cancel(skb, matches_attr); 2020 goto err_match_values_put; 2021 } 2022 nla_nest_end(skb, matches_attr); 2023 2024 actions_attr = nla_nest_start(skb, 2025 DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES); 2026 if (!actions_attr) 2027 goto nla_put_failure; 2028 2029 err = devlink_dpipe_action_values_put(skb, entry->action_values, 2030 entry->action_values_count); 2031 if (err) { 2032 nla_nest_cancel(skb, actions_attr); 2033 goto err_action_values_put; 2034 } 2035 nla_nest_end(skb, actions_attr); 2036 2037 nla_nest_end(skb, entry_attr); 2038 return 0; 2039 2040nla_put_failure: 2041 err = -EMSGSIZE; 2042err_match_values_put: 2043err_action_values_put: 2044 nla_nest_cancel(skb, entry_attr); 2045 return err; 2046} 2047 2048static struct devlink_dpipe_table * 2049devlink_dpipe_table_find(struct list_head *dpipe_tables, 2050 const char *table_name) 2051{ 2052 struct devlink_dpipe_table *table; 2053 2054 list_for_each_entry_rcu(table, dpipe_tables, list) { 2055 if (!strcmp(table->name, table_name)) 2056 return table; 2057 } 2058 return NULL; 2059} 2060 2061int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx) 2062{ 2063 struct devlink *devlink; 2064 int err; 2065 2066 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx->skb, 2067 dump_ctx->info); 2068 if (err) 2069 return err; 2070 2071 dump_ctx->hdr = genlmsg_put(dump_ctx->skb, 2072 dump_ctx->info->snd_portid, 2073 dump_ctx->info->snd_seq, 2074 &devlink_nl_family, NLM_F_MULTI, 2075 dump_ctx->cmd); 2076 if (!dump_ctx->hdr) 2077 goto nla_put_failure; 2078 2079 devlink = dump_ctx->info->user_ptr[0]; 2080 if (devlink_nl_put_handle(dump_ctx->skb, devlink)) 2081 goto nla_put_failure; 2082 dump_ctx->nest = nla_nest_start(dump_ctx->skb, 2083 DEVLINK_ATTR_DPIPE_ENTRIES); 2084 if (!dump_ctx->nest) 2085 goto nla_put_failure; 2086 return 0; 2087 2088nla_put_failure: 2089 nlmsg_free(dump_ctx->skb); 2090 return -EMSGSIZE; 2091} 2092EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_prepare); 2093 2094int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx, 2095 struct devlink_dpipe_entry *entry) 2096{ 2097 return devlink_dpipe_entry_put(dump_ctx->skb, entry); 2098} 2099EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_append); 2100 2101int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx) 2102{ 2103 nla_nest_end(dump_ctx->skb, dump_ctx->nest); 2104 genlmsg_end(dump_ctx->skb, dump_ctx->hdr); 2105 return 0; 2106} 2107EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close); 2108 2109void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry) 2110 2111{ 2112 unsigned int value_count, value_index; 2113 struct devlink_dpipe_value *value; 2114 2115 value = entry->action_values; 2116 value_count = entry->action_values_count; 2117 for (value_index = 0; value_index < value_count; value_index++) { 2118 kfree(value[value_index].value); 2119 kfree(value[value_index].mask); 2120 } 2121 2122 value = entry->match_values; 2123 value_count = entry->match_values_count; 2124 for (value_index = 0; value_index < value_count; value_index++) { 2125 kfree(value[value_index].value); 2126 kfree(value[value_index].mask); 2127 } 2128} 2129EXPORT_SYMBOL(devlink_dpipe_entry_clear); 2130 2131static int devlink_dpipe_entries_fill(struct genl_info *info, 2132 enum devlink_command cmd, int flags, 2133 struct devlink_dpipe_table *table) 2134{ 2135 struct devlink_dpipe_dump_ctx dump_ctx; 2136 struct nlmsghdr *nlh; 2137 int err; 2138 2139 dump_ctx.skb = NULL; 2140 dump_ctx.cmd = cmd; 2141 dump_ctx.info = info; 2142 2143 err = table->table_ops->entries_dump(table->priv, 2144 table->counters_enabled, 2145 &dump_ctx); 2146 if (err) 2147 return err; 2148 2149send_done: 2150 nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq, 2151 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2152 if (!nlh) { 2153 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info); 2154 if (err) 2155 return err; 2156 goto send_done; 2157 } 2158 return genlmsg_reply(dump_ctx.skb, info); 2159} 2160 2161static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb, 2162 struct genl_info *info) 2163{ 2164 struct devlink *devlink = info->user_ptr[0]; 2165 struct devlink_dpipe_table *table; 2166 const char *table_name; 2167 2168 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]) 2169 return -EINVAL; 2170 2171 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 2172 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 2173 table_name); 2174 if (!table) 2175 return -EINVAL; 2176 2177 if (!table->table_ops->entries_dump) 2178 return -EINVAL; 2179 2180 return devlink_dpipe_entries_fill(info, DEVLINK_CMD_DPIPE_ENTRIES_GET, 2181 0, table); 2182} 2183 2184static int devlink_dpipe_fields_put(struct sk_buff *skb, 2185 const struct devlink_dpipe_header *header) 2186{ 2187 struct devlink_dpipe_field *field; 2188 struct nlattr *field_attr; 2189 int i; 2190 2191 for (i = 0; i < header->fields_count; i++) { 2192 field = &header->fields[i]; 2193 field_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_FIELD); 2194 if (!field_attr) 2195 return -EMSGSIZE; 2196 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_FIELD_NAME, field->name) || 2197 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 2198 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, field->bitwidth) || 2199 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, field->mapping_type)) 2200 goto nla_put_failure; 2201 nla_nest_end(skb, field_attr); 2202 } 2203 return 0; 2204 2205nla_put_failure: 2206 nla_nest_cancel(skb, field_attr); 2207 return -EMSGSIZE; 2208} 2209 2210static int devlink_dpipe_header_put(struct sk_buff *skb, 2211 struct devlink_dpipe_header *header) 2212{ 2213 struct nlattr *fields_attr, *header_attr; 2214 int err; 2215 2216 header_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADER); 2217 if (!header_attr) 2218 return -EMSGSIZE; 2219 2220 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_HEADER_NAME, header->name) || 2221 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 2222 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 2223 goto nla_put_failure; 2224 2225 fields_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADER_FIELDS); 2226 if (!fields_attr) 2227 goto nla_put_failure; 2228 2229 err = devlink_dpipe_fields_put(skb, header); 2230 if (err) { 2231 nla_nest_cancel(skb, fields_attr); 2232 goto nla_put_failure; 2233 } 2234 nla_nest_end(skb, fields_attr); 2235 nla_nest_end(skb, header_attr); 2236 return 0; 2237 2238nla_put_failure: 2239 err = -EMSGSIZE; 2240 nla_nest_cancel(skb, header_attr); 2241 return err; 2242} 2243 2244static int devlink_dpipe_headers_fill(struct genl_info *info, 2245 enum devlink_command cmd, int flags, 2246 struct devlink_dpipe_headers * 2247 dpipe_headers) 2248{ 2249 struct devlink *devlink = info->user_ptr[0]; 2250 struct nlattr *headers_attr; 2251 struct sk_buff *skb = NULL; 2252 struct nlmsghdr *nlh; 2253 void *hdr; 2254 int i, j; 2255 int err; 2256 2257 i = 0; 2258start_again: 2259 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2260 if (err) 2261 return err; 2262 2263 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 2264 &devlink_nl_family, NLM_F_MULTI, cmd); 2265 if (!hdr) { 2266 nlmsg_free(skb); 2267 return -EMSGSIZE; 2268 } 2269 2270 if (devlink_nl_put_handle(skb, devlink)) 2271 goto nla_put_failure; 2272 headers_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADERS); 2273 if (!headers_attr) 2274 goto nla_put_failure; 2275 2276 j = 0; 2277 for (; i < dpipe_headers->headers_count; i++) { 2278 err = devlink_dpipe_header_put(skb, dpipe_headers->headers[i]); 2279 if (err) { 2280 if (!j) 2281 goto err_table_put; 2282 break; 2283 } 2284 j++; 2285 } 2286 nla_nest_end(skb, headers_attr); 2287 genlmsg_end(skb, hdr); 2288 if (i != dpipe_headers->headers_count) 2289 goto start_again; 2290 2291send_done: 2292 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 2293 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2294 if (!nlh) { 2295 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2296 if (err) 2297 return err; 2298 goto send_done; 2299 } 2300 return genlmsg_reply(skb, info); 2301 2302nla_put_failure: 2303 err = -EMSGSIZE; 2304err_table_put: 2305 nlmsg_free(skb); 2306 return err; 2307} 2308 2309static int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb, 2310 struct genl_info *info) 2311{ 2312 struct devlink *devlink = info->user_ptr[0]; 2313 2314 if (!devlink->dpipe_headers) 2315 return -EOPNOTSUPP; 2316 return devlink_dpipe_headers_fill(info, DEVLINK_CMD_DPIPE_HEADERS_GET, 2317 0, devlink->dpipe_headers); 2318} 2319 2320static int devlink_dpipe_table_counters_set(struct devlink *devlink, 2321 const char *table_name, 2322 bool enable) 2323{ 2324 struct devlink_dpipe_table *table; 2325 2326 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 2327 table_name); 2328 if (!table) 2329 return -EINVAL; 2330 2331 if (table->counter_control_extern) 2332 return -EOPNOTSUPP; 2333 2334 if (!(table->counters_enabled ^ enable)) 2335 return 0; 2336 2337 table->counters_enabled = enable; 2338 if (table->table_ops->counters_set_update) 2339 table->table_ops->counters_set_update(table->priv, enable); 2340 return 0; 2341} 2342 2343static int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb, 2344 struct genl_info *info) 2345{ 2346 struct devlink *devlink = info->user_ptr[0]; 2347 const char *table_name; 2348 bool counters_enable; 2349 2350 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME] || 2351 !info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]) 2352 return -EINVAL; 2353 2354 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 2355 counters_enable = !!nla_get_u8(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]); 2356 2357 return devlink_dpipe_table_counters_set(devlink, table_name, 2358 counters_enable); 2359} 2360 2361static struct devlink_resource * 2362devlink_resource_find(struct devlink *devlink, 2363 struct devlink_resource *resource, u64 resource_id) 2364{ 2365 struct list_head *resource_list; 2366 2367 if (resource) 2368 resource_list = &resource->resource_list; 2369 else 2370 resource_list = &devlink->resource_list; 2371 2372 list_for_each_entry(resource, resource_list, list) { 2373 struct devlink_resource *child_resource; 2374 2375 if (resource->id == resource_id) 2376 return resource; 2377 2378 child_resource = devlink_resource_find(devlink, resource, 2379 resource_id); 2380 if (child_resource) 2381 return child_resource; 2382 } 2383 return NULL; 2384} 2385 2386static void 2387devlink_resource_validate_children(struct devlink_resource *resource) 2388{ 2389 struct devlink_resource *child_resource; 2390 bool size_valid = true; 2391 u64 parts_size = 0; 2392 2393 if (list_empty(&resource->resource_list)) 2394 goto out; 2395 2396 list_for_each_entry(child_resource, &resource->resource_list, list) 2397 parts_size += child_resource->size_new; 2398 2399 if (parts_size > resource->size_new) 2400 size_valid = false; 2401out: 2402 resource->size_valid = size_valid; 2403} 2404 2405static int 2406devlink_resource_validate_size(struct devlink_resource *resource, u64 size, 2407 struct netlink_ext_ack *extack) 2408{ 2409 u64 reminder; 2410 int err = 0; 2411 2412 if (size > resource->size_params.size_max) { 2413 NL_SET_ERR_MSG_MOD(extack, "Size larger than maximum"); 2414 err = -EINVAL; 2415 } 2416 2417 if (size < resource->size_params.size_min) { 2418 NL_SET_ERR_MSG_MOD(extack, "Size smaller than minimum"); 2419 err = -EINVAL; 2420 } 2421 2422 div64_u64_rem(size, resource->size_params.size_granularity, &reminder); 2423 if (reminder) { 2424 NL_SET_ERR_MSG_MOD(extack, "Wrong granularity"); 2425 err = -EINVAL; 2426 } 2427 2428 return err; 2429} 2430 2431static int devlink_nl_cmd_resource_set(struct sk_buff *skb, 2432 struct genl_info *info) 2433{ 2434 struct devlink *devlink = info->user_ptr[0]; 2435 struct devlink_resource *resource; 2436 u64 resource_id; 2437 u64 size; 2438 int err; 2439 2440 if (!info->attrs[DEVLINK_ATTR_RESOURCE_ID] || 2441 !info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]) 2442 return -EINVAL; 2443 resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]); 2444 2445 resource = devlink_resource_find(devlink, NULL, resource_id); 2446 if (!resource) 2447 return -EINVAL; 2448 2449 size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]); 2450 err = devlink_resource_validate_size(resource, size, info->extack); 2451 if (err) 2452 return err; 2453 2454 resource->size_new = size; 2455 devlink_resource_validate_children(resource); 2456 if (resource->parent) 2457 devlink_resource_validate_children(resource->parent); 2458 return 0; 2459} 2460 2461static int 2462devlink_resource_size_params_put(struct devlink_resource *resource, 2463 struct sk_buff *skb) 2464{ 2465 struct devlink_resource_size_params *size_params; 2466 2467 size_params = &resource->size_params; 2468 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN, 2469 size_params->size_granularity, DEVLINK_ATTR_PAD) || 2470 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX, 2471 size_params->size_max, DEVLINK_ATTR_PAD) || 2472 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN, 2473 size_params->size_min, DEVLINK_ATTR_PAD) || 2474 nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit)) 2475 return -EMSGSIZE; 2476 return 0; 2477} 2478 2479static int devlink_resource_occ_put(struct devlink_resource *resource, 2480 struct sk_buff *skb) 2481{ 2482 if (!resource->occ_get) 2483 return 0; 2484 return nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC, 2485 resource->occ_get(resource->occ_get_priv), 2486 DEVLINK_ATTR_PAD); 2487} 2488 2489static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb, 2490 struct devlink_resource *resource) 2491{ 2492 struct devlink_resource *child_resource; 2493 struct nlattr *child_resource_attr; 2494 struct nlattr *resource_attr; 2495 2496 resource_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE); 2497 if (!resource_attr) 2498 return -EMSGSIZE; 2499 2500 if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) || 2501 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size, 2502 DEVLINK_ATTR_PAD) || 2503 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id, 2504 DEVLINK_ATTR_PAD)) 2505 goto nla_put_failure; 2506 if (resource->size != resource->size_new) 2507 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW, 2508 resource->size_new, DEVLINK_ATTR_PAD); 2509 if (devlink_resource_occ_put(resource, skb)) 2510 goto nla_put_failure; 2511 if (devlink_resource_size_params_put(resource, skb)) 2512 goto nla_put_failure; 2513 if (list_empty(&resource->resource_list)) 2514 goto out; 2515 2516 if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID, 2517 resource->size_valid)) 2518 goto nla_put_failure; 2519 2520 child_resource_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE_LIST); 2521 if (!child_resource_attr) 2522 goto nla_put_failure; 2523 2524 list_for_each_entry(child_resource, &resource->resource_list, list) { 2525 if (devlink_resource_put(devlink, skb, child_resource)) 2526 goto resource_put_failure; 2527 } 2528 2529 nla_nest_end(skb, child_resource_attr); 2530out: 2531 nla_nest_end(skb, resource_attr); 2532 return 0; 2533 2534resource_put_failure: 2535 nla_nest_cancel(skb, child_resource_attr); 2536nla_put_failure: 2537 nla_nest_cancel(skb, resource_attr); 2538 return -EMSGSIZE; 2539} 2540 2541static int devlink_resource_fill(struct genl_info *info, 2542 enum devlink_command cmd, int flags) 2543{ 2544 struct devlink *devlink = info->user_ptr[0]; 2545 struct devlink_resource *resource; 2546 struct nlattr *resources_attr; 2547 struct sk_buff *skb = NULL; 2548 struct nlmsghdr *nlh; 2549 bool incomplete; 2550 void *hdr; 2551 int i; 2552 int err; 2553 2554 resource = list_first_entry(&devlink->resource_list, 2555 struct devlink_resource, list); 2556start_again: 2557 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2558 if (err) 2559 return err; 2560 2561 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 2562 &devlink_nl_family, NLM_F_MULTI, cmd); 2563 if (!hdr) { 2564 nlmsg_free(skb); 2565 return -EMSGSIZE; 2566 } 2567 2568 if (devlink_nl_put_handle(skb, devlink)) 2569 goto nla_put_failure; 2570 2571 resources_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE_LIST); 2572 if (!resources_attr) 2573 goto nla_put_failure; 2574 2575 incomplete = false; 2576 i = 0; 2577 list_for_each_entry_from(resource, &devlink->resource_list, list) { 2578 err = devlink_resource_put(devlink, skb, resource); 2579 if (err) { 2580 if (!i) 2581 goto err_resource_put; 2582 incomplete = true; 2583 break; 2584 } 2585 i++; 2586 } 2587 nla_nest_end(skb, resources_attr); 2588 genlmsg_end(skb, hdr); 2589 if (incomplete) 2590 goto start_again; 2591send_done: 2592 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 2593 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2594 if (!nlh) { 2595 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2596 if (err) 2597 return err; 2598 goto send_done; 2599 } 2600 return genlmsg_reply(skb, info); 2601 2602nla_put_failure: 2603 err = -EMSGSIZE; 2604err_resource_put: 2605 nlmsg_free(skb); 2606 return err; 2607} 2608 2609static int devlink_nl_cmd_resource_dump(struct sk_buff *skb, 2610 struct genl_info *info) 2611{ 2612 struct devlink *devlink = info->user_ptr[0]; 2613 2614 if (list_empty(&devlink->resource_list)) 2615 return -EOPNOTSUPP; 2616 2617 return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0); 2618} 2619 2620static int 2621devlink_resources_validate(struct devlink *devlink, 2622 struct devlink_resource *resource, 2623 struct genl_info *info) 2624{ 2625 struct list_head *resource_list; 2626 int err = 0; 2627 2628 if (resource) 2629 resource_list = &resource->resource_list; 2630 else 2631 resource_list = &devlink->resource_list; 2632 2633 list_for_each_entry(resource, resource_list, list) { 2634 if (!resource->size_valid) 2635 return -EINVAL; 2636 err = devlink_resources_validate(devlink, resource, info); 2637 if (err) 2638 return err; 2639 } 2640 return err; 2641} 2642 2643static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info) 2644{ 2645 struct devlink *devlink = info->user_ptr[0]; 2646 int err; 2647 2648 if (!devlink->ops->reload) 2649 return -EOPNOTSUPP; 2650 2651 err = devlink_resources_validate(devlink, NULL, info); 2652 if (err) { 2653 NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed"); 2654 return err; 2655 } 2656 return devlink->ops->reload(devlink, info->extack); 2657} 2658 2659static const struct devlink_param devlink_param_generic[] = { 2660 { 2661 .id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET, 2662 .name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME, 2663 .type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE, 2664 }, 2665 { 2666 .id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS, 2667 .name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME, 2668 .type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE, 2669 }, 2670 { 2671 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV, 2672 .name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME, 2673 .type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE, 2674 }, 2675 { 2676 .id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT, 2677 .name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME, 2678 .type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE, 2679 }, 2680 { 2681 .id = DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI, 2682 .name = DEVLINK_PARAM_GENERIC_IGNORE_ARI_NAME, 2683 .type = DEVLINK_PARAM_GENERIC_IGNORE_ARI_TYPE, 2684 }, 2685 { 2686 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX, 2687 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_NAME, 2688 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_TYPE, 2689 }, 2690 { 2691 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN, 2692 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_NAME, 2693 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_TYPE, 2694 }, 2695 { 2696 .id = DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY, 2697 .name = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME, 2698 .type = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE, 2699 }, 2700}; 2701 2702static int devlink_param_generic_verify(const struct devlink_param *param) 2703{ 2704 /* verify it match generic parameter by id and name */ 2705 if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX) 2706 return -EINVAL; 2707 if (strcmp(param->name, devlink_param_generic[param->id].name)) 2708 return -ENOENT; 2709 2710 WARN_ON(param->type != devlink_param_generic[param->id].type); 2711 2712 return 0; 2713} 2714 2715static int devlink_param_driver_verify(const struct devlink_param *param) 2716{ 2717 int i; 2718 2719 if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX) 2720 return -EINVAL; 2721 /* verify no such name in generic params */ 2722 for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++) 2723 if (!strcmp(param->name, devlink_param_generic[i].name)) 2724 return -EEXIST; 2725 2726 return 0; 2727} 2728 2729static struct devlink_param_item * 2730devlink_param_find_by_name(struct list_head *param_list, 2731 const char *param_name) 2732{ 2733 struct devlink_param_item *param_item; 2734 2735 list_for_each_entry(param_item, param_list, list) 2736 if (!strcmp(param_item->param->name, param_name)) 2737 return param_item; 2738 return NULL; 2739} 2740 2741static struct devlink_param_item * 2742devlink_param_find_by_id(struct list_head *param_list, u32 param_id) 2743{ 2744 struct devlink_param_item *param_item; 2745 2746 list_for_each_entry(param_item, param_list, list) 2747 if (param_item->param->id == param_id) 2748 return param_item; 2749 return NULL; 2750} 2751 2752static bool 2753devlink_param_cmode_is_supported(const struct devlink_param *param, 2754 enum devlink_param_cmode cmode) 2755{ 2756 return test_bit(cmode, &param->supported_cmodes); 2757} 2758 2759static int devlink_param_get(struct devlink *devlink, 2760 const struct devlink_param *param, 2761 struct devlink_param_gset_ctx *ctx) 2762{ 2763 if (!param->get) 2764 return -EOPNOTSUPP; 2765 return param->get(devlink, param->id, ctx); 2766} 2767 2768static int devlink_param_set(struct devlink *devlink, 2769 const struct devlink_param *param, 2770 struct devlink_param_gset_ctx *ctx) 2771{ 2772 if (!param->set) 2773 return -EOPNOTSUPP; 2774 return param->set(devlink, param->id, ctx); 2775} 2776 2777static int 2778devlink_param_type_to_nla_type(enum devlink_param_type param_type) 2779{ 2780 switch (param_type) { 2781 case DEVLINK_PARAM_TYPE_U8: 2782 return NLA_U8; 2783 case DEVLINK_PARAM_TYPE_U16: 2784 return NLA_U16; 2785 case DEVLINK_PARAM_TYPE_U32: 2786 return NLA_U32; 2787 case DEVLINK_PARAM_TYPE_STRING: 2788 return NLA_STRING; 2789 case DEVLINK_PARAM_TYPE_BOOL: 2790 return NLA_FLAG; 2791 default: 2792 return -EINVAL; 2793 } 2794} 2795 2796static int 2797devlink_nl_param_value_fill_one(struct sk_buff *msg, 2798 enum devlink_param_type type, 2799 enum devlink_param_cmode cmode, 2800 union devlink_param_value val) 2801{ 2802 struct nlattr *param_value_attr; 2803 2804 param_value_attr = nla_nest_start(msg, DEVLINK_ATTR_PARAM_VALUE); 2805 if (!param_value_attr) 2806 goto nla_put_failure; 2807 2808 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode)) 2809 goto value_nest_cancel; 2810 2811 switch (type) { 2812 case DEVLINK_PARAM_TYPE_U8: 2813 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8)) 2814 goto value_nest_cancel; 2815 break; 2816 case DEVLINK_PARAM_TYPE_U16: 2817 if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16)) 2818 goto value_nest_cancel; 2819 break; 2820 case DEVLINK_PARAM_TYPE_U32: 2821 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32)) 2822 goto value_nest_cancel; 2823 break; 2824 case DEVLINK_PARAM_TYPE_STRING: 2825 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, 2826 val.vstr)) 2827 goto value_nest_cancel; 2828 break; 2829 case DEVLINK_PARAM_TYPE_BOOL: 2830 if (val.vbool && 2831 nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA)) 2832 goto value_nest_cancel; 2833 break; 2834 } 2835 2836 nla_nest_end(msg, param_value_attr); 2837 return 0; 2838 2839value_nest_cancel: 2840 nla_nest_cancel(msg, param_value_attr); 2841nla_put_failure: 2842 return -EMSGSIZE; 2843} 2844 2845static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, 2846 struct devlink_param_item *param_item, 2847 enum devlink_command cmd, 2848 u32 portid, u32 seq, int flags) 2849{ 2850 union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1]; 2851 const struct devlink_param *param = param_item->param; 2852 struct devlink_param_gset_ctx ctx; 2853 struct nlattr *param_values_list; 2854 struct nlattr *param_attr; 2855 int nla_type; 2856 void *hdr; 2857 int err; 2858 int i; 2859 2860 /* Get value from driver part to driverinit configuration mode */ 2861 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 2862 if (!devlink_param_cmode_is_supported(param, i)) 2863 continue; 2864 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) { 2865 if (!param_item->driverinit_value_valid) 2866 return -EOPNOTSUPP; 2867 param_value[i] = param_item->driverinit_value; 2868 } else { 2869 ctx.cmode = i; 2870 err = devlink_param_get(devlink, param, &ctx); 2871 if (err) 2872 return err; 2873 param_value[i] = ctx.val; 2874 } 2875 } 2876 2877 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 2878 if (!hdr) 2879 return -EMSGSIZE; 2880 2881 if (devlink_nl_put_handle(msg, devlink)) 2882 goto genlmsg_cancel; 2883 param_attr = nla_nest_start(msg, DEVLINK_ATTR_PARAM); 2884 if (!param_attr) 2885 goto genlmsg_cancel; 2886 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name)) 2887 goto param_nest_cancel; 2888 if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC)) 2889 goto param_nest_cancel; 2890 2891 nla_type = devlink_param_type_to_nla_type(param->type); 2892 if (nla_type < 0) 2893 goto param_nest_cancel; 2894 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type)) 2895 goto param_nest_cancel; 2896 2897 param_values_list = nla_nest_start(msg, DEVLINK_ATTR_PARAM_VALUES_LIST); 2898 if (!param_values_list) 2899 goto param_nest_cancel; 2900 2901 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 2902 if (!devlink_param_cmode_is_supported(param, i)) 2903 continue; 2904 err = devlink_nl_param_value_fill_one(msg, param->type, 2905 i, param_value[i]); 2906 if (err) 2907 goto values_list_nest_cancel; 2908 } 2909 2910 nla_nest_end(msg, param_values_list); 2911 nla_nest_end(msg, param_attr); 2912 genlmsg_end(msg, hdr); 2913 return 0; 2914 2915values_list_nest_cancel: 2916 nla_nest_end(msg, param_values_list); 2917param_nest_cancel: 2918 nla_nest_cancel(msg, param_attr); 2919genlmsg_cancel: 2920 genlmsg_cancel(msg, hdr); 2921 return -EMSGSIZE; 2922} 2923 2924static void devlink_param_notify(struct devlink *devlink, 2925 struct devlink_param_item *param_item, 2926 enum devlink_command cmd) 2927{ 2928 struct sk_buff *msg; 2929 int err; 2930 2931 WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL); 2932 2933 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 2934 if (!msg) 2935 return; 2936 err = devlink_nl_param_fill(msg, devlink, param_item, cmd, 0, 0, 0); 2937 if (err) { 2938 nlmsg_free(msg); 2939 return; 2940 } 2941 2942 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 2943 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 2944} 2945 2946static int devlink_nl_cmd_param_get_dumpit(struct sk_buff *msg, 2947 struct netlink_callback *cb) 2948{ 2949 struct devlink_param_item *param_item; 2950 struct devlink *devlink; 2951 int start = cb->args[0]; 2952 int idx = 0; 2953 int err; 2954 2955 mutex_lock(&devlink_mutex); 2956 list_for_each_entry(devlink, &devlink_list, list) { 2957 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 2958 continue; 2959 mutex_lock(&devlink->lock); 2960 list_for_each_entry(param_item, &devlink->param_list, list) { 2961 if (idx < start) { 2962 idx++; 2963 continue; 2964 } 2965 err = devlink_nl_param_fill(msg, devlink, param_item, 2966 DEVLINK_CMD_PARAM_GET, 2967 NETLINK_CB(cb->skb).portid, 2968 cb->nlh->nlmsg_seq, 2969 NLM_F_MULTI); 2970 if (err) { 2971 mutex_unlock(&devlink->lock); 2972 goto out; 2973 } 2974 idx++; 2975 } 2976 mutex_unlock(&devlink->lock); 2977 } 2978out: 2979 mutex_unlock(&devlink_mutex); 2980 2981 cb->args[0] = idx; 2982 return msg->len; 2983} 2984 2985static int 2986devlink_param_type_get_from_info(struct genl_info *info, 2987 enum devlink_param_type *param_type) 2988{ 2989 if (!info->attrs[DEVLINK_ATTR_PARAM_TYPE]) 2990 return -EINVAL; 2991 2992 switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) { 2993 case NLA_U8: 2994 *param_type = DEVLINK_PARAM_TYPE_U8; 2995 break; 2996 case NLA_U16: 2997 *param_type = DEVLINK_PARAM_TYPE_U16; 2998 break; 2999 case NLA_U32: 3000 *param_type = DEVLINK_PARAM_TYPE_U32; 3001 break; 3002 case NLA_STRING: 3003 *param_type = DEVLINK_PARAM_TYPE_STRING; 3004 break; 3005 case NLA_FLAG: 3006 *param_type = DEVLINK_PARAM_TYPE_BOOL; 3007 break; 3008 default: 3009 return -EINVAL; 3010 } 3011 3012 return 0; 3013} 3014 3015static int 3016devlink_param_value_get_from_info(const struct devlink_param *param, 3017 struct genl_info *info, 3018 union devlink_param_value *value) 3019{ 3020 int len; 3021 3022 if (param->type != DEVLINK_PARAM_TYPE_BOOL && 3023 !info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) 3024 return -EINVAL; 3025 3026 switch (param->type) { 3027 case DEVLINK_PARAM_TYPE_U8: 3028 value->vu8 = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3029 break; 3030 case DEVLINK_PARAM_TYPE_U16: 3031 value->vu16 = nla_get_u16(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3032 break; 3033 case DEVLINK_PARAM_TYPE_U32: 3034 value->vu32 = nla_get_u32(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3035 break; 3036 case DEVLINK_PARAM_TYPE_STRING: 3037 len = strnlen(nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]), 3038 nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])); 3039 if (len == nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) || 3040 len >= __DEVLINK_PARAM_MAX_STRING_VALUE) 3041 return -EINVAL; 3042 strcpy(value->vstr, 3043 nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])); 3044 break; 3045 case DEVLINK_PARAM_TYPE_BOOL: 3046 value->vbool = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA] ? 3047 true : false; 3048 break; 3049 } 3050 return 0; 3051} 3052 3053static struct devlink_param_item * 3054devlink_param_get_from_info(struct devlink *devlink, 3055 struct genl_info *info) 3056{ 3057 char *param_name; 3058 3059 if (!info->attrs[DEVLINK_ATTR_PARAM_NAME]) 3060 return NULL; 3061 3062 param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]); 3063 return devlink_param_find_by_name(&devlink->param_list, param_name); 3064} 3065 3066static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb, 3067 struct genl_info *info) 3068{ 3069 struct devlink *devlink = info->user_ptr[0]; 3070 struct devlink_param_item *param_item; 3071 struct sk_buff *msg; 3072 int err; 3073 3074 param_item = devlink_param_get_from_info(devlink, info); 3075 if (!param_item) 3076 return -EINVAL; 3077 3078 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3079 if (!msg) 3080 return -ENOMEM; 3081 3082 err = devlink_nl_param_fill(msg, devlink, param_item, 3083 DEVLINK_CMD_PARAM_GET, 3084 info->snd_portid, info->snd_seq, 0); 3085 if (err) { 3086 nlmsg_free(msg); 3087 return err; 3088 } 3089 3090 return genlmsg_reply(msg, info); 3091} 3092 3093static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb, 3094 struct genl_info *info) 3095{ 3096 struct devlink *devlink = info->user_ptr[0]; 3097 enum devlink_param_type param_type; 3098 struct devlink_param_gset_ctx ctx; 3099 enum devlink_param_cmode cmode; 3100 struct devlink_param_item *param_item; 3101 const struct devlink_param *param; 3102 union devlink_param_value value; 3103 int err = 0; 3104 3105 param_item = devlink_param_get_from_info(devlink, info); 3106 if (!param_item) 3107 return -EINVAL; 3108 param = param_item->param; 3109 err = devlink_param_type_get_from_info(info, &param_type); 3110 if (err) 3111 return err; 3112 if (param_type != param->type) 3113 return -EINVAL; 3114 err = devlink_param_value_get_from_info(param, info, &value); 3115 if (err) 3116 return err; 3117 if (param->validate) { 3118 err = param->validate(devlink, param->id, value, info->extack); 3119 if (err) 3120 return err; 3121 } 3122 3123 if (!info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]) 3124 return -EINVAL; 3125 cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]); 3126 if (!devlink_param_cmode_is_supported(param, cmode)) 3127 return -EOPNOTSUPP; 3128 3129 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) { 3130 if (param->type == DEVLINK_PARAM_TYPE_STRING) 3131 strcpy(param_item->driverinit_value.vstr, value.vstr); 3132 else 3133 param_item->driverinit_value = value; 3134 param_item->driverinit_value_valid = true; 3135 } else { 3136 if (!param->set) 3137 return -EOPNOTSUPP; 3138 ctx.val = value; 3139 ctx.cmode = cmode; 3140 err = devlink_param_set(devlink, param, &ctx); 3141 if (err) 3142 return err; 3143 } 3144 3145 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW); 3146 return 0; 3147} 3148 3149static int devlink_param_register_one(struct devlink *devlink, 3150 const struct devlink_param *param) 3151{ 3152 struct devlink_param_item *param_item; 3153 3154 if (devlink_param_find_by_name(&devlink->param_list, 3155 param->name)) 3156 return -EEXIST; 3157 3158 if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT)) 3159 WARN_ON(param->get || param->set); 3160 else 3161 WARN_ON(!param->get || !param->set); 3162 3163 param_item = kzalloc(sizeof(*param_item), GFP_KERNEL); 3164 if (!param_item) 3165 return -ENOMEM; 3166 param_item->param = param; 3167 3168 list_add_tail(&param_item->list, &devlink->param_list); 3169 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW); 3170 return 0; 3171} 3172 3173static void devlink_param_unregister_one(struct devlink *devlink, 3174 const struct devlink_param *param) 3175{ 3176 struct devlink_param_item *param_item; 3177 3178 param_item = devlink_param_find_by_name(&devlink->param_list, 3179 param->name); 3180 WARN_ON(!param_item); 3181 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_DEL); 3182 list_del(&param_item->list); 3183 kfree(param_item); 3184} 3185 3186static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg, 3187 struct devlink *devlink, 3188 struct devlink_snapshot *snapshot) 3189{ 3190 struct nlattr *snap_attr; 3191 int err; 3192 3193 snap_attr = nla_nest_start(msg, DEVLINK_ATTR_REGION_SNAPSHOT); 3194 if (!snap_attr) 3195 return -EINVAL; 3196 3197 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id); 3198 if (err) 3199 goto nla_put_failure; 3200 3201 nla_nest_end(msg, snap_attr); 3202 return 0; 3203 3204nla_put_failure: 3205 nla_nest_cancel(msg, snap_attr); 3206 return err; 3207} 3208 3209static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg, 3210 struct devlink *devlink, 3211 struct devlink_region *region) 3212{ 3213 struct devlink_snapshot *snapshot; 3214 struct nlattr *snapshots_attr; 3215 int err; 3216 3217 snapshots_attr = nla_nest_start(msg, DEVLINK_ATTR_REGION_SNAPSHOTS); 3218 if (!snapshots_attr) 3219 return -EINVAL; 3220 3221 list_for_each_entry(snapshot, &region->snapshot_list, list) { 3222 err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot); 3223 if (err) 3224 goto nla_put_failure; 3225 } 3226 3227 nla_nest_end(msg, snapshots_attr); 3228 return 0; 3229 3230nla_put_failure: 3231 nla_nest_cancel(msg, snapshots_attr); 3232 return err; 3233} 3234 3235static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink, 3236 enum devlink_command cmd, u32 portid, 3237 u32 seq, int flags, 3238 struct devlink_region *region) 3239{ 3240 void *hdr; 3241 int err; 3242 3243 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 3244 if (!hdr) 3245 return -EMSGSIZE; 3246 3247 err = devlink_nl_put_handle(msg, devlink); 3248 if (err) 3249 goto nla_put_failure; 3250 3251 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->name); 3252 if (err) 3253 goto nla_put_failure; 3254 3255 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE, 3256 region->size, 3257 DEVLINK_ATTR_PAD); 3258 if (err) 3259 goto nla_put_failure; 3260 3261 err = devlink_nl_region_snapshots_id_put(msg, devlink, region); 3262 if (err) 3263 goto nla_put_failure; 3264 3265 genlmsg_end(msg, hdr); 3266 return 0; 3267 3268nla_put_failure: 3269 genlmsg_cancel(msg, hdr); 3270 return err; 3271} 3272 3273static void devlink_nl_region_notify(struct devlink_region *region, 3274 struct devlink_snapshot *snapshot, 3275 enum devlink_command cmd) 3276{ 3277 struct devlink *devlink = region->devlink; 3278 struct sk_buff *msg; 3279 void *hdr; 3280 int err; 3281 3282 WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL); 3283 3284 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3285 if (!msg) 3286 return; 3287 3288 hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd); 3289 if (!hdr) 3290 goto out_free_msg; 3291 3292 err = devlink_nl_put_handle(msg, devlink); 3293 if (err) 3294 goto out_cancel_msg; 3295 3296 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, 3297 region->name); 3298 if (err) 3299 goto out_cancel_msg; 3300 3301 if (snapshot) { 3302 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, 3303 snapshot->id); 3304 if (err) 3305 goto out_cancel_msg; 3306 } else { 3307 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE, 3308 region->size, DEVLINK_ATTR_PAD); 3309 if (err) 3310 goto out_cancel_msg; 3311 } 3312 genlmsg_end(msg, hdr); 3313 3314 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 3315 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 3316 3317 return; 3318 3319out_cancel_msg: 3320 genlmsg_cancel(msg, hdr); 3321out_free_msg: 3322 nlmsg_free(msg); 3323} 3324 3325static int devlink_nl_cmd_region_get_doit(struct sk_buff *skb, 3326 struct genl_info *info) 3327{ 3328 struct devlink *devlink = info->user_ptr[0]; 3329 struct devlink_region *region; 3330 const char *region_name; 3331 struct sk_buff *msg; 3332 int err; 3333 3334 if (!info->attrs[DEVLINK_ATTR_REGION_NAME]) 3335 return -EINVAL; 3336 3337 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 3338 region = devlink_region_get_by_name(devlink, region_name); 3339 if (!region) 3340 return -EINVAL; 3341 3342 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3343 if (!msg) 3344 return -ENOMEM; 3345 3346 err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET, 3347 info->snd_portid, info->snd_seq, 0, 3348 region); 3349 if (err) { 3350 nlmsg_free(msg); 3351 return err; 3352 } 3353 3354 return genlmsg_reply(msg, info); 3355} 3356 3357static int devlink_nl_cmd_region_get_dumpit(struct sk_buff *msg, 3358 struct netlink_callback *cb) 3359{ 3360 struct devlink_region *region; 3361 struct devlink *devlink; 3362 int start = cb->args[0]; 3363 int idx = 0; 3364 int err; 3365 3366 mutex_lock(&devlink_mutex); 3367 list_for_each_entry(devlink, &devlink_list, list) { 3368 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 3369 continue; 3370 3371 mutex_lock(&devlink->lock); 3372 list_for_each_entry(region, &devlink->region_list, list) { 3373 if (idx < start) { 3374 idx++; 3375 continue; 3376 } 3377 err = devlink_nl_region_fill(msg, devlink, 3378 DEVLINK_CMD_REGION_GET, 3379 NETLINK_CB(cb->skb).portid, 3380 cb->nlh->nlmsg_seq, 3381 NLM_F_MULTI, region); 3382 if (err) { 3383 mutex_unlock(&devlink->lock); 3384 goto out; 3385 } 3386 idx++; 3387 } 3388 mutex_unlock(&devlink->lock); 3389 } 3390out: 3391 mutex_unlock(&devlink_mutex); 3392 cb->args[0] = idx; 3393 return msg->len; 3394} 3395 3396static int devlink_nl_cmd_region_del(struct sk_buff *skb, 3397 struct genl_info *info) 3398{ 3399 struct devlink *devlink = info->user_ptr[0]; 3400 struct devlink_snapshot *snapshot; 3401 struct devlink_region *region; 3402 const char *region_name; 3403 u32 snapshot_id; 3404 3405 if (!info->attrs[DEVLINK_ATTR_REGION_NAME] || 3406 !info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) 3407 return -EINVAL; 3408 3409 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 3410 snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); 3411 3412 region = devlink_region_get_by_name(devlink, region_name); 3413 if (!region) 3414 return -EINVAL; 3415 3416 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); 3417 if (!snapshot) 3418 return -EINVAL; 3419 3420 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL); 3421 devlink_region_snapshot_del(snapshot); 3422 return 0; 3423} 3424 3425static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg, 3426 struct devlink *devlink, 3427 u8 *chunk, u32 chunk_size, 3428 u64 addr) 3429{ 3430 struct nlattr *chunk_attr; 3431 int err; 3432 3433 chunk_attr = nla_nest_start(msg, DEVLINK_ATTR_REGION_CHUNK); 3434 if (!chunk_attr) 3435 return -EINVAL; 3436 3437 err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk); 3438 if (err) 3439 goto nla_put_failure; 3440 3441 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr, 3442 DEVLINK_ATTR_PAD); 3443 if (err) 3444 goto nla_put_failure; 3445 3446 nla_nest_end(msg, chunk_attr); 3447 return 0; 3448 3449nla_put_failure: 3450 nla_nest_cancel(msg, chunk_attr); 3451 return err; 3452} 3453 3454#define DEVLINK_REGION_READ_CHUNK_SIZE 256 3455 3456static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb, 3457 struct devlink *devlink, 3458 struct devlink_region *region, 3459 struct nlattr **attrs, 3460 u64 start_offset, 3461 u64 end_offset, 3462 bool dump, 3463 u64 *new_offset) 3464{ 3465 struct devlink_snapshot *snapshot; 3466 u64 curr_offset = start_offset; 3467 u32 snapshot_id; 3468 int err = 0; 3469 3470 *new_offset = start_offset; 3471 3472 snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); 3473 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); 3474 if (!snapshot) 3475 return -EINVAL; 3476 3477 if (end_offset > snapshot->data_len || dump) 3478 end_offset = snapshot->data_len; 3479 3480 while (curr_offset < end_offset) { 3481 u32 data_size; 3482 u8 *data; 3483 3484 if (end_offset - curr_offset < DEVLINK_REGION_READ_CHUNK_SIZE) 3485 data_size = end_offset - curr_offset; 3486 else 3487 data_size = DEVLINK_REGION_READ_CHUNK_SIZE; 3488 3489 data = &snapshot->data[curr_offset]; 3490 err = devlink_nl_cmd_region_read_chunk_fill(skb, devlink, 3491 data, data_size, 3492 curr_offset); 3493 if (err) 3494 break; 3495 3496 curr_offset += data_size; 3497 } 3498 *new_offset = curr_offset; 3499 3500 return err; 3501} 3502 3503static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, 3504 struct netlink_callback *cb) 3505{ 3506 u64 ret_offset, start_offset, end_offset = 0; 3507 struct nlattr *attrs[DEVLINK_ATTR_MAX + 1]; 3508 const struct genl_ops *ops = cb->data; 3509 struct devlink_region *region; 3510 struct nlattr *chunks_attr; 3511 const char *region_name; 3512 struct devlink *devlink; 3513 bool dump = true; 3514 void *hdr; 3515 int err; 3516 3517 start_offset = *((u64 *)&cb->args[0]); 3518 3519 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + devlink_nl_family.hdrsize, 3520 attrs, DEVLINK_ATTR_MAX, ops->policy, cb->extack); 3521 if (err) 3522 goto out; 3523 3524 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs); 3525 if (IS_ERR(devlink)) 3526 goto out; 3527 3528 mutex_lock(&devlink_mutex); 3529 mutex_lock(&devlink->lock); 3530 3531 if (!attrs[DEVLINK_ATTR_REGION_NAME] || 3532 !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) 3533 goto out_unlock; 3534 3535 region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]); 3536 region = devlink_region_get_by_name(devlink, region_name); 3537 if (!region) 3538 goto out_unlock; 3539 3540 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 3541 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, 3542 DEVLINK_CMD_REGION_READ); 3543 if (!hdr) 3544 goto out_unlock; 3545 3546 err = devlink_nl_put_handle(skb, devlink); 3547 if (err) 3548 goto nla_put_failure; 3549 3550 err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name); 3551 if (err) 3552 goto nla_put_failure; 3553 3554 chunks_attr = nla_nest_start(skb, DEVLINK_ATTR_REGION_CHUNKS); 3555 if (!chunks_attr) 3556 goto nla_put_failure; 3557 3558 if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] && 3559 attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) { 3560 if (!start_offset) 3561 start_offset = 3562 nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); 3563 3564 end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); 3565 end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]); 3566 dump = false; 3567 } 3568 3569 err = devlink_nl_region_read_snapshot_fill(skb, devlink, 3570 region, attrs, 3571 start_offset, 3572 end_offset, dump, 3573 &ret_offset); 3574 3575 if (err && err != -EMSGSIZE) 3576 goto nla_put_failure; 3577 3578 /* Check if there was any progress done to prevent infinite loop */ 3579 if (ret_offset == start_offset) 3580 goto nla_put_failure; 3581 3582 *((u64 *)&cb->args[0]) = ret_offset; 3583 3584 nla_nest_end(skb, chunks_attr); 3585 genlmsg_end(skb, hdr); 3586 mutex_unlock(&devlink->lock); 3587 mutex_unlock(&devlink_mutex); 3588 3589 return skb->len; 3590 3591nla_put_failure: 3592 genlmsg_cancel(skb, hdr); 3593out_unlock: 3594 mutex_unlock(&devlink->lock); 3595 mutex_unlock(&devlink_mutex); 3596out: 3597 return 0; 3598} 3599 3600static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { 3601 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING }, 3602 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING }, 3603 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 }, 3604 [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 }, 3605 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 }, 3606 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 }, 3607 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 }, 3608 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 }, 3609 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 }, 3610 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 }, 3611 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 }, 3612 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 }, 3613 [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 }, 3614 [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 }, 3615 [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 }, 3616 [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING }, 3617 [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 }, 3618 [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64}, 3619 [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64}, 3620 [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING }, 3621 [DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 }, 3622 [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 }, 3623 [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING }, 3624 [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 }, 3625}; 3626 3627static const struct genl_ops devlink_nl_ops[] = { 3628 { 3629 .cmd = DEVLINK_CMD_GET, 3630 .doit = devlink_nl_cmd_get_doit, 3631 .dumpit = devlink_nl_cmd_get_dumpit, 3632 .policy = devlink_nl_policy, 3633 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3634 /* can be retrieved by unprivileged users */ 3635 }, 3636 { 3637 .cmd = DEVLINK_CMD_PORT_GET, 3638 .doit = devlink_nl_cmd_port_get_doit, 3639 .dumpit = devlink_nl_cmd_port_get_dumpit, 3640 .policy = devlink_nl_policy, 3641 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 3642 /* can be retrieved by unprivileged users */ 3643 }, 3644 { 3645 .cmd = DEVLINK_CMD_PORT_SET, 3646 .doit = devlink_nl_cmd_port_set_doit, 3647 .policy = devlink_nl_policy, 3648 .flags = GENL_ADMIN_PERM, 3649 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 3650 }, 3651 { 3652 .cmd = DEVLINK_CMD_PORT_SPLIT, 3653 .doit = devlink_nl_cmd_port_split_doit, 3654 .policy = devlink_nl_policy, 3655 .flags = GENL_ADMIN_PERM, 3656 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3657 DEVLINK_NL_FLAG_NO_LOCK, 3658 }, 3659 { 3660 .cmd = DEVLINK_CMD_PORT_UNSPLIT, 3661 .doit = devlink_nl_cmd_port_unsplit_doit, 3662 .policy = devlink_nl_policy, 3663 .flags = GENL_ADMIN_PERM, 3664 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3665 DEVLINK_NL_FLAG_NO_LOCK, 3666 }, 3667 { 3668 .cmd = DEVLINK_CMD_SB_GET, 3669 .doit = devlink_nl_cmd_sb_get_doit, 3670 .dumpit = devlink_nl_cmd_sb_get_dumpit, 3671 .policy = devlink_nl_policy, 3672 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3673 DEVLINK_NL_FLAG_NEED_SB, 3674 /* can be retrieved by unprivileged users */ 3675 }, 3676 { 3677 .cmd = DEVLINK_CMD_SB_POOL_GET, 3678 .doit = devlink_nl_cmd_sb_pool_get_doit, 3679 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit, 3680 .policy = devlink_nl_policy, 3681 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3682 DEVLINK_NL_FLAG_NEED_SB, 3683 /* can be retrieved by unprivileged users */ 3684 }, 3685 { 3686 .cmd = DEVLINK_CMD_SB_POOL_SET, 3687 .doit = devlink_nl_cmd_sb_pool_set_doit, 3688 .policy = devlink_nl_policy, 3689 .flags = GENL_ADMIN_PERM, 3690 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3691 DEVLINK_NL_FLAG_NEED_SB, 3692 }, 3693 { 3694 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET, 3695 .doit = devlink_nl_cmd_sb_port_pool_get_doit, 3696 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit, 3697 .policy = devlink_nl_policy, 3698 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 3699 DEVLINK_NL_FLAG_NEED_SB, 3700 /* can be retrieved by unprivileged users */ 3701 }, 3702 { 3703 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET, 3704 .doit = devlink_nl_cmd_sb_port_pool_set_doit, 3705 .policy = devlink_nl_policy, 3706 .flags = GENL_ADMIN_PERM, 3707 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 3708 DEVLINK_NL_FLAG_NEED_SB, 3709 }, 3710 { 3711 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET, 3712 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit, 3713 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit, 3714 .policy = devlink_nl_policy, 3715 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 3716 DEVLINK_NL_FLAG_NEED_SB, 3717 /* can be retrieved by unprivileged users */ 3718 }, 3719 { 3720 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET, 3721 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit, 3722 .policy = devlink_nl_policy, 3723 .flags = GENL_ADMIN_PERM, 3724 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 3725 DEVLINK_NL_FLAG_NEED_SB, 3726 }, 3727 { 3728 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT, 3729 .doit = devlink_nl_cmd_sb_occ_snapshot_doit, 3730 .policy = devlink_nl_policy, 3731 .flags = GENL_ADMIN_PERM, 3732 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3733 DEVLINK_NL_FLAG_NEED_SB, 3734 }, 3735 { 3736 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR, 3737 .doit = devlink_nl_cmd_sb_occ_max_clear_doit, 3738 .policy = devlink_nl_policy, 3739 .flags = GENL_ADMIN_PERM, 3740 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3741 DEVLINK_NL_FLAG_NEED_SB, 3742 }, 3743 { 3744 .cmd = DEVLINK_CMD_ESWITCH_GET, 3745 .doit = devlink_nl_cmd_eswitch_get_doit, 3746 .policy = devlink_nl_policy, 3747 .flags = GENL_ADMIN_PERM, 3748 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3749 }, 3750 { 3751 .cmd = DEVLINK_CMD_ESWITCH_SET, 3752 .doit = devlink_nl_cmd_eswitch_set_doit, 3753 .policy = devlink_nl_policy, 3754 .flags = GENL_ADMIN_PERM, 3755 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3756 DEVLINK_NL_FLAG_NO_LOCK, 3757 }, 3758 { 3759 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET, 3760 .doit = devlink_nl_cmd_dpipe_table_get, 3761 .policy = devlink_nl_policy, 3762 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3763 /* can be retrieved by unprivileged users */ 3764 }, 3765 { 3766 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET, 3767 .doit = devlink_nl_cmd_dpipe_entries_get, 3768 .policy = devlink_nl_policy, 3769 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3770 /* can be retrieved by unprivileged users */ 3771 }, 3772 { 3773 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET, 3774 .doit = devlink_nl_cmd_dpipe_headers_get, 3775 .policy = devlink_nl_policy, 3776 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3777 /* can be retrieved by unprivileged users */ 3778 }, 3779 { 3780 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET, 3781 .doit = devlink_nl_cmd_dpipe_table_counters_set, 3782 .policy = devlink_nl_policy, 3783 .flags = GENL_ADMIN_PERM, 3784 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3785 }, 3786 { 3787 .cmd = DEVLINK_CMD_RESOURCE_SET, 3788 .doit = devlink_nl_cmd_resource_set, 3789 .policy = devlink_nl_policy, 3790 .flags = GENL_ADMIN_PERM, 3791 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3792 }, 3793 { 3794 .cmd = DEVLINK_CMD_RESOURCE_DUMP, 3795 .doit = devlink_nl_cmd_resource_dump, 3796 .policy = devlink_nl_policy, 3797 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3798 /* can be retrieved by unprivileged users */ 3799 }, 3800 { 3801 .cmd = DEVLINK_CMD_RELOAD, 3802 .doit = devlink_nl_cmd_reload, 3803 .policy = devlink_nl_policy, 3804 .flags = GENL_ADMIN_PERM, 3805 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3806 DEVLINK_NL_FLAG_NO_LOCK, 3807 }, 3808 { 3809 .cmd = DEVLINK_CMD_PARAM_GET, 3810 .doit = devlink_nl_cmd_param_get_doit, 3811 .dumpit = devlink_nl_cmd_param_get_dumpit, 3812 .policy = devlink_nl_policy, 3813 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3814 /* can be retrieved by unprivileged users */ 3815 }, 3816 { 3817 .cmd = DEVLINK_CMD_PARAM_SET, 3818 .doit = devlink_nl_cmd_param_set_doit, 3819 .policy = devlink_nl_policy, 3820 .flags = GENL_ADMIN_PERM, 3821 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3822 }, 3823 { 3824 .cmd = DEVLINK_CMD_REGION_GET, 3825 .doit = devlink_nl_cmd_region_get_doit, 3826 .dumpit = devlink_nl_cmd_region_get_dumpit, 3827 .policy = devlink_nl_policy, 3828 .flags = GENL_ADMIN_PERM, 3829 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3830 }, 3831 { 3832 .cmd = DEVLINK_CMD_REGION_DEL, 3833 .doit = devlink_nl_cmd_region_del, 3834 .policy = devlink_nl_policy, 3835 .flags = GENL_ADMIN_PERM, 3836 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3837 }, 3838 { 3839 .cmd = DEVLINK_CMD_REGION_READ, 3840 .dumpit = devlink_nl_cmd_region_read_dumpit, 3841 .policy = devlink_nl_policy, 3842 .flags = GENL_ADMIN_PERM, 3843 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3844 }, 3845}; 3846 3847static struct genl_family devlink_nl_family __ro_after_init = { 3848 .name = DEVLINK_GENL_NAME, 3849 .version = DEVLINK_GENL_VERSION, 3850 .maxattr = DEVLINK_ATTR_MAX, 3851 .netnsok = true, 3852 .pre_doit = devlink_nl_pre_doit, 3853 .post_doit = devlink_nl_post_doit, 3854 .module = THIS_MODULE, 3855 .ops = devlink_nl_ops, 3856 .n_ops = ARRAY_SIZE(devlink_nl_ops), 3857 .mcgrps = devlink_nl_mcgrps, 3858 .n_mcgrps = ARRAY_SIZE(devlink_nl_mcgrps), 3859}; 3860 3861/** 3862 * devlink_alloc - Allocate new devlink instance resources 3863 * 3864 * @ops: ops 3865 * @priv_size: size of user private data 3866 * 3867 * Allocate new devlink instance resources, including devlink index 3868 * and name. 3869 */ 3870struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size) 3871{ 3872 struct devlink *devlink; 3873 3874 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL); 3875 if (!devlink) 3876 return NULL; 3877 devlink->ops = ops; 3878 devlink_net_set(devlink, &init_net); 3879 INIT_LIST_HEAD(&devlink->port_list); 3880 INIT_LIST_HEAD(&devlink->sb_list); 3881 INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list); 3882 INIT_LIST_HEAD(&devlink->resource_list); 3883 INIT_LIST_HEAD(&devlink->param_list); 3884 INIT_LIST_HEAD(&devlink->region_list); 3885 mutex_init(&devlink->lock); 3886 return devlink; 3887} 3888EXPORT_SYMBOL_GPL(devlink_alloc); 3889 3890/** 3891 * devlink_register - Register devlink instance 3892 * 3893 * @devlink: devlink 3894 */ 3895int devlink_register(struct devlink *devlink, struct device *dev) 3896{ 3897 mutex_lock(&devlink_mutex); 3898 devlink->dev = dev; 3899 list_add_tail(&devlink->list, &devlink_list); 3900 devlink_notify(devlink, DEVLINK_CMD_NEW); 3901 mutex_unlock(&devlink_mutex); 3902 return 0; 3903} 3904EXPORT_SYMBOL_GPL(devlink_register); 3905 3906/** 3907 * devlink_unregister - Unregister devlink instance 3908 * 3909 * @devlink: devlink 3910 */ 3911void devlink_unregister(struct devlink *devlink) 3912{ 3913 mutex_lock(&devlink_mutex); 3914 devlink_notify(devlink, DEVLINK_CMD_DEL); 3915 list_del(&devlink->list); 3916 mutex_unlock(&devlink_mutex); 3917} 3918EXPORT_SYMBOL_GPL(devlink_unregister); 3919 3920/** 3921 * devlink_free - Free devlink instance resources 3922 * 3923 * @devlink: devlink 3924 */ 3925void devlink_free(struct devlink *devlink) 3926{ 3927 kfree(devlink); 3928} 3929EXPORT_SYMBOL_GPL(devlink_free); 3930 3931/** 3932 * devlink_port_register - Register devlink port 3933 * 3934 * @devlink: devlink 3935 * @devlink_port: devlink port 3936 * @port_index 3937 * 3938 * Register devlink port with provided port index. User can use 3939 * any indexing, even hw-related one. devlink_port structure 3940 * is convenient to be embedded inside user driver private structure. 3941 * Note that the caller should take care of zeroing the devlink_port 3942 * structure. 3943 */ 3944int devlink_port_register(struct devlink *devlink, 3945 struct devlink_port *devlink_port, 3946 unsigned int port_index) 3947{ 3948 mutex_lock(&devlink->lock); 3949 if (devlink_port_index_exists(devlink, port_index)) { 3950 mutex_unlock(&devlink->lock); 3951 return -EEXIST; 3952 } 3953 devlink_port->devlink = devlink; 3954 devlink_port->index = port_index; 3955 devlink_port->registered = true; 3956 list_add_tail(&devlink_port->list, &devlink->port_list); 3957 mutex_unlock(&devlink->lock); 3958 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 3959 return 0; 3960} 3961EXPORT_SYMBOL_GPL(devlink_port_register); 3962 3963/** 3964 * devlink_port_unregister - Unregister devlink port 3965 * 3966 * @devlink_port: devlink port 3967 */ 3968void devlink_port_unregister(struct devlink_port *devlink_port) 3969{ 3970 struct devlink *devlink = devlink_port->devlink; 3971 3972 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL); 3973 mutex_lock(&devlink->lock); 3974 list_del(&devlink_port->list); 3975 mutex_unlock(&devlink->lock); 3976} 3977EXPORT_SYMBOL_GPL(devlink_port_unregister); 3978 3979static void __devlink_port_type_set(struct devlink_port *devlink_port, 3980 enum devlink_port_type type, 3981 void *type_dev) 3982{ 3983 devlink_port->type = type; 3984 devlink_port->type_dev = type_dev; 3985 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 3986} 3987 3988/** 3989 * devlink_port_type_eth_set - Set port type to Ethernet 3990 * 3991 * @devlink_port: devlink port 3992 * @netdev: related netdevice 3993 */ 3994void devlink_port_type_eth_set(struct devlink_port *devlink_port, 3995 struct net_device *netdev) 3996{ 3997 return __devlink_port_type_set(devlink_port, 3998 DEVLINK_PORT_TYPE_ETH, netdev); 3999} 4000EXPORT_SYMBOL_GPL(devlink_port_type_eth_set); 4001 4002/** 4003 * devlink_port_type_ib_set - Set port type to InfiniBand 4004 * 4005 * @devlink_port: devlink port 4006 * @ibdev: related IB device 4007 */ 4008void devlink_port_type_ib_set(struct devlink_port *devlink_port, 4009 struct ib_device *ibdev) 4010{ 4011 return __devlink_port_type_set(devlink_port, 4012 DEVLINK_PORT_TYPE_IB, ibdev); 4013} 4014EXPORT_SYMBOL_GPL(devlink_port_type_ib_set); 4015 4016/** 4017 * devlink_port_type_clear - Clear port type 4018 * 4019 * @devlink_port: devlink port 4020 */ 4021void devlink_port_type_clear(struct devlink_port *devlink_port) 4022{ 4023 return __devlink_port_type_set(devlink_port, 4024 DEVLINK_PORT_TYPE_NOTSET, NULL); 4025} 4026EXPORT_SYMBOL_GPL(devlink_port_type_clear); 4027 4028/** 4029 * devlink_port_attrs_set - Set port attributes 4030 * 4031 * @devlink_port: devlink port 4032 * @flavour: flavour of the port 4033 * @port_number: number of the port that is facing user, for example 4034 * the front panel port number 4035 * @split: indicates if this is split port 4036 * @split_subport_number: if the port is split, this is the number 4037 * of subport. 4038 */ 4039void devlink_port_attrs_set(struct devlink_port *devlink_port, 4040 enum devlink_port_flavour flavour, 4041 u32 port_number, bool split, 4042 u32 split_subport_number) 4043{ 4044 struct devlink_port_attrs *attrs = &devlink_port->attrs; 4045 4046 attrs->set = true; 4047 attrs->flavour = flavour; 4048 attrs->port_number = port_number; 4049 attrs->split = split; 4050 attrs->split_subport_number = split_subport_number; 4051 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 4052} 4053EXPORT_SYMBOL_GPL(devlink_port_attrs_set); 4054 4055int devlink_port_get_phys_port_name(struct devlink_port *devlink_port, 4056 char *name, size_t len) 4057{ 4058 struct devlink_port_attrs *attrs = &devlink_port->attrs; 4059 int n = 0; 4060 4061 if (!attrs->set) 4062 return -EOPNOTSUPP; 4063 4064 switch (attrs->flavour) { 4065 case DEVLINK_PORT_FLAVOUR_PHYSICAL: 4066 if (!attrs->split) 4067 n = snprintf(name, len, "p%u", attrs->port_number); 4068 else 4069 n = snprintf(name, len, "p%us%u", attrs->port_number, 4070 attrs->split_subport_number); 4071 break; 4072 case DEVLINK_PORT_FLAVOUR_CPU: 4073 case DEVLINK_PORT_FLAVOUR_DSA: 4074 /* As CPU and DSA ports do not have a netdevice associated 4075 * case should not ever happen. 4076 */ 4077 WARN_ON(1); 4078 return -EINVAL; 4079 } 4080 4081 if (n >= len) 4082 return -EINVAL; 4083 4084 return 0; 4085} 4086EXPORT_SYMBOL_GPL(devlink_port_get_phys_port_name); 4087 4088int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, 4089 u32 size, u16 ingress_pools_count, 4090 u16 egress_pools_count, u16 ingress_tc_count, 4091 u16 egress_tc_count) 4092{ 4093 struct devlink_sb *devlink_sb; 4094 int err = 0; 4095 4096 mutex_lock(&devlink->lock); 4097 if (devlink_sb_index_exists(devlink, sb_index)) { 4098 err = -EEXIST; 4099 goto unlock; 4100 } 4101 4102 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL); 4103 if (!devlink_sb) { 4104 err = -ENOMEM; 4105 goto unlock; 4106 } 4107 devlink_sb->index = sb_index; 4108 devlink_sb->size = size; 4109 devlink_sb->ingress_pools_count = ingress_pools_count; 4110 devlink_sb->egress_pools_count = egress_pools_count; 4111 devlink_sb->ingress_tc_count = ingress_tc_count; 4112 devlink_sb->egress_tc_count = egress_tc_count; 4113 list_add_tail(&devlink_sb->list, &devlink->sb_list); 4114unlock: 4115 mutex_unlock(&devlink->lock); 4116 return err; 4117} 4118EXPORT_SYMBOL_GPL(devlink_sb_register); 4119 4120void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index) 4121{ 4122 struct devlink_sb *devlink_sb; 4123 4124 mutex_lock(&devlink->lock); 4125 devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 4126 WARN_ON(!devlink_sb); 4127 list_del(&devlink_sb->list); 4128 mutex_unlock(&devlink->lock); 4129 kfree(devlink_sb); 4130} 4131EXPORT_SYMBOL_GPL(devlink_sb_unregister); 4132 4133/** 4134 * devlink_dpipe_headers_register - register dpipe headers 4135 * 4136 * @devlink: devlink 4137 * @dpipe_headers: dpipe header array 4138 * 4139 * Register the headers supported by hardware. 4140 */ 4141int devlink_dpipe_headers_register(struct devlink *devlink, 4142 struct devlink_dpipe_headers *dpipe_headers) 4143{ 4144 mutex_lock(&devlink->lock); 4145 devlink->dpipe_headers = dpipe_headers; 4146 mutex_unlock(&devlink->lock); 4147 return 0; 4148} 4149EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register); 4150 4151/** 4152 * devlink_dpipe_headers_unregister - unregister dpipe headers 4153 * 4154 * @devlink: devlink 4155 * 4156 * Unregister the headers supported by hardware. 4157 */ 4158void devlink_dpipe_headers_unregister(struct devlink *devlink) 4159{ 4160 mutex_lock(&devlink->lock); 4161 devlink->dpipe_headers = NULL; 4162 mutex_unlock(&devlink->lock); 4163} 4164EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister); 4165 4166/** 4167 * devlink_dpipe_table_counter_enabled - check if counter allocation 4168 * required 4169 * @devlink: devlink 4170 * @table_name: tables name 4171 * 4172 * Used by driver to check if counter allocation is required. 4173 * After counter allocation is turned on the table entries 4174 * are updated to include counter statistics. 4175 * 4176 * After that point on the driver must respect the counter 4177 * state so that each entry added to the table is added 4178 * with a counter. 4179 */ 4180bool devlink_dpipe_table_counter_enabled(struct devlink *devlink, 4181 const char *table_name) 4182{ 4183 struct devlink_dpipe_table *table; 4184 bool enabled; 4185 4186 rcu_read_lock(); 4187 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 4188 table_name); 4189 enabled = false; 4190 if (table) 4191 enabled = table->counters_enabled; 4192 rcu_read_unlock(); 4193 return enabled; 4194} 4195EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled); 4196 4197/** 4198 * devlink_dpipe_table_register - register dpipe table 4199 * 4200 * @devlink: devlink 4201 * @table_name: table name 4202 * @table_ops: table ops 4203 * @priv: priv 4204 * @counter_control_extern: external control for counters 4205 */ 4206int devlink_dpipe_table_register(struct devlink *devlink, 4207 const char *table_name, 4208 struct devlink_dpipe_table_ops *table_ops, 4209 void *priv, bool counter_control_extern) 4210{ 4211 struct devlink_dpipe_table *table; 4212 4213 if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name)) 4214 return -EEXIST; 4215 4216 if (WARN_ON(!table_ops->size_get)) 4217 return -EINVAL; 4218 4219 table = kzalloc(sizeof(*table), GFP_KERNEL); 4220 if (!table) 4221 return -ENOMEM; 4222 4223 table->name = table_name; 4224 table->table_ops = table_ops; 4225 table->priv = priv; 4226 table->counter_control_extern = counter_control_extern; 4227 4228 mutex_lock(&devlink->lock); 4229 list_add_tail_rcu(&table->list, &devlink->dpipe_table_list); 4230 mutex_unlock(&devlink->lock); 4231 return 0; 4232} 4233EXPORT_SYMBOL_GPL(devlink_dpipe_table_register); 4234 4235/** 4236 * devlink_dpipe_table_unregister - unregister dpipe table 4237 * 4238 * @devlink: devlink 4239 * @table_name: table name 4240 */ 4241void devlink_dpipe_table_unregister(struct devlink *devlink, 4242 const char *table_name) 4243{ 4244 struct devlink_dpipe_table *table; 4245 4246 mutex_lock(&devlink->lock); 4247 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 4248 table_name); 4249 if (!table) 4250 goto unlock; 4251 list_del_rcu(&table->list); 4252 mutex_unlock(&devlink->lock); 4253 kfree_rcu(table, rcu); 4254 return; 4255unlock: 4256 mutex_unlock(&devlink->lock); 4257} 4258EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister); 4259 4260/** 4261 * devlink_resource_register - devlink resource register 4262 * 4263 * @devlink: devlink 4264 * @resource_name: resource's name 4265 * @top_hierarchy: top hierarchy 4266 * @reload_required: reload is required for new configuration to 4267 * apply 4268 * @resource_size: resource's size 4269 * @resource_id: resource's id 4270 * @parent_reosurce_id: resource's parent id 4271 * @size params: size parameters 4272 */ 4273int devlink_resource_register(struct devlink *devlink, 4274 const char *resource_name, 4275 u64 resource_size, 4276 u64 resource_id, 4277 u64 parent_resource_id, 4278 const struct devlink_resource_size_params *size_params) 4279{ 4280 struct devlink_resource *resource; 4281 struct list_head *resource_list; 4282 bool top_hierarchy; 4283 int err = 0; 4284 4285 top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP; 4286 4287 mutex_lock(&devlink->lock); 4288 resource = devlink_resource_find(devlink, NULL, resource_id); 4289 if (resource) { 4290 err = -EINVAL; 4291 goto out; 4292 } 4293 4294 resource = kzalloc(sizeof(*resource), GFP_KERNEL); 4295 if (!resource) { 4296 err = -ENOMEM; 4297 goto out; 4298 } 4299 4300 if (top_hierarchy) { 4301 resource_list = &devlink->resource_list; 4302 } else { 4303 struct devlink_resource *parent_resource; 4304 4305 parent_resource = devlink_resource_find(devlink, NULL, 4306 parent_resource_id); 4307 if (parent_resource) { 4308 resource_list = &parent_resource->resource_list; 4309 resource->parent = parent_resource; 4310 } else { 4311 kfree(resource); 4312 err = -EINVAL; 4313 goto out; 4314 } 4315 } 4316 4317 resource->name = resource_name; 4318 resource->size = resource_size; 4319 resource->size_new = resource_size; 4320 resource->id = resource_id; 4321 resource->size_valid = true; 4322 memcpy(&resource->size_params, size_params, 4323 sizeof(resource->size_params)); 4324 INIT_LIST_HEAD(&resource->resource_list); 4325 list_add_tail(&resource->list, resource_list); 4326out: 4327 mutex_unlock(&devlink->lock); 4328 return err; 4329} 4330EXPORT_SYMBOL_GPL(devlink_resource_register); 4331 4332/** 4333 * devlink_resources_unregister - free all resources 4334 * 4335 * @devlink: devlink 4336 * @resource: resource 4337 */ 4338void devlink_resources_unregister(struct devlink *devlink, 4339 struct devlink_resource *resource) 4340{ 4341 struct devlink_resource *tmp, *child_resource; 4342 struct list_head *resource_list; 4343 4344 if (resource) 4345 resource_list = &resource->resource_list; 4346 else 4347 resource_list = &devlink->resource_list; 4348 4349 if (!resource) 4350 mutex_lock(&devlink->lock); 4351 4352 list_for_each_entry_safe(child_resource, tmp, resource_list, list) { 4353 devlink_resources_unregister(devlink, child_resource); 4354 list_del(&child_resource->list); 4355 kfree(child_resource); 4356 } 4357 4358 if (!resource) 4359 mutex_unlock(&devlink->lock); 4360} 4361EXPORT_SYMBOL_GPL(devlink_resources_unregister); 4362 4363/** 4364 * devlink_resource_size_get - get and update size 4365 * 4366 * @devlink: devlink 4367 * @resource_id: the requested resource id 4368 * @p_resource_size: ptr to update 4369 */ 4370int devlink_resource_size_get(struct devlink *devlink, 4371 u64 resource_id, 4372 u64 *p_resource_size) 4373{ 4374 struct devlink_resource *resource; 4375 int err = 0; 4376 4377 mutex_lock(&devlink->lock); 4378 resource = devlink_resource_find(devlink, NULL, resource_id); 4379 if (!resource) { 4380 err = -EINVAL; 4381 goto out; 4382 } 4383 *p_resource_size = resource->size_new; 4384 resource->size = resource->size_new; 4385out: 4386 mutex_unlock(&devlink->lock); 4387 return err; 4388} 4389EXPORT_SYMBOL_GPL(devlink_resource_size_get); 4390 4391/** 4392 * devlink_dpipe_table_resource_set - set the resource id 4393 * 4394 * @devlink: devlink 4395 * @table_name: table name 4396 * @resource_id: resource id 4397 * @resource_units: number of resource's units consumed per table's entry 4398 */ 4399int devlink_dpipe_table_resource_set(struct devlink *devlink, 4400 const char *table_name, u64 resource_id, 4401 u64 resource_units) 4402{ 4403 struct devlink_dpipe_table *table; 4404 int err = 0; 4405 4406 mutex_lock(&devlink->lock); 4407 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 4408 table_name); 4409 if (!table) { 4410 err = -EINVAL; 4411 goto out; 4412 } 4413 table->resource_id = resource_id; 4414 table->resource_units = resource_units; 4415 table->resource_valid = true; 4416out: 4417 mutex_unlock(&devlink->lock); 4418 return err; 4419} 4420EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set); 4421 4422/** 4423 * devlink_resource_occ_get_register - register occupancy getter 4424 * 4425 * @devlink: devlink 4426 * @resource_id: resource id 4427 * @occ_get: occupancy getter callback 4428 * @occ_get_priv: occupancy getter callback priv 4429 */ 4430void devlink_resource_occ_get_register(struct devlink *devlink, 4431 u64 resource_id, 4432 devlink_resource_occ_get_t *occ_get, 4433 void *occ_get_priv) 4434{ 4435 struct devlink_resource *resource; 4436 4437 mutex_lock(&devlink->lock); 4438 resource = devlink_resource_find(devlink, NULL, resource_id); 4439 if (WARN_ON(!resource)) 4440 goto out; 4441 WARN_ON(resource->occ_get); 4442 4443 resource->occ_get = occ_get; 4444 resource->occ_get_priv = occ_get_priv; 4445out: 4446 mutex_unlock(&devlink->lock); 4447} 4448EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register); 4449 4450/** 4451 * devlink_resource_occ_get_unregister - unregister occupancy getter 4452 * 4453 * @devlink: devlink 4454 * @resource_id: resource id 4455 */ 4456void devlink_resource_occ_get_unregister(struct devlink *devlink, 4457 u64 resource_id) 4458{ 4459 struct devlink_resource *resource; 4460 4461 mutex_lock(&devlink->lock); 4462 resource = devlink_resource_find(devlink, NULL, resource_id); 4463 if (WARN_ON(!resource)) 4464 goto out; 4465 WARN_ON(!resource->occ_get); 4466 4467 resource->occ_get = NULL; 4468 resource->occ_get_priv = NULL; 4469out: 4470 mutex_unlock(&devlink->lock); 4471} 4472EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister); 4473 4474/** 4475 * devlink_params_register - register configuration parameters 4476 * 4477 * @devlink: devlink 4478 * @params: configuration parameters array 4479 * @params_count: number of parameters provided 4480 * 4481 * Register the configuration parameters supported by the driver. 4482 */ 4483int devlink_params_register(struct devlink *devlink, 4484 const struct devlink_param *params, 4485 size_t params_count) 4486{ 4487 const struct devlink_param *param = params; 4488 int i; 4489 int err; 4490 4491 mutex_lock(&devlink->lock); 4492 for (i = 0; i < params_count; i++, param++) { 4493 if (!param || !param->name || !param->supported_cmodes) { 4494 err = -EINVAL; 4495 goto rollback; 4496 } 4497 if (param->generic) { 4498 err = devlink_param_generic_verify(param); 4499 if (err) 4500 goto rollback; 4501 } else { 4502 err = devlink_param_driver_verify(param); 4503 if (err) 4504 goto rollback; 4505 } 4506 err = devlink_param_register_one(devlink, param); 4507 if (err) 4508 goto rollback; 4509 } 4510 4511 mutex_unlock(&devlink->lock); 4512 return 0; 4513 4514rollback: 4515 if (!i) 4516 goto unlock; 4517 for (param--; i > 0; i--, param--) 4518 devlink_param_unregister_one(devlink, param); 4519unlock: 4520 mutex_unlock(&devlink->lock); 4521 return err; 4522} 4523EXPORT_SYMBOL_GPL(devlink_params_register); 4524 4525/** 4526 * devlink_params_unregister - unregister configuration parameters 4527 * @devlink: devlink 4528 * @params: configuration parameters to unregister 4529 * @params_count: number of parameters provided 4530 */ 4531void devlink_params_unregister(struct devlink *devlink, 4532 const struct devlink_param *params, 4533 size_t params_count) 4534{ 4535 const struct devlink_param *param = params; 4536 int i; 4537 4538 mutex_lock(&devlink->lock); 4539 for (i = 0; i < params_count; i++, param++) 4540 devlink_param_unregister_one(devlink, param); 4541 mutex_unlock(&devlink->lock); 4542} 4543EXPORT_SYMBOL_GPL(devlink_params_unregister); 4544 4545/** 4546 * devlink_param_driverinit_value_get - get configuration parameter 4547 * value for driver initializing 4548 * 4549 * @devlink: devlink 4550 * @param_id: parameter ID 4551 * @init_val: value of parameter in driverinit configuration mode 4552 * 4553 * This function should be used by the driver to get driverinit 4554 * configuration for initialization after reload command. 4555 */ 4556int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id, 4557 union devlink_param_value *init_val) 4558{ 4559 struct devlink_param_item *param_item; 4560 4561 if (!devlink->ops || !devlink->ops->reload) 4562 return -EOPNOTSUPP; 4563 4564 param_item = devlink_param_find_by_id(&devlink->param_list, param_id); 4565 if (!param_item) 4566 return -EINVAL; 4567 4568 if (!param_item->driverinit_value_valid || 4569 !devlink_param_cmode_is_supported(param_item->param, 4570 DEVLINK_PARAM_CMODE_DRIVERINIT)) 4571 return -EOPNOTSUPP; 4572 4573 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING) 4574 strcpy(init_val->vstr, param_item->driverinit_value.vstr); 4575 else 4576 *init_val = param_item->driverinit_value; 4577 4578 return 0; 4579} 4580EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_get); 4581 4582/** 4583 * devlink_param_driverinit_value_set - set value of configuration 4584 * parameter for driverinit 4585 * configuration mode 4586 * 4587 * @devlink: devlink 4588 * @param_id: parameter ID 4589 * @init_val: value of parameter to set for driverinit configuration mode 4590 * 4591 * This function should be used by the driver to set driverinit 4592 * configuration mode default value. 4593 */ 4594int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id, 4595 union devlink_param_value init_val) 4596{ 4597 struct devlink_param_item *param_item; 4598 4599 param_item = devlink_param_find_by_id(&devlink->param_list, param_id); 4600 if (!param_item) 4601 return -EINVAL; 4602 4603 if (!devlink_param_cmode_is_supported(param_item->param, 4604 DEVLINK_PARAM_CMODE_DRIVERINIT)) 4605 return -EOPNOTSUPP; 4606 4607 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING) 4608 strcpy(param_item->driverinit_value.vstr, init_val.vstr); 4609 else 4610 param_item->driverinit_value = init_val; 4611 param_item->driverinit_value_valid = true; 4612 4613 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW); 4614 return 0; 4615} 4616EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_set); 4617 4618/** 4619 * devlink_param_value_changed - notify devlink on a parameter's value 4620 * change. Should be called by the driver 4621 * right after the change. 4622 * 4623 * @devlink: devlink 4624 * @param_id: parameter ID 4625 * 4626 * This function should be used by the driver to notify devlink on value 4627 * change, excluding driverinit configuration mode. 4628 * For driverinit configuration mode driver should use the function 4629 * devlink_param_driverinit_value_set() instead. 4630 */ 4631void devlink_param_value_changed(struct devlink *devlink, u32 param_id) 4632{ 4633 struct devlink_param_item *param_item; 4634 4635 param_item = devlink_param_find_by_id(&devlink->param_list, param_id); 4636 WARN_ON(!param_item); 4637 4638 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW); 4639} 4640EXPORT_SYMBOL_GPL(devlink_param_value_changed); 4641 4642/** 4643 * devlink_param_value_str_fill - Safely fill-up the string preventing 4644 * from overflow of the preallocated buffer 4645 * 4646 * @dst_val: destination devlink_param_value 4647 * @src: source buffer 4648 */ 4649void devlink_param_value_str_fill(union devlink_param_value *dst_val, 4650 const char *src) 4651{ 4652 size_t len; 4653 4654 len = strlcpy(dst_val->vstr, src, __DEVLINK_PARAM_MAX_STRING_VALUE); 4655 WARN_ON(len >= __DEVLINK_PARAM_MAX_STRING_VALUE); 4656} 4657EXPORT_SYMBOL_GPL(devlink_param_value_str_fill); 4658 4659/** 4660 * devlink_region_create - create a new address region 4661 * 4662 * @devlink: devlink 4663 * @region_name: region name 4664 * @region_max_snapshots: Maximum supported number of snapshots for region 4665 * @region_size: size of region 4666 */ 4667struct devlink_region *devlink_region_create(struct devlink *devlink, 4668 const char *region_name, 4669 u32 region_max_snapshots, 4670 u64 region_size) 4671{ 4672 struct devlink_region *region; 4673 int err = 0; 4674 4675 mutex_lock(&devlink->lock); 4676 4677 if (devlink_region_get_by_name(devlink, region_name)) { 4678 err = -EEXIST; 4679 goto unlock; 4680 } 4681 4682 region = kzalloc(sizeof(*region), GFP_KERNEL); 4683 if (!region) { 4684 err = -ENOMEM; 4685 goto unlock; 4686 } 4687 4688 region->devlink = devlink; 4689 region->max_snapshots = region_max_snapshots; 4690 region->name = region_name; 4691 region->size = region_size; 4692 INIT_LIST_HEAD(&region->snapshot_list); 4693 list_add_tail(&region->list, &devlink->region_list); 4694 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW); 4695 4696 mutex_unlock(&devlink->lock); 4697 return region; 4698 4699unlock: 4700 mutex_unlock(&devlink->lock); 4701 return ERR_PTR(err); 4702} 4703EXPORT_SYMBOL_GPL(devlink_region_create); 4704 4705/** 4706 * devlink_region_destroy - destroy address region 4707 * 4708 * @region: devlink region to destroy 4709 */ 4710void devlink_region_destroy(struct devlink_region *region) 4711{ 4712 struct devlink *devlink = region->devlink; 4713 struct devlink_snapshot *snapshot, *ts; 4714 4715 mutex_lock(&devlink->lock); 4716 4717 /* Free all snapshots of region */ 4718 list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list) 4719 devlink_region_snapshot_del(snapshot); 4720 4721 list_del(&region->list); 4722 4723 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL); 4724 mutex_unlock(&devlink->lock); 4725 kfree(region); 4726} 4727EXPORT_SYMBOL_GPL(devlink_region_destroy); 4728 4729/** 4730 * devlink_region_shapshot_id_get - get snapshot ID 4731 * 4732 * This callback should be called when adding a new snapshot, 4733 * Driver should use the same id for multiple snapshots taken 4734 * on multiple regions at the same time/by the same trigger. 4735 * 4736 * @devlink: devlink 4737 */ 4738u32 devlink_region_shapshot_id_get(struct devlink *devlink) 4739{ 4740 u32 id; 4741 4742 mutex_lock(&devlink->lock); 4743 id = ++devlink->snapshot_id; 4744 mutex_unlock(&devlink->lock); 4745 4746 return id; 4747} 4748EXPORT_SYMBOL_GPL(devlink_region_shapshot_id_get); 4749 4750/** 4751 * devlink_region_snapshot_create - create a new snapshot 4752 * This will add a new snapshot of a region. The snapshot 4753 * will be stored on the region struct and can be accessed 4754 * from devlink. This is useful for future analyses of snapshots. 4755 * Multiple snapshots can be created on a region. 4756 * The @snapshot_id should be obtained using the getter function. 4757 * 4758 * @devlink_region: devlink region of the snapshot 4759 * @data_len: size of snapshot data 4760 * @data: snapshot data 4761 * @snapshot_id: snapshot id to be created 4762 * @data_destructor: pointer to destructor function to free data 4763 */ 4764int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len, 4765 u8 *data, u32 snapshot_id, 4766 devlink_snapshot_data_dest_t *data_destructor) 4767{ 4768 struct devlink *devlink = region->devlink; 4769 struct devlink_snapshot *snapshot; 4770 int err; 4771 4772 mutex_lock(&devlink->lock); 4773 4774 /* check if region can hold one more snapshot */ 4775 if (region->cur_snapshots == region->max_snapshots) { 4776 err = -ENOMEM; 4777 goto unlock; 4778 } 4779 4780 if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { 4781 err = -EEXIST; 4782 goto unlock; 4783 } 4784 4785 snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL); 4786 if (!snapshot) { 4787 err = -ENOMEM; 4788 goto unlock; 4789 } 4790 4791 snapshot->id = snapshot_id; 4792 snapshot->region = region; 4793 snapshot->data = data; 4794 snapshot->data_len = data_len; 4795 snapshot->data_destructor = data_destructor; 4796 4797 list_add_tail(&snapshot->list, &region->snapshot_list); 4798 4799 region->cur_snapshots++; 4800 4801 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW); 4802 mutex_unlock(&devlink->lock); 4803 return 0; 4804 4805unlock: 4806 mutex_unlock(&devlink->lock); 4807 return err; 4808} 4809EXPORT_SYMBOL_GPL(devlink_region_snapshot_create); 4810 4811static int __init devlink_module_init(void) 4812{ 4813 return genl_register_family(&devlink_nl_family); 4814} 4815 4816static void __exit devlink_module_exit(void) 4817{ 4818 genl_unregister_family(&devlink_nl_family); 4819} 4820 4821module_init(devlink_module_init); 4822module_exit(devlink_module_exit); 4823 4824MODULE_LICENSE("GPL v2"); 4825MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>"); 4826MODULE_DESCRIPTION("Network physical device Netlink interface"); 4827MODULE_ALIAS_GENL_FAMILY(DEVLINK_GENL_NAME);