at v4.20-rc4 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 2697static int devlink_param_generic_verify(const struct devlink_param *param) 2698{ 2699 /* verify it match generic parameter by id and name */ 2700 if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX) 2701 return -EINVAL; 2702 if (strcmp(param->name, devlink_param_generic[param->id].name)) 2703 return -ENOENT; 2704 2705 WARN_ON(param->type != devlink_param_generic[param->id].type); 2706 2707 return 0; 2708} 2709 2710static int devlink_param_driver_verify(const struct devlink_param *param) 2711{ 2712 int i; 2713 2714 if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX) 2715 return -EINVAL; 2716 /* verify no such name in generic params */ 2717 for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++) 2718 if (!strcmp(param->name, devlink_param_generic[i].name)) 2719 return -EEXIST; 2720 2721 return 0; 2722} 2723 2724static struct devlink_param_item * 2725devlink_param_find_by_name(struct list_head *param_list, 2726 const char *param_name) 2727{ 2728 struct devlink_param_item *param_item; 2729 2730 list_for_each_entry(param_item, param_list, list) 2731 if (!strcmp(param_item->param->name, param_name)) 2732 return param_item; 2733 return NULL; 2734} 2735 2736static struct devlink_param_item * 2737devlink_param_find_by_id(struct list_head *param_list, u32 param_id) 2738{ 2739 struct devlink_param_item *param_item; 2740 2741 list_for_each_entry(param_item, param_list, list) 2742 if (param_item->param->id == param_id) 2743 return param_item; 2744 return NULL; 2745} 2746 2747static bool 2748devlink_param_cmode_is_supported(const struct devlink_param *param, 2749 enum devlink_param_cmode cmode) 2750{ 2751 return test_bit(cmode, &param->supported_cmodes); 2752} 2753 2754static int devlink_param_get(struct devlink *devlink, 2755 const struct devlink_param *param, 2756 struct devlink_param_gset_ctx *ctx) 2757{ 2758 if (!param->get) 2759 return -EOPNOTSUPP; 2760 return param->get(devlink, param->id, ctx); 2761} 2762 2763static int devlink_param_set(struct devlink *devlink, 2764 const struct devlink_param *param, 2765 struct devlink_param_gset_ctx *ctx) 2766{ 2767 if (!param->set) 2768 return -EOPNOTSUPP; 2769 return param->set(devlink, param->id, ctx); 2770} 2771 2772static int 2773devlink_param_type_to_nla_type(enum devlink_param_type param_type) 2774{ 2775 switch (param_type) { 2776 case DEVLINK_PARAM_TYPE_U8: 2777 return NLA_U8; 2778 case DEVLINK_PARAM_TYPE_U16: 2779 return NLA_U16; 2780 case DEVLINK_PARAM_TYPE_U32: 2781 return NLA_U32; 2782 case DEVLINK_PARAM_TYPE_STRING: 2783 return NLA_STRING; 2784 case DEVLINK_PARAM_TYPE_BOOL: 2785 return NLA_FLAG; 2786 default: 2787 return -EINVAL; 2788 } 2789} 2790 2791static int 2792devlink_nl_param_value_fill_one(struct sk_buff *msg, 2793 enum devlink_param_type type, 2794 enum devlink_param_cmode cmode, 2795 union devlink_param_value val) 2796{ 2797 struct nlattr *param_value_attr; 2798 2799 param_value_attr = nla_nest_start(msg, DEVLINK_ATTR_PARAM_VALUE); 2800 if (!param_value_attr) 2801 goto nla_put_failure; 2802 2803 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode)) 2804 goto value_nest_cancel; 2805 2806 switch (type) { 2807 case DEVLINK_PARAM_TYPE_U8: 2808 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8)) 2809 goto value_nest_cancel; 2810 break; 2811 case DEVLINK_PARAM_TYPE_U16: 2812 if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16)) 2813 goto value_nest_cancel; 2814 break; 2815 case DEVLINK_PARAM_TYPE_U32: 2816 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32)) 2817 goto value_nest_cancel; 2818 break; 2819 case DEVLINK_PARAM_TYPE_STRING: 2820 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, 2821 val.vstr)) 2822 goto value_nest_cancel; 2823 break; 2824 case DEVLINK_PARAM_TYPE_BOOL: 2825 if (val.vbool && 2826 nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA)) 2827 goto value_nest_cancel; 2828 break; 2829 } 2830 2831 nla_nest_end(msg, param_value_attr); 2832 return 0; 2833 2834value_nest_cancel: 2835 nla_nest_cancel(msg, param_value_attr); 2836nla_put_failure: 2837 return -EMSGSIZE; 2838} 2839 2840static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, 2841 struct devlink_param_item *param_item, 2842 enum devlink_command cmd, 2843 u32 portid, u32 seq, int flags) 2844{ 2845 union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1]; 2846 const struct devlink_param *param = param_item->param; 2847 struct devlink_param_gset_ctx ctx; 2848 struct nlattr *param_values_list; 2849 struct nlattr *param_attr; 2850 int nla_type; 2851 void *hdr; 2852 int err; 2853 int i; 2854 2855 /* Get value from driver part to driverinit configuration mode */ 2856 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 2857 if (!devlink_param_cmode_is_supported(param, i)) 2858 continue; 2859 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) { 2860 if (!param_item->driverinit_value_valid) 2861 return -EOPNOTSUPP; 2862 param_value[i] = param_item->driverinit_value; 2863 } else { 2864 ctx.cmode = i; 2865 err = devlink_param_get(devlink, param, &ctx); 2866 if (err) 2867 return err; 2868 param_value[i] = ctx.val; 2869 } 2870 } 2871 2872 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 2873 if (!hdr) 2874 return -EMSGSIZE; 2875 2876 if (devlink_nl_put_handle(msg, devlink)) 2877 goto genlmsg_cancel; 2878 param_attr = nla_nest_start(msg, DEVLINK_ATTR_PARAM); 2879 if (!param_attr) 2880 goto genlmsg_cancel; 2881 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name)) 2882 goto param_nest_cancel; 2883 if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC)) 2884 goto param_nest_cancel; 2885 2886 nla_type = devlink_param_type_to_nla_type(param->type); 2887 if (nla_type < 0) 2888 goto param_nest_cancel; 2889 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type)) 2890 goto param_nest_cancel; 2891 2892 param_values_list = nla_nest_start(msg, DEVLINK_ATTR_PARAM_VALUES_LIST); 2893 if (!param_values_list) 2894 goto param_nest_cancel; 2895 2896 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 2897 if (!devlink_param_cmode_is_supported(param, i)) 2898 continue; 2899 err = devlink_nl_param_value_fill_one(msg, param->type, 2900 i, param_value[i]); 2901 if (err) 2902 goto values_list_nest_cancel; 2903 } 2904 2905 nla_nest_end(msg, param_values_list); 2906 nla_nest_end(msg, param_attr); 2907 genlmsg_end(msg, hdr); 2908 return 0; 2909 2910values_list_nest_cancel: 2911 nla_nest_end(msg, param_values_list); 2912param_nest_cancel: 2913 nla_nest_cancel(msg, param_attr); 2914genlmsg_cancel: 2915 genlmsg_cancel(msg, hdr); 2916 return -EMSGSIZE; 2917} 2918 2919static void devlink_param_notify(struct devlink *devlink, 2920 struct devlink_param_item *param_item, 2921 enum devlink_command cmd) 2922{ 2923 struct sk_buff *msg; 2924 int err; 2925 2926 WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL); 2927 2928 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 2929 if (!msg) 2930 return; 2931 err = devlink_nl_param_fill(msg, devlink, param_item, cmd, 0, 0, 0); 2932 if (err) { 2933 nlmsg_free(msg); 2934 return; 2935 } 2936 2937 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 2938 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 2939} 2940 2941static int devlink_nl_cmd_param_get_dumpit(struct sk_buff *msg, 2942 struct netlink_callback *cb) 2943{ 2944 struct devlink_param_item *param_item; 2945 struct devlink *devlink; 2946 int start = cb->args[0]; 2947 int idx = 0; 2948 int err; 2949 2950 mutex_lock(&devlink_mutex); 2951 list_for_each_entry(devlink, &devlink_list, list) { 2952 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 2953 continue; 2954 mutex_lock(&devlink->lock); 2955 list_for_each_entry(param_item, &devlink->param_list, list) { 2956 if (idx < start) { 2957 idx++; 2958 continue; 2959 } 2960 err = devlink_nl_param_fill(msg, devlink, param_item, 2961 DEVLINK_CMD_PARAM_GET, 2962 NETLINK_CB(cb->skb).portid, 2963 cb->nlh->nlmsg_seq, 2964 NLM_F_MULTI); 2965 if (err) { 2966 mutex_unlock(&devlink->lock); 2967 goto out; 2968 } 2969 idx++; 2970 } 2971 mutex_unlock(&devlink->lock); 2972 } 2973out: 2974 mutex_unlock(&devlink_mutex); 2975 2976 cb->args[0] = idx; 2977 return msg->len; 2978} 2979 2980static int 2981devlink_param_type_get_from_info(struct genl_info *info, 2982 enum devlink_param_type *param_type) 2983{ 2984 if (!info->attrs[DEVLINK_ATTR_PARAM_TYPE]) 2985 return -EINVAL; 2986 2987 switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) { 2988 case NLA_U8: 2989 *param_type = DEVLINK_PARAM_TYPE_U8; 2990 break; 2991 case NLA_U16: 2992 *param_type = DEVLINK_PARAM_TYPE_U16; 2993 break; 2994 case NLA_U32: 2995 *param_type = DEVLINK_PARAM_TYPE_U32; 2996 break; 2997 case NLA_STRING: 2998 *param_type = DEVLINK_PARAM_TYPE_STRING; 2999 break; 3000 case NLA_FLAG: 3001 *param_type = DEVLINK_PARAM_TYPE_BOOL; 3002 break; 3003 default: 3004 return -EINVAL; 3005 } 3006 3007 return 0; 3008} 3009 3010static int 3011devlink_param_value_get_from_info(const struct devlink_param *param, 3012 struct genl_info *info, 3013 union devlink_param_value *value) 3014{ 3015 int len; 3016 3017 if (param->type != DEVLINK_PARAM_TYPE_BOOL && 3018 !info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) 3019 return -EINVAL; 3020 3021 switch (param->type) { 3022 case DEVLINK_PARAM_TYPE_U8: 3023 value->vu8 = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3024 break; 3025 case DEVLINK_PARAM_TYPE_U16: 3026 value->vu16 = nla_get_u16(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3027 break; 3028 case DEVLINK_PARAM_TYPE_U32: 3029 value->vu32 = nla_get_u32(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3030 break; 3031 case DEVLINK_PARAM_TYPE_STRING: 3032 len = strnlen(nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]), 3033 nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])); 3034 if (len == nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) || 3035 len >= __DEVLINK_PARAM_MAX_STRING_VALUE) 3036 return -EINVAL; 3037 strcpy(value->vstr, 3038 nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])); 3039 break; 3040 case DEVLINK_PARAM_TYPE_BOOL: 3041 value->vbool = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA] ? 3042 true : false; 3043 break; 3044 } 3045 return 0; 3046} 3047 3048static struct devlink_param_item * 3049devlink_param_get_from_info(struct devlink *devlink, 3050 struct genl_info *info) 3051{ 3052 char *param_name; 3053 3054 if (!info->attrs[DEVLINK_ATTR_PARAM_NAME]) 3055 return NULL; 3056 3057 param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]); 3058 return devlink_param_find_by_name(&devlink->param_list, param_name); 3059} 3060 3061static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb, 3062 struct genl_info *info) 3063{ 3064 struct devlink *devlink = info->user_ptr[0]; 3065 struct devlink_param_item *param_item; 3066 struct sk_buff *msg; 3067 int err; 3068 3069 param_item = devlink_param_get_from_info(devlink, info); 3070 if (!param_item) 3071 return -EINVAL; 3072 3073 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3074 if (!msg) 3075 return -ENOMEM; 3076 3077 err = devlink_nl_param_fill(msg, devlink, param_item, 3078 DEVLINK_CMD_PARAM_GET, 3079 info->snd_portid, info->snd_seq, 0); 3080 if (err) { 3081 nlmsg_free(msg); 3082 return err; 3083 } 3084 3085 return genlmsg_reply(msg, info); 3086} 3087 3088static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb, 3089 struct genl_info *info) 3090{ 3091 struct devlink *devlink = info->user_ptr[0]; 3092 enum devlink_param_type param_type; 3093 struct devlink_param_gset_ctx ctx; 3094 enum devlink_param_cmode cmode; 3095 struct devlink_param_item *param_item; 3096 const struct devlink_param *param; 3097 union devlink_param_value value; 3098 int err = 0; 3099 3100 param_item = devlink_param_get_from_info(devlink, info); 3101 if (!param_item) 3102 return -EINVAL; 3103 param = param_item->param; 3104 err = devlink_param_type_get_from_info(info, &param_type); 3105 if (err) 3106 return err; 3107 if (param_type != param->type) 3108 return -EINVAL; 3109 err = devlink_param_value_get_from_info(param, info, &value); 3110 if (err) 3111 return err; 3112 if (param->validate) { 3113 err = param->validate(devlink, param->id, value, info->extack); 3114 if (err) 3115 return err; 3116 } 3117 3118 if (!info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]) 3119 return -EINVAL; 3120 cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]); 3121 if (!devlink_param_cmode_is_supported(param, cmode)) 3122 return -EOPNOTSUPP; 3123 3124 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) { 3125 if (param->type == DEVLINK_PARAM_TYPE_STRING) 3126 strcpy(param_item->driverinit_value.vstr, value.vstr); 3127 else 3128 param_item->driverinit_value = value; 3129 param_item->driverinit_value_valid = true; 3130 } else { 3131 if (!param->set) 3132 return -EOPNOTSUPP; 3133 ctx.val = value; 3134 ctx.cmode = cmode; 3135 err = devlink_param_set(devlink, param, &ctx); 3136 if (err) 3137 return err; 3138 } 3139 3140 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW); 3141 return 0; 3142} 3143 3144static int devlink_param_register_one(struct devlink *devlink, 3145 const struct devlink_param *param) 3146{ 3147 struct devlink_param_item *param_item; 3148 3149 if (devlink_param_find_by_name(&devlink->param_list, 3150 param->name)) 3151 return -EEXIST; 3152 3153 if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT)) 3154 WARN_ON(param->get || param->set); 3155 else 3156 WARN_ON(!param->get || !param->set); 3157 3158 param_item = kzalloc(sizeof(*param_item), GFP_KERNEL); 3159 if (!param_item) 3160 return -ENOMEM; 3161 param_item->param = param; 3162 3163 list_add_tail(&param_item->list, &devlink->param_list); 3164 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW); 3165 return 0; 3166} 3167 3168static void devlink_param_unregister_one(struct devlink *devlink, 3169 const struct devlink_param *param) 3170{ 3171 struct devlink_param_item *param_item; 3172 3173 param_item = devlink_param_find_by_name(&devlink->param_list, 3174 param->name); 3175 WARN_ON(!param_item); 3176 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_DEL); 3177 list_del(&param_item->list); 3178 kfree(param_item); 3179} 3180 3181static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg, 3182 struct devlink *devlink, 3183 struct devlink_snapshot *snapshot) 3184{ 3185 struct nlattr *snap_attr; 3186 int err; 3187 3188 snap_attr = nla_nest_start(msg, DEVLINK_ATTR_REGION_SNAPSHOT); 3189 if (!snap_attr) 3190 return -EINVAL; 3191 3192 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id); 3193 if (err) 3194 goto nla_put_failure; 3195 3196 nla_nest_end(msg, snap_attr); 3197 return 0; 3198 3199nla_put_failure: 3200 nla_nest_cancel(msg, snap_attr); 3201 return err; 3202} 3203 3204static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg, 3205 struct devlink *devlink, 3206 struct devlink_region *region) 3207{ 3208 struct devlink_snapshot *snapshot; 3209 struct nlattr *snapshots_attr; 3210 int err; 3211 3212 snapshots_attr = nla_nest_start(msg, DEVLINK_ATTR_REGION_SNAPSHOTS); 3213 if (!snapshots_attr) 3214 return -EINVAL; 3215 3216 list_for_each_entry(snapshot, &region->snapshot_list, list) { 3217 err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot); 3218 if (err) 3219 goto nla_put_failure; 3220 } 3221 3222 nla_nest_end(msg, snapshots_attr); 3223 return 0; 3224 3225nla_put_failure: 3226 nla_nest_cancel(msg, snapshots_attr); 3227 return err; 3228} 3229 3230static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink, 3231 enum devlink_command cmd, u32 portid, 3232 u32 seq, int flags, 3233 struct devlink_region *region) 3234{ 3235 void *hdr; 3236 int err; 3237 3238 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 3239 if (!hdr) 3240 return -EMSGSIZE; 3241 3242 err = devlink_nl_put_handle(msg, devlink); 3243 if (err) 3244 goto nla_put_failure; 3245 3246 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->name); 3247 if (err) 3248 goto nla_put_failure; 3249 3250 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE, 3251 region->size, 3252 DEVLINK_ATTR_PAD); 3253 if (err) 3254 goto nla_put_failure; 3255 3256 err = devlink_nl_region_snapshots_id_put(msg, devlink, region); 3257 if (err) 3258 goto nla_put_failure; 3259 3260 genlmsg_end(msg, hdr); 3261 return 0; 3262 3263nla_put_failure: 3264 genlmsg_cancel(msg, hdr); 3265 return err; 3266} 3267 3268static void devlink_nl_region_notify(struct devlink_region *region, 3269 struct devlink_snapshot *snapshot, 3270 enum devlink_command cmd) 3271{ 3272 struct devlink *devlink = region->devlink; 3273 struct sk_buff *msg; 3274 void *hdr; 3275 int err; 3276 3277 WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL); 3278 3279 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3280 if (!msg) 3281 return; 3282 3283 hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd); 3284 if (!hdr) 3285 goto out_free_msg; 3286 3287 err = devlink_nl_put_handle(msg, devlink); 3288 if (err) 3289 goto out_cancel_msg; 3290 3291 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, 3292 region->name); 3293 if (err) 3294 goto out_cancel_msg; 3295 3296 if (snapshot) { 3297 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, 3298 snapshot->id); 3299 if (err) 3300 goto out_cancel_msg; 3301 } else { 3302 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE, 3303 region->size, DEVLINK_ATTR_PAD); 3304 if (err) 3305 goto out_cancel_msg; 3306 } 3307 genlmsg_end(msg, hdr); 3308 3309 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 3310 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 3311 3312 return; 3313 3314out_cancel_msg: 3315 genlmsg_cancel(msg, hdr); 3316out_free_msg: 3317 nlmsg_free(msg); 3318} 3319 3320static int devlink_nl_cmd_region_get_doit(struct sk_buff *skb, 3321 struct genl_info *info) 3322{ 3323 struct devlink *devlink = info->user_ptr[0]; 3324 struct devlink_region *region; 3325 const char *region_name; 3326 struct sk_buff *msg; 3327 int err; 3328 3329 if (!info->attrs[DEVLINK_ATTR_REGION_NAME]) 3330 return -EINVAL; 3331 3332 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 3333 region = devlink_region_get_by_name(devlink, region_name); 3334 if (!region) 3335 return -EINVAL; 3336 3337 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3338 if (!msg) 3339 return -ENOMEM; 3340 3341 err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET, 3342 info->snd_portid, info->snd_seq, 0, 3343 region); 3344 if (err) { 3345 nlmsg_free(msg); 3346 return err; 3347 } 3348 3349 return genlmsg_reply(msg, info); 3350} 3351 3352static int devlink_nl_cmd_region_get_dumpit(struct sk_buff *msg, 3353 struct netlink_callback *cb) 3354{ 3355 struct devlink_region *region; 3356 struct devlink *devlink; 3357 int start = cb->args[0]; 3358 int idx = 0; 3359 int err; 3360 3361 mutex_lock(&devlink_mutex); 3362 list_for_each_entry(devlink, &devlink_list, list) { 3363 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 3364 continue; 3365 3366 mutex_lock(&devlink->lock); 3367 list_for_each_entry(region, &devlink->region_list, list) { 3368 if (idx < start) { 3369 idx++; 3370 continue; 3371 } 3372 err = devlink_nl_region_fill(msg, devlink, 3373 DEVLINK_CMD_REGION_GET, 3374 NETLINK_CB(cb->skb).portid, 3375 cb->nlh->nlmsg_seq, 3376 NLM_F_MULTI, region); 3377 if (err) { 3378 mutex_unlock(&devlink->lock); 3379 goto out; 3380 } 3381 idx++; 3382 } 3383 mutex_unlock(&devlink->lock); 3384 } 3385out: 3386 mutex_unlock(&devlink_mutex); 3387 cb->args[0] = idx; 3388 return msg->len; 3389} 3390 3391static int devlink_nl_cmd_region_del(struct sk_buff *skb, 3392 struct genl_info *info) 3393{ 3394 struct devlink *devlink = info->user_ptr[0]; 3395 struct devlink_snapshot *snapshot; 3396 struct devlink_region *region; 3397 const char *region_name; 3398 u32 snapshot_id; 3399 3400 if (!info->attrs[DEVLINK_ATTR_REGION_NAME] || 3401 !info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) 3402 return -EINVAL; 3403 3404 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 3405 snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); 3406 3407 region = devlink_region_get_by_name(devlink, region_name); 3408 if (!region) 3409 return -EINVAL; 3410 3411 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); 3412 if (!snapshot) 3413 return -EINVAL; 3414 3415 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL); 3416 devlink_region_snapshot_del(snapshot); 3417 return 0; 3418} 3419 3420static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg, 3421 struct devlink *devlink, 3422 u8 *chunk, u32 chunk_size, 3423 u64 addr) 3424{ 3425 struct nlattr *chunk_attr; 3426 int err; 3427 3428 chunk_attr = nla_nest_start(msg, DEVLINK_ATTR_REGION_CHUNK); 3429 if (!chunk_attr) 3430 return -EINVAL; 3431 3432 err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk); 3433 if (err) 3434 goto nla_put_failure; 3435 3436 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr, 3437 DEVLINK_ATTR_PAD); 3438 if (err) 3439 goto nla_put_failure; 3440 3441 nla_nest_end(msg, chunk_attr); 3442 return 0; 3443 3444nla_put_failure: 3445 nla_nest_cancel(msg, chunk_attr); 3446 return err; 3447} 3448 3449#define DEVLINK_REGION_READ_CHUNK_SIZE 256 3450 3451static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb, 3452 struct devlink *devlink, 3453 struct devlink_region *region, 3454 struct nlattr **attrs, 3455 u64 start_offset, 3456 u64 end_offset, 3457 bool dump, 3458 u64 *new_offset) 3459{ 3460 struct devlink_snapshot *snapshot; 3461 u64 curr_offset = start_offset; 3462 u32 snapshot_id; 3463 int err = 0; 3464 3465 *new_offset = start_offset; 3466 3467 snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); 3468 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); 3469 if (!snapshot) 3470 return -EINVAL; 3471 3472 if (end_offset > snapshot->data_len || dump) 3473 end_offset = snapshot->data_len; 3474 3475 while (curr_offset < end_offset) { 3476 u32 data_size; 3477 u8 *data; 3478 3479 if (end_offset - curr_offset < DEVLINK_REGION_READ_CHUNK_SIZE) 3480 data_size = end_offset - curr_offset; 3481 else 3482 data_size = DEVLINK_REGION_READ_CHUNK_SIZE; 3483 3484 data = &snapshot->data[curr_offset]; 3485 err = devlink_nl_cmd_region_read_chunk_fill(skb, devlink, 3486 data, data_size, 3487 curr_offset); 3488 if (err) 3489 break; 3490 3491 curr_offset += data_size; 3492 } 3493 *new_offset = curr_offset; 3494 3495 return err; 3496} 3497 3498static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, 3499 struct netlink_callback *cb) 3500{ 3501 u64 ret_offset, start_offset, end_offset = 0; 3502 struct nlattr *attrs[DEVLINK_ATTR_MAX + 1]; 3503 const struct genl_ops *ops = cb->data; 3504 struct devlink_region *region; 3505 struct nlattr *chunks_attr; 3506 const char *region_name; 3507 struct devlink *devlink; 3508 bool dump = true; 3509 void *hdr; 3510 int err; 3511 3512 start_offset = *((u64 *)&cb->args[0]); 3513 3514 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + devlink_nl_family.hdrsize, 3515 attrs, DEVLINK_ATTR_MAX, ops->policy, cb->extack); 3516 if (err) 3517 goto out; 3518 3519 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs); 3520 if (IS_ERR(devlink)) 3521 goto out; 3522 3523 mutex_lock(&devlink_mutex); 3524 mutex_lock(&devlink->lock); 3525 3526 if (!attrs[DEVLINK_ATTR_REGION_NAME] || 3527 !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) 3528 goto out_unlock; 3529 3530 region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]); 3531 region = devlink_region_get_by_name(devlink, region_name); 3532 if (!region) 3533 goto out_unlock; 3534 3535 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 3536 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, 3537 DEVLINK_CMD_REGION_READ); 3538 if (!hdr) 3539 goto out_unlock; 3540 3541 err = devlink_nl_put_handle(skb, devlink); 3542 if (err) 3543 goto nla_put_failure; 3544 3545 err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name); 3546 if (err) 3547 goto nla_put_failure; 3548 3549 chunks_attr = nla_nest_start(skb, DEVLINK_ATTR_REGION_CHUNKS); 3550 if (!chunks_attr) 3551 goto nla_put_failure; 3552 3553 if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] && 3554 attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) { 3555 if (!start_offset) 3556 start_offset = 3557 nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); 3558 3559 end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); 3560 end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]); 3561 dump = false; 3562 } 3563 3564 err = devlink_nl_region_read_snapshot_fill(skb, devlink, 3565 region, attrs, 3566 start_offset, 3567 end_offset, dump, 3568 &ret_offset); 3569 3570 if (err && err != -EMSGSIZE) 3571 goto nla_put_failure; 3572 3573 /* Check if there was any progress done to prevent infinite loop */ 3574 if (ret_offset == start_offset) 3575 goto nla_put_failure; 3576 3577 *((u64 *)&cb->args[0]) = ret_offset; 3578 3579 nla_nest_end(skb, chunks_attr); 3580 genlmsg_end(skb, hdr); 3581 mutex_unlock(&devlink->lock); 3582 mutex_unlock(&devlink_mutex); 3583 3584 return skb->len; 3585 3586nla_put_failure: 3587 genlmsg_cancel(skb, hdr); 3588out_unlock: 3589 mutex_unlock(&devlink->lock); 3590 mutex_unlock(&devlink_mutex); 3591out: 3592 return 0; 3593} 3594 3595static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { 3596 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING }, 3597 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING }, 3598 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 }, 3599 [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 }, 3600 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 }, 3601 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 }, 3602 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 }, 3603 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 }, 3604 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 }, 3605 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 }, 3606 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 }, 3607 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 }, 3608 [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 }, 3609 [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 }, 3610 [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 }, 3611 [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING }, 3612 [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 }, 3613 [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64}, 3614 [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64}, 3615 [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING }, 3616 [DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 }, 3617 [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 }, 3618 [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING }, 3619 [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 }, 3620}; 3621 3622static const struct genl_ops devlink_nl_ops[] = { 3623 { 3624 .cmd = DEVLINK_CMD_GET, 3625 .doit = devlink_nl_cmd_get_doit, 3626 .dumpit = devlink_nl_cmd_get_dumpit, 3627 .policy = devlink_nl_policy, 3628 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3629 /* can be retrieved by unprivileged users */ 3630 }, 3631 { 3632 .cmd = DEVLINK_CMD_PORT_GET, 3633 .doit = devlink_nl_cmd_port_get_doit, 3634 .dumpit = devlink_nl_cmd_port_get_dumpit, 3635 .policy = devlink_nl_policy, 3636 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 3637 /* can be retrieved by unprivileged users */ 3638 }, 3639 { 3640 .cmd = DEVLINK_CMD_PORT_SET, 3641 .doit = devlink_nl_cmd_port_set_doit, 3642 .policy = devlink_nl_policy, 3643 .flags = GENL_ADMIN_PERM, 3644 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 3645 }, 3646 { 3647 .cmd = DEVLINK_CMD_PORT_SPLIT, 3648 .doit = devlink_nl_cmd_port_split_doit, 3649 .policy = devlink_nl_policy, 3650 .flags = GENL_ADMIN_PERM, 3651 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3652 DEVLINK_NL_FLAG_NO_LOCK, 3653 }, 3654 { 3655 .cmd = DEVLINK_CMD_PORT_UNSPLIT, 3656 .doit = devlink_nl_cmd_port_unsplit_doit, 3657 .policy = devlink_nl_policy, 3658 .flags = GENL_ADMIN_PERM, 3659 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3660 DEVLINK_NL_FLAG_NO_LOCK, 3661 }, 3662 { 3663 .cmd = DEVLINK_CMD_SB_GET, 3664 .doit = devlink_nl_cmd_sb_get_doit, 3665 .dumpit = devlink_nl_cmd_sb_get_dumpit, 3666 .policy = devlink_nl_policy, 3667 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3668 DEVLINK_NL_FLAG_NEED_SB, 3669 /* can be retrieved by unprivileged users */ 3670 }, 3671 { 3672 .cmd = DEVLINK_CMD_SB_POOL_GET, 3673 .doit = devlink_nl_cmd_sb_pool_get_doit, 3674 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit, 3675 .policy = devlink_nl_policy, 3676 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3677 DEVLINK_NL_FLAG_NEED_SB, 3678 /* can be retrieved by unprivileged users */ 3679 }, 3680 { 3681 .cmd = DEVLINK_CMD_SB_POOL_SET, 3682 .doit = devlink_nl_cmd_sb_pool_set_doit, 3683 .policy = devlink_nl_policy, 3684 .flags = GENL_ADMIN_PERM, 3685 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3686 DEVLINK_NL_FLAG_NEED_SB, 3687 }, 3688 { 3689 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET, 3690 .doit = devlink_nl_cmd_sb_port_pool_get_doit, 3691 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit, 3692 .policy = devlink_nl_policy, 3693 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 3694 DEVLINK_NL_FLAG_NEED_SB, 3695 /* can be retrieved by unprivileged users */ 3696 }, 3697 { 3698 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET, 3699 .doit = devlink_nl_cmd_sb_port_pool_set_doit, 3700 .policy = devlink_nl_policy, 3701 .flags = GENL_ADMIN_PERM, 3702 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 3703 DEVLINK_NL_FLAG_NEED_SB, 3704 }, 3705 { 3706 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET, 3707 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit, 3708 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit, 3709 .policy = devlink_nl_policy, 3710 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 3711 DEVLINK_NL_FLAG_NEED_SB, 3712 /* can be retrieved by unprivileged users */ 3713 }, 3714 { 3715 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET, 3716 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit, 3717 .policy = devlink_nl_policy, 3718 .flags = GENL_ADMIN_PERM, 3719 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 3720 DEVLINK_NL_FLAG_NEED_SB, 3721 }, 3722 { 3723 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT, 3724 .doit = devlink_nl_cmd_sb_occ_snapshot_doit, 3725 .policy = devlink_nl_policy, 3726 .flags = GENL_ADMIN_PERM, 3727 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3728 DEVLINK_NL_FLAG_NEED_SB, 3729 }, 3730 { 3731 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR, 3732 .doit = devlink_nl_cmd_sb_occ_max_clear_doit, 3733 .policy = devlink_nl_policy, 3734 .flags = GENL_ADMIN_PERM, 3735 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3736 DEVLINK_NL_FLAG_NEED_SB, 3737 }, 3738 { 3739 .cmd = DEVLINK_CMD_ESWITCH_GET, 3740 .doit = devlink_nl_cmd_eswitch_get_doit, 3741 .policy = devlink_nl_policy, 3742 .flags = GENL_ADMIN_PERM, 3743 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3744 }, 3745 { 3746 .cmd = DEVLINK_CMD_ESWITCH_SET, 3747 .doit = devlink_nl_cmd_eswitch_set_doit, 3748 .policy = devlink_nl_policy, 3749 .flags = GENL_ADMIN_PERM, 3750 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3751 DEVLINK_NL_FLAG_NO_LOCK, 3752 }, 3753 { 3754 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET, 3755 .doit = devlink_nl_cmd_dpipe_table_get, 3756 .policy = devlink_nl_policy, 3757 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3758 /* can be retrieved by unprivileged users */ 3759 }, 3760 { 3761 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET, 3762 .doit = devlink_nl_cmd_dpipe_entries_get, 3763 .policy = devlink_nl_policy, 3764 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3765 /* can be retrieved by unprivileged users */ 3766 }, 3767 { 3768 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET, 3769 .doit = devlink_nl_cmd_dpipe_headers_get, 3770 .policy = devlink_nl_policy, 3771 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3772 /* can be retrieved by unprivileged users */ 3773 }, 3774 { 3775 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET, 3776 .doit = devlink_nl_cmd_dpipe_table_counters_set, 3777 .policy = devlink_nl_policy, 3778 .flags = GENL_ADMIN_PERM, 3779 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3780 }, 3781 { 3782 .cmd = DEVLINK_CMD_RESOURCE_SET, 3783 .doit = devlink_nl_cmd_resource_set, 3784 .policy = devlink_nl_policy, 3785 .flags = GENL_ADMIN_PERM, 3786 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3787 }, 3788 { 3789 .cmd = DEVLINK_CMD_RESOURCE_DUMP, 3790 .doit = devlink_nl_cmd_resource_dump, 3791 .policy = devlink_nl_policy, 3792 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3793 /* can be retrieved by unprivileged users */ 3794 }, 3795 { 3796 .cmd = DEVLINK_CMD_RELOAD, 3797 .doit = devlink_nl_cmd_reload, 3798 .policy = devlink_nl_policy, 3799 .flags = GENL_ADMIN_PERM, 3800 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3801 DEVLINK_NL_FLAG_NO_LOCK, 3802 }, 3803 { 3804 .cmd = DEVLINK_CMD_PARAM_GET, 3805 .doit = devlink_nl_cmd_param_get_doit, 3806 .dumpit = devlink_nl_cmd_param_get_dumpit, 3807 .policy = devlink_nl_policy, 3808 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3809 /* can be retrieved by unprivileged users */ 3810 }, 3811 { 3812 .cmd = DEVLINK_CMD_PARAM_SET, 3813 .doit = devlink_nl_cmd_param_set_doit, 3814 .policy = devlink_nl_policy, 3815 .flags = GENL_ADMIN_PERM, 3816 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3817 }, 3818 { 3819 .cmd = DEVLINK_CMD_REGION_GET, 3820 .doit = devlink_nl_cmd_region_get_doit, 3821 .dumpit = devlink_nl_cmd_region_get_dumpit, 3822 .policy = devlink_nl_policy, 3823 .flags = GENL_ADMIN_PERM, 3824 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3825 }, 3826 { 3827 .cmd = DEVLINK_CMD_REGION_DEL, 3828 .doit = devlink_nl_cmd_region_del, 3829 .policy = devlink_nl_policy, 3830 .flags = GENL_ADMIN_PERM, 3831 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3832 }, 3833 { 3834 .cmd = DEVLINK_CMD_REGION_READ, 3835 .dumpit = devlink_nl_cmd_region_read_dumpit, 3836 .policy = devlink_nl_policy, 3837 .flags = GENL_ADMIN_PERM, 3838 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3839 }, 3840}; 3841 3842static struct genl_family devlink_nl_family __ro_after_init = { 3843 .name = DEVLINK_GENL_NAME, 3844 .version = DEVLINK_GENL_VERSION, 3845 .maxattr = DEVLINK_ATTR_MAX, 3846 .netnsok = true, 3847 .pre_doit = devlink_nl_pre_doit, 3848 .post_doit = devlink_nl_post_doit, 3849 .module = THIS_MODULE, 3850 .ops = devlink_nl_ops, 3851 .n_ops = ARRAY_SIZE(devlink_nl_ops), 3852 .mcgrps = devlink_nl_mcgrps, 3853 .n_mcgrps = ARRAY_SIZE(devlink_nl_mcgrps), 3854}; 3855 3856/** 3857 * devlink_alloc - Allocate new devlink instance resources 3858 * 3859 * @ops: ops 3860 * @priv_size: size of user private data 3861 * 3862 * Allocate new devlink instance resources, including devlink index 3863 * and name. 3864 */ 3865struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size) 3866{ 3867 struct devlink *devlink; 3868 3869 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL); 3870 if (!devlink) 3871 return NULL; 3872 devlink->ops = ops; 3873 devlink_net_set(devlink, &init_net); 3874 INIT_LIST_HEAD(&devlink->port_list); 3875 INIT_LIST_HEAD(&devlink->sb_list); 3876 INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list); 3877 INIT_LIST_HEAD(&devlink->resource_list); 3878 INIT_LIST_HEAD(&devlink->param_list); 3879 INIT_LIST_HEAD(&devlink->region_list); 3880 mutex_init(&devlink->lock); 3881 return devlink; 3882} 3883EXPORT_SYMBOL_GPL(devlink_alloc); 3884 3885/** 3886 * devlink_register - Register devlink instance 3887 * 3888 * @devlink: devlink 3889 */ 3890int devlink_register(struct devlink *devlink, struct device *dev) 3891{ 3892 mutex_lock(&devlink_mutex); 3893 devlink->dev = dev; 3894 list_add_tail(&devlink->list, &devlink_list); 3895 devlink_notify(devlink, DEVLINK_CMD_NEW); 3896 mutex_unlock(&devlink_mutex); 3897 return 0; 3898} 3899EXPORT_SYMBOL_GPL(devlink_register); 3900 3901/** 3902 * devlink_unregister - Unregister devlink instance 3903 * 3904 * @devlink: devlink 3905 */ 3906void devlink_unregister(struct devlink *devlink) 3907{ 3908 mutex_lock(&devlink_mutex); 3909 devlink_notify(devlink, DEVLINK_CMD_DEL); 3910 list_del(&devlink->list); 3911 mutex_unlock(&devlink_mutex); 3912} 3913EXPORT_SYMBOL_GPL(devlink_unregister); 3914 3915/** 3916 * devlink_free - Free devlink instance resources 3917 * 3918 * @devlink: devlink 3919 */ 3920void devlink_free(struct devlink *devlink) 3921{ 3922 kfree(devlink); 3923} 3924EXPORT_SYMBOL_GPL(devlink_free); 3925 3926/** 3927 * devlink_port_register - Register devlink port 3928 * 3929 * @devlink: devlink 3930 * @devlink_port: devlink port 3931 * @port_index 3932 * 3933 * Register devlink port with provided port index. User can use 3934 * any indexing, even hw-related one. devlink_port structure 3935 * is convenient to be embedded inside user driver private structure. 3936 * Note that the caller should take care of zeroing the devlink_port 3937 * structure. 3938 */ 3939int devlink_port_register(struct devlink *devlink, 3940 struct devlink_port *devlink_port, 3941 unsigned int port_index) 3942{ 3943 mutex_lock(&devlink->lock); 3944 if (devlink_port_index_exists(devlink, port_index)) { 3945 mutex_unlock(&devlink->lock); 3946 return -EEXIST; 3947 } 3948 devlink_port->devlink = devlink; 3949 devlink_port->index = port_index; 3950 devlink_port->registered = true; 3951 list_add_tail(&devlink_port->list, &devlink->port_list); 3952 mutex_unlock(&devlink->lock); 3953 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 3954 return 0; 3955} 3956EXPORT_SYMBOL_GPL(devlink_port_register); 3957 3958/** 3959 * devlink_port_unregister - Unregister devlink port 3960 * 3961 * @devlink_port: devlink port 3962 */ 3963void devlink_port_unregister(struct devlink_port *devlink_port) 3964{ 3965 struct devlink *devlink = devlink_port->devlink; 3966 3967 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL); 3968 mutex_lock(&devlink->lock); 3969 list_del(&devlink_port->list); 3970 mutex_unlock(&devlink->lock); 3971} 3972EXPORT_SYMBOL_GPL(devlink_port_unregister); 3973 3974static void __devlink_port_type_set(struct devlink_port *devlink_port, 3975 enum devlink_port_type type, 3976 void *type_dev) 3977{ 3978 devlink_port->type = type; 3979 devlink_port->type_dev = type_dev; 3980 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 3981} 3982 3983/** 3984 * devlink_port_type_eth_set - Set port type to Ethernet 3985 * 3986 * @devlink_port: devlink port 3987 * @netdev: related netdevice 3988 */ 3989void devlink_port_type_eth_set(struct devlink_port *devlink_port, 3990 struct net_device *netdev) 3991{ 3992 return __devlink_port_type_set(devlink_port, 3993 DEVLINK_PORT_TYPE_ETH, netdev); 3994} 3995EXPORT_SYMBOL_GPL(devlink_port_type_eth_set); 3996 3997/** 3998 * devlink_port_type_ib_set - Set port type to InfiniBand 3999 * 4000 * @devlink_port: devlink port 4001 * @ibdev: related IB device 4002 */ 4003void devlink_port_type_ib_set(struct devlink_port *devlink_port, 4004 struct ib_device *ibdev) 4005{ 4006 return __devlink_port_type_set(devlink_port, 4007 DEVLINK_PORT_TYPE_IB, ibdev); 4008} 4009EXPORT_SYMBOL_GPL(devlink_port_type_ib_set); 4010 4011/** 4012 * devlink_port_type_clear - Clear port type 4013 * 4014 * @devlink_port: devlink port 4015 */ 4016void devlink_port_type_clear(struct devlink_port *devlink_port) 4017{ 4018 return __devlink_port_type_set(devlink_port, 4019 DEVLINK_PORT_TYPE_NOTSET, NULL); 4020} 4021EXPORT_SYMBOL_GPL(devlink_port_type_clear); 4022 4023/** 4024 * devlink_port_attrs_set - Set port attributes 4025 * 4026 * @devlink_port: devlink port 4027 * @flavour: flavour of the port 4028 * @port_number: number of the port that is facing user, for example 4029 * the front panel port number 4030 * @split: indicates if this is split port 4031 * @split_subport_number: if the port is split, this is the number 4032 * of subport. 4033 */ 4034void devlink_port_attrs_set(struct devlink_port *devlink_port, 4035 enum devlink_port_flavour flavour, 4036 u32 port_number, bool split, 4037 u32 split_subport_number) 4038{ 4039 struct devlink_port_attrs *attrs = &devlink_port->attrs; 4040 4041 attrs->set = true; 4042 attrs->flavour = flavour; 4043 attrs->port_number = port_number; 4044 attrs->split = split; 4045 attrs->split_subport_number = split_subport_number; 4046 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 4047} 4048EXPORT_SYMBOL_GPL(devlink_port_attrs_set); 4049 4050int devlink_port_get_phys_port_name(struct devlink_port *devlink_port, 4051 char *name, size_t len) 4052{ 4053 struct devlink_port_attrs *attrs = &devlink_port->attrs; 4054 int n = 0; 4055 4056 if (!attrs->set) 4057 return -EOPNOTSUPP; 4058 4059 switch (attrs->flavour) { 4060 case DEVLINK_PORT_FLAVOUR_PHYSICAL: 4061 if (!attrs->split) 4062 n = snprintf(name, len, "p%u", attrs->port_number); 4063 else 4064 n = snprintf(name, len, "p%us%u", attrs->port_number, 4065 attrs->split_subport_number); 4066 break; 4067 case DEVLINK_PORT_FLAVOUR_CPU: 4068 case DEVLINK_PORT_FLAVOUR_DSA: 4069 /* As CPU and DSA ports do not have a netdevice associated 4070 * case should not ever happen. 4071 */ 4072 WARN_ON(1); 4073 return -EINVAL; 4074 } 4075 4076 if (n >= len) 4077 return -EINVAL; 4078 4079 return 0; 4080} 4081EXPORT_SYMBOL_GPL(devlink_port_get_phys_port_name); 4082 4083int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, 4084 u32 size, u16 ingress_pools_count, 4085 u16 egress_pools_count, u16 ingress_tc_count, 4086 u16 egress_tc_count) 4087{ 4088 struct devlink_sb *devlink_sb; 4089 int err = 0; 4090 4091 mutex_lock(&devlink->lock); 4092 if (devlink_sb_index_exists(devlink, sb_index)) { 4093 err = -EEXIST; 4094 goto unlock; 4095 } 4096 4097 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL); 4098 if (!devlink_sb) { 4099 err = -ENOMEM; 4100 goto unlock; 4101 } 4102 devlink_sb->index = sb_index; 4103 devlink_sb->size = size; 4104 devlink_sb->ingress_pools_count = ingress_pools_count; 4105 devlink_sb->egress_pools_count = egress_pools_count; 4106 devlink_sb->ingress_tc_count = ingress_tc_count; 4107 devlink_sb->egress_tc_count = egress_tc_count; 4108 list_add_tail(&devlink_sb->list, &devlink->sb_list); 4109unlock: 4110 mutex_unlock(&devlink->lock); 4111 return err; 4112} 4113EXPORT_SYMBOL_GPL(devlink_sb_register); 4114 4115void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index) 4116{ 4117 struct devlink_sb *devlink_sb; 4118 4119 mutex_lock(&devlink->lock); 4120 devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 4121 WARN_ON(!devlink_sb); 4122 list_del(&devlink_sb->list); 4123 mutex_unlock(&devlink->lock); 4124 kfree(devlink_sb); 4125} 4126EXPORT_SYMBOL_GPL(devlink_sb_unregister); 4127 4128/** 4129 * devlink_dpipe_headers_register - register dpipe headers 4130 * 4131 * @devlink: devlink 4132 * @dpipe_headers: dpipe header array 4133 * 4134 * Register the headers supported by hardware. 4135 */ 4136int devlink_dpipe_headers_register(struct devlink *devlink, 4137 struct devlink_dpipe_headers *dpipe_headers) 4138{ 4139 mutex_lock(&devlink->lock); 4140 devlink->dpipe_headers = dpipe_headers; 4141 mutex_unlock(&devlink->lock); 4142 return 0; 4143} 4144EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register); 4145 4146/** 4147 * devlink_dpipe_headers_unregister - unregister dpipe headers 4148 * 4149 * @devlink: devlink 4150 * 4151 * Unregister the headers supported by hardware. 4152 */ 4153void devlink_dpipe_headers_unregister(struct devlink *devlink) 4154{ 4155 mutex_lock(&devlink->lock); 4156 devlink->dpipe_headers = NULL; 4157 mutex_unlock(&devlink->lock); 4158} 4159EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister); 4160 4161/** 4162 * devlink_dpipe_table_counter_enabled - check if counter allocation 4163 * required 4164 * @devlink: devlink 4165 * @table_name: tables name 4166 * 4167 * Used by driver to check if counter allocation is required. 4168 * After counter allocation is turned on the table entries 4169 * are updated to include counter statistics. 4170 * 4171 * After that point on the driver must respect the counter 4172 * state so that each entry added to the table is added 4173 * with a counter. 4174 */ 4175bool devlink_dpipe_table_counter_enabled(struct devlink *devlink, 4176 const char *table_name) 4177{ 4178 struct devlink_dpipe_table *table; 4179 bool enabled; 4180 4181 rcu_read_lock(); 4182 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 4183 table_name); 4184 enabled = false; 4185 if (table) 4186 enabled = table->counters_enabled; 4187 rcu_read_unlock(); 4188 return enabled; 4189} 4190EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled); 4191 4192/** 4193 * devlink_dpipe_table_register - register dpipe table 4194 * 4195 * @devlink: devlink 4196 * @table_name: table name 4197 * @table_ops: table ops 4198 * @priv: priv 4199 * @counter_control_extern: external control for counters 4200 */ 4201int devlink_dpipe_table_register(struct devlink *devlink, 4202 const char *table_name, 4203 struct devlink_dpipe_table_ops *table_ops, 4204 void *priv, bool counter_control_extern) 4205{ 4206 struct devlink_dpipe_table *table; 4207 4208 if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name)) 4209 return -EEXIST; 4210 4211 if (WARN_ON(!table_ops->size_get)) 4212 return -EINVAL; 4213 4214 table = kzalloc(sizeof(*table), GFP_KERNEL); 4215 if (!table) 4216 return -ENOMEM; 4217 4218 table->name = table_name; 4219 table->table_ops = table_ops; 4220 table->priv = priv; 4221 table->counter_control_extern = counter_control_extern; 4222 4223 mutex_lock(&devlink->lock); 4224 list_add_tail_rcu(&table->list, &devlink->dpipe_table_list); 4225 mutex_unlock(&devlink->lock); 4226 return 0; 4227} 4228EXPORT_SYMBOL_GPL(devlink_dpipe_table_register); 4229 4230/** 4231 * devlink_dpipe_table_unregister - unregister dpipe table 4232 * 4233 * @devlink: devlink 4234 * @table_name: table name 4235 */ 4236void devlink_dpipe_table_unregister(struct devlink *devlink, 4237 const char *table_name) 4238{ 4239 struct devlink_dpipe_table *table; 4240 4241 mutex_lock(&devlink->lock); 4242 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 4243 table_name); 4244 if (!table) 4245 goto unlock; 4246 list_del_rcu(&table->list); 4247 mutex_unlock(&devlink->lock); 4248 kfree_rcu(table, rcu); 4249 return; 4250unlock: 4251 mutex_unlock(&devlink->lock); 4252} 4253EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister); 4254 4255/** 4256 * devlink_resource_register - devlink resource register 4257 * 4258 * @devlink: devlink 4259 * @resource_name: resource's name 4260 * @top_hierarchy: top hierarchy 4261 * @reload_required: reload is required for new configuration to 4262 * apply 4263 * @resource_size: resource's size 4264 * @resource_id: resource's id 4265 * @parent_reosurce_id: resource's parent id 4266 * @size params: size parameters 4267 */ 4268int devlink_resource_register(struct devlink *devlink, 4269 const char *resource_name, 4270 u64 resource_size, 4271 u64 resource_id, 4272 u64 parent_resource_id, 4273 const struct devlink_resource_size_params *size_params) 4274{ 4275 struct devlink_resource *resource; 4276 struct list_head *resource_list; 4277 bool top_hierarchy; 4278 int err = 0; 4279 4280 top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP; 4281 4282 mutex_lock(&devlink->lock); 4283 resource = devlink_resource_find(devlink, NULL, resource_id); 4284 if (resource) { 4285 err = -EINVAL; 4286 goto out; 4287 } 4288 4289 resource = kzalloc(sizeof(*resource), GFP_KERNEL); 4290 if (!resource) { 4291 err = -ENOMEM; 4292 goto out; 4293 } 4294 4295 if (top_hierarchy) { 4296 resource_list = &devlink->resource_list; 4297 } else { 4298 struct devlink_resource *parent_resource; 4299 4300 parent_resource = devlink_resource_find(devlink, NULL, 4301 parent_resource_id); 4302 if (parent_resource) { 4303 resource_list = &parent_resource->resource_list; 4304 resource->parent = parent_resource; 4305 } else { 4306 kfree(resource); 4307 err = -EINVAL; 4308 goto out; 4309 } 4310 } 4311 4312 resource->name = resource_name; 4313 resource->size = resource_size; 4314 resource->size_new = resource_size; 4315 resource->id = resource_id; 4316 resource->size_valid = true; 4317 memcpy(&resource->size_params, size_params, 4318 sizeof(resource->size_params)); 4319 INIT_LIST_HEAD(&resource->resource_list); 4320 list_add_tail(&resource->list, resource_list); 4321out: 4322 mutex_unlock(&devlink->lock); 4323 return err; 4324} 4325EXPORT_SYMBOL_GPL(devlink_resource_register); 4326 4327/** 4328 * devlink_resources_unregister - free all resources 4329 * 4330 * @devlink: devlink 4331 * @resource: resource 4332 */ 4333void devlink_resources_unregister(struct devlink *devlink, 4334 struct devlink_resource *resource) 4335{ 4336 struct devlink_resource *tmp, *child_resource; 4337 struct list_head *resource_list; 4338 4339 if (resource) 4340 resource_list = &resource->resource_list; 4341 else 4342 resource_list = &devlink->resource_list; 4343 4344 if (!resource) 4345 mutex_lock(&devlink->lock); 4346 4347 list_for_each_entry_safe(child_resource, tmp, resource_list, list) { 4348 devlink_resources_unregister(devlink, child_resource); 4349 list_del(&child_resource->list); 4350 kfree(child_resource); 4351 } 4352 4353 if (!resource) 4354 mutex_unlock(&devlink->lock); 4355} 4356EXPORT_SYMBOL_GPL(devlink_resources_unregister); 4357 4358/** 4359 * devlink_resource_size_get - get and update size 4360 * 4361 * @devlink: devlink 4362 * @resource_id: the requested resource id 4363 * @p_resource_size: ptr to update 4364 */ 4365int devlink_resource_size_get(struct devlink *devlink, 4366 u64 resource_id, 4367 u64 *p_resource_size) 4368{ 4369 struct devlink_resource *resource; 4370 int err = 0; 4371 4372 mutex_lock(&devlink->lock); 4373 resource = devlink_resource_find(devlink, NULL, resource_id); 4374 if (!resource) { 4375 err = -EINVAL; 4376 goto out; 4377 } 4378 *p_resource_size = resource->size_new; 4379 resource->size = resource->size_new; 4380out: 4381 mutex_unlock(&devlink->lock); 4382 return err; 4383} 4384EXPORT_SYMBOL_GPL(devlink_resource_size_get); 4385 4386/** 4387 * devlink_dpipe_table_resource_set - set the resource id 4388 * 4389 * @devlink: devlink 4390 * @table_name: table name 4391 * @resource_id: resource id 4392 * @resource_units: number of resource's units consumed per table's entry 4393 */ 4394int devlink_dpipe_table_resource_set(struct devlink *devlink, 4395 const char *table_name, u64 resource_id, 4396 u64 resource_units) 4397{ 4398 struct devlink_dpipe_table *table; 4399 int err = 0; 4400 4401 mutex_lock(&devlink->lock); 4402 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 4403 table_name); 4404 if (!table) { 4405 err = -EINVAL; 4406 goto out; 4407 } 4408 table->resource_id = resource_id; 4409 table->resource_units = resource_units; 4410 table->resource_valid = true; 4411out: 4412 mutex_unlock(&devlink->lock); 4413 return err; 4414} 4415EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set); 4416 4417/** 4418 * devlink_resource_occ_get_register - register occupancy getter 4419 * 4420 * @devlink: devlink 4421 * @resource_id: resource id 4422 * @occ_get: occupancy getter callback 4423 * @occ_get_priv: occupancy getter callback priv 4424 */ 4425void devlink_resource_occ_get_register(struct devlink *devlink, 4426 u64 resource_id, 4427 devlink_resource_occ_get_t *occ_get, 4428 void *occ_get_priv) 4429{ 4430 struct devlink_resource *resource; 4431 4432 mutex_lock(&devlink->lock); 4433 resource = devlink_resource_find(devlink, NULL, resource_id); 4434 if (WARN_ON(!resource)) 4435 goto out; 4436 WARN_ON(resource->occ_get); 4437 4438 resource->occ_get = occ_get; 4439 resource->occ_get_priv = occ_get_priv; 4440out: 4441 mutex_unlock(&devlink->lock); 4442} 4443EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register); 4444 4445/** 4446 * devlink_resource_occ_get_unregister - unregister occupancy getter 4447 * 4448 * @devlink: devlink 4449 * @resource_id: resource id 4450 */ 4451void devlink_resource_occ_get_unregister(struct devlink *devlink, 4452 u64 resource_id) 4453{ 4454 struct devlink_resource *resource; 4455 4456 mutex_lock(&devlink->lock); 4457 resource = devlink_resource_find(devlink, NULL, resource_id); 4458 if (WARN_ON(!resource)) 4459 goto out; 4460 WARN_ON(!resource->occ_get); 4461 4462 resource->occ_get = NULL; 4463 resource->occ_get_priv = NULL; 4464out: 4465 mutex_unlock(&devlink->lock); 4466} 4467EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister); 4468 4469/** 4470 * devlink_params_register - register configuration parameters 4471 * 4472 * @devlink: devlink 4473 * @params: configuration parameters array 4474 * @params_count: number of parameters provided 4475 * 4476 * Register the configuration parameters supported by the driver. 4477 */ 4478int devlink_params_register(struct devlink *devlink, 4479 const struct devlink_param *params, 4480 size_t params_count) 4481{ 4482 const struct devlink_param *param = params; 4483 int i; 4484 int err; 4485 4486 mutex_lock(&devlink->lock); 4487 for (i = 0; i < params_count; i++, param++) { 4488 if (!param || !param->name || !param->supported_cmodes) { 4489 err = -EINVAL; 4490 goto rollback; 4491 } 4492 if (param->generic) { 4493 err = devlink_param_generic_verify(param); 4494 if (err) 4495 goto rollback; 4496 } else { 4497 err = devlink_param_driver_verify(param); 4498 if (err) 4499 goto rollback; 4500 } 4501 err = devlink_param_register_one(devlink, param); 4502 if (err) 4503 goto rollback; 4504 } 4505 4506 mutex_unlock(&devlink->lock); 4507 return 0; 4508 4509rollback: 4510 if (!i) 4511 goto unlock; 4512 for (param--; i > 0; i--, param--) 4513 devlink_param_unregister_one(devlink, param); 4514unlock: 4515 mutex_unlock(&devlink->lock); 4516 return err; 4517} 4518EXPORT_SYMBOL_GPL(devlink_params_register); 4519 4520/** 4521 * devlink_params_unregister - unregister configuration parameters 4522 * @devlink: devlink 4523 * @params: configuration parameters to unregister 4524 * @params_count: number of parameters provided 4525 */ 4526void devlink_params_unregister(struct devlink *devlink, 4527 const struct devlink_param *params, 4528 size_t params_count) 4529{ 4530 const struct devlink_param *param = params; 4531 int i; 4532 4533 mutex_lock(&devlink->lock); 4534 for (i = 0; i < params_count; i++, param++) 4535 devlink_param_unregister_one(devlink, param); 4536 mutex_unlock(&devlink->lock); 4537} 4538EXPORT_SYMBOL_GPL(devlink_params_unregister); 4539 4540/** 4541 * devlink_param_driverinit_value_get - get configuration parameter 4542 * value for driver initializing 4543 * 4544 * @devlink: devlink 4545 * @param_id: parameter ID 4546 * @init_val: value of parameter in driverinit configuration mode 4547 * 4548 * This function should be used by the driver to get driverinit 4549 * configuration for initialization after reload command. 4550 */ 4551int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id, 4552 union devlink_param_value *init_val) 4553{ 4554 struct devlink_param_item *param_item; 4555 4556 if (!devlink->ops || !devlink->ops->reload) 4557 return -EOPNOTSUPP; 4558 4559 param_item = devlink_param_find_by_id(&devlink->param_list, param_id); 4560 if (!param_item) 4561 return -EINVAL; 4562 4563 if (!param_item->driverinit_value_valid || 4564 !devlink_param_cmode_is_supported(param_item->param, 4565 DEVLINK_PARAM_CMODE_DRIVERINIT)) 4566 return -EOPNOTSUPP; 4567 4568 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING) 4569 strcpy(init_val->vstr, param_item->driverinit_value.vstr); 4570 else 4571 *init_val = param_item->driverinit_value; 4572 4573 return 0; 4574} 4575EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_get); 4576 4577/** 4578 * devlink_param_driverinit_value_set - set value of configuration 4579 * parameter for driverinit 4580 * configuration mode 4581 * 4582 * @devlink: devlink 4583 * @param_id: parameter ID 4584 * @init_val: value of parameter to set for driverinit configuration mode 4585 * 4586 * This function should be used by the driver to set driverinit 4587 * configuration mode default value. 4588 */ 4589int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id, 4590 union devlink_param_value init_val) 4591{ 4592 struct devlink_param_item *param_item; 4593 4594 param_item = devlink_param_find_by_id(&devlink->param_list, param_id); 4595 if (!param_item) 4596 return -EINVAL; 4597 4598 if (!devlink_param_cmode_is_supported(param_item->param, 4599 DEVLINK_PARAM_CMODE_DRIVERINIT)) 4600 return -EOPNOTSUPP; 4601 4602 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING) 4603 strcpy(param_item->driverinit_value.vstr, init_val.vstr); 4604 else 4605 param_item->driverinit_value = init_val; 4606 param_item->driverinit_value_valid = true; 4607 4608 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW); 4609 return 0; 4610} 4611EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_set); 4612 4613/** 4614 * devlink_param_value_changed - notify devlink on a parameter's value 4615 * change. Should be called by the driver 4616 * right after the change. 4617 * 4618 * @devlink: devlink 4619 * @param_id: parameter ID 4620 * 4621 * This function should be used by the driver to notify devlink on value 4622 * change, excluding driverinit configuration mode. 4623 * For driverinit configuration mode driver should use the function 4624 * devlink_param_driverinit_value_set() instead. 4625 */ 4626void devlink_param_value_changed(struct devlink *devlink, u32 param_id) 4627{ 4628 struct devlink_param_item *param_item; 4629 4630 param_item = devlink_param_find_by_id(&devlink->param_list, param_id); 4631 WARN_ON(!param_item); 4632 4633 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW); 4634} 4635EXPORT_SYMBOL_GPL(devlink_param_value_changed); 4636 4637/** 4638 * devlink_param_value_str_fill - Safely fill-up the string preventing 4639 * from overflow of the preallocated buffer 4640 * 4641 * @dst_val: destination devlink_param_value 4642 * @src: source buffer 4643 */ 4644void devlink_param_value_str_fill(union devlink_param_value *dst_val, 4645 const char *src) 4646{ 4647 size_t len; 4648 4649 len = strlcpy(dst_val->vstr, src, __DEVLINK_PARAM_MAX_STRING_VALUE); 4650 WARN_ON(len >= __DEVLINK_PARAM_MAX_STRING_VALUE); 4651} 4652EXPORT_SYMBOL_GPL(devlink_param_value_str_fill); 4653 4654/** 4655 * devlink_region_create - create a new address region 4656 * 4657 * @devlink: devlink 4658 * @region_name: region name 4659 * @region_max_snapshots: Maximum supported number of snapshots for region 4660 * @region_size: size of region 4661 */ 4662struct devlink_region *devlink_region_create(struct devlink *devlink, 4663 const char *region_name, 4664 u32 region_max_snapshots, 4665 u64 region_size) 4666{ 4667 struct devlink_region *region; 4668 int err = 0; 4669 4670 mutex_lock(&devlink->lock); 4671 4672 if (devlink_region_get_by_name(devlink, region_name)) { 4673 err = -EEXIST; 4674 goto unlock; 4675 } 4676 4677 region = kzalloc(sizeof(*region), GFP_KERNEL); 4678 if (!region) { 4679 err = -ENOMEM; 4680 goto unlock; 4681 } 4682 4683 region->devlink = devlink; 4684 region->max_snapshots = region_max_snapshots; 4685 region->name = region_name; 4686 region->size = region_size; 4687 INIT_LIST_HEAD(&region->snapshot_list); 4688 list_add_tail(&region->list, &devlink->region_list); 4689 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW); 4690 4691 mutex_unlock(&devlink->lock); 4692 return region; 4693 4694unlock: 4695 mutex_unlock(&devlink->lock); 4696 return ERR_PTR(err); 4697} 4698EXPORT_SYMBOL_GPL(devlink_region_create); 4699 4700/** 4701 * devlink_region_destroy - destroy address region 4702 * 4703 * @region: devlink region to destroy 4704 */ 4705void devlink_region_destroy(struct devlink_region *region) 4706{ 4707 struct devlink *devlink = region->devlink; 4708 struct devlink_snapshot *snapshot, *ts; 4709 4710 mutex_lock(&devlink->lock); 4711 4712 /* Free all snapshots of region */ 4713 list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list) 4714 devlink_region_snapshot_del(snapshot); 4715 4716 list_del(&region->list); 4717 4718 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL); 4719 mutex_unlock(&devlink->lock); 4720 kfree(region); 4721} 4722EXPORT_SYMBOL_GPL(devlink_region_destroy); 4723 4724/** 4725 * devlink_region_shapshot_id_get - get snapshot ID 4726 * 4727 * This callback should be called when adding a new snapshot, 4728 * Driver should use the same id for multiple snapshots taken 4729 * on multiple regions at the same time/by the same trigger. 4730 * 4731 * @devlink: devlink 4732 */ 4733u32 devlink_region_shapshot_id_get(struct devlink *devlink) 4734{ 4735 u32 id; 4736 4737 mutex_lock(&devlink->lock); 4738 id = ++devlink->snapshot_id; 4739 mutex_unlock(&devlink->lock); 4740 4741 return id; 4742} 4743EXPORT_SYMBOL_GPL(devlink_region_shapshot_id_get); 4744 4745/** 4746 * devlink_region_snapshot_create - create a new snapshot 4747 * This will add a new snapshot of a region. The snapshot 4748 * will be stored on the region struct and can be accessed 4749 * from devlink. This is useful for future analyses of snapshots. 4750 * Multiple snapshots can be created on a region. 4751 * The @snapshot_id should be obtained using the getter function. 4752 * 4753 * @devlink_region: devlink region of the snapshot 4754 * @data_len: size of snapshot data 4755 * @data: snapshot data 4756 * @snapshot_id: snapshot id to be created 4757 * @data_destructor: pointer to destructor function to free data 4758 */ 4759int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len, 4760 u8 *data, u32 snapshot_id, 4761 devlink_snapshot_data_dest_t *data_destructor) 4762{ 4763 struct devlink *devlink = region->devlink; 4764 struct devlink_snapshot *snapshot; 4765 int err; 4766 4767 mutex_lock(&devlink->lock); 4768 4769 /* check if region can hold one more snapshot */ 4770 if (region->cur_snapshots == region->max_snapshots) { 4771 err = -ENOMEM; 4772 goto unlock; 4773 } 4774 4775 if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { 4776 err = -EEXIST; 4777 goto unlock; 4778 } 4779 4780 snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL); 4781 if (!snapshot) { 4782 err = -ENOMEM; 4783 goto unlock; 4784 } 4785 4786 snapshot->id = snapshot_id; 4787 snapshot->region = region; 4788 snapshot->data = data; 4789 snapshot->data_len = data_len; 4790 snapshot->data_destructor = data_destructor; 4791 4792 list_add_tail(&snapshot->list, &region->snapshot_list); 4793 4794 region->cur_snapshots++; 4795 4796 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW); 4797 mutex_unlock(&devlink->lock); 4798 return 0; 4799 4800unlock: 4801 mutex_unlock(&devlink->lock); 4802 return err; 4803} 4804EXPORT_SYMBOL_GPL(devlink_region_snapshot_create); 4805 4806static int __init devlink_module_init(void) 4807{ 4808 return genl_register_family(&devlink_nl_family); 4809} 4810 4811static void __exit devlink_module_exit(void) 4812{ 4813 genl_unregister_family(&devlink_nl_family); 4814} 4815 4816module_init(devlink_module_init); 4817module_exit(devlink_module_exit); 4818 4819MODULE_LICENSE("GPL v2"); 4820MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>"); 4821MODULE_DESCRIPTION("Network physical device Netlink interface"); 4822MODULE_ALIAS_GENL_FAMILY(DEVLINK_GENL_NAME);