at v5.3 182 kB view raw
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * net/core/devlink.c - Network physical/parent device Netlink interface 4 * 5 * Heavily inspired by net/wireless/ 6 * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 7 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 8 */ 9 10#include <linux/kernel.h> 11#include <linux/module.h> 12#include <linux/types.h> 13#include <linux/slab.h> 14#include <linux/gfp.h> 15#include <linux/device.h> 16#include <linux/list.h> 17#include <linux/netdevice.h> 18#include <linux/spinlock.h> 19#include <linux/refcount.h> 20#include <linux/workqueue.h> 21#include <rdma/ib_verbs.h> 22#include <net/netlink.h> 23#include <net/genetlink.h> 24#include <net/rtnetlink.h> 25#include <net/net_namespace.h> 26#include <net/sock.h> 27#include <net/devlink.h> 28#define CREATE_TRACE_POINTS 29#include <trace/events/devlink.h> 30 31static struct devlink_dpipe_field devlink_dpipe_fields_ethernet[] = { 32 { 33 .name = "destination mac", 34 .id = DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC, 35 .bitwidth = 48, 36 }, 37}; 38 39struct devlink_dpipe_header devlink_dpipe_header_ethernet = { 40 .name = "ethernet", 41 .id = DEVLINK_DPIPE_HEADER_ETHERNET, 42 .fields = devlink_dpipe_fields_ethernet, 43 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ethernet), 44 .global = true, 45}; 46EXPORT_SYMBOL(devlink_dpipe_header_ethernet); 47 48static struct devlink_dpipe_field devlink_dpipe_fields_ipv4[] = { 49 { 50 .name = "destination ip", 51 .id = DEVLINK_DPIPE_FIELD_IPV4_DST_IP, 52 .bitwidth = 32, 53 }, 54}; 55 56struct devlink_dpipe_header devlink_dpipe_header_ipv4 = { 57 .name = "ipv4", 58 .id = DEVLINK_DPIPE_HEADER_IPV4, 59 .fields = devlink_dpipe_fields_ipv4, 60 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv4), 61 .global = true, 62}; 63EXPORT_SYMBOL(devlink_dpipe_header_ipv4); 64 65static struct devlink_dpipe_field devlink_dpipe_fields_ipv6[] = { 66 { 67 .name = "destination ip", 68 .id = DEVLINK_DPIPE_FIELD_IPV6_DST_IP, 69 .bitwidth = 128, 70 }, 71}; 72 73struct devlink_dpipe_header devlink_dpipe_header_ipv6 = { 74 .name = "ipv6", 75 .id = DEVLINK_DPIPE_HEADER_IPV6, 76 .fields = devlink_dpipe_fields_ipv6, 77 .fields_count = ARRAY_SIZE(devlink_dpipe_fields_ipv6), 78 .global = true, 79}; 80EXPORT_SYMBOL(devlink_dpipe_header_ipv6); 81 82EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwmsg); 83EXPORT_TRACEPOINT_SYMBOL_GPL(devlink_hwerr); 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 lockdep_assert_held(&devlink_mutex); 119 120 list_for_each_entry(devlink, &devlink_list, list) { 121 if (strcmp(devlink->dev->bus->name, busname) == 0 && 122 strcmp(dev_name(devlink->dev), devname) == 0 && 123 net_eq(devlink_net(devlink), net)) 124 return devlink; 125 } 126 127 return ERR_PTR(-ENODEV); 128} 129 130static struct devlink *devlink_get_from_info(struct genl_info *info) 131{ 132 return devlink_get_from_attrs(genl_info_net(info), info->attrs); 133} 134 135static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink, 136 int port_index) 137{ 138 struct devlink_port *devlink_port; 139 140 list_for_each_entry(devlink_port, &devlink->port_list, list) { 141 if (devlink_port->index == port_index) 142 return devlink_port; 143 } 144 return NULL; 145} 146 147static bool devlink_port_index_exists(struct devlink *devlink, int port_index) 148{ 149 return devlink_port_get_by_index(devlink, port_index); 150} 151 152static struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink, 153 struct nlattr **attrs) 154{ 155 if (attrs[DEVLINK_ATTR_PORT_INDEX]) { 156 u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]); 157 struct devlink_port *devlink_port; 158 159 devlink_port = devlink_port_get_by_index(devlink, port_index); 160 if (!devlink_port) 161 return ERR_PTR(-ENODEV); 162 return devlink_port; 163 } 164 return ERR_PTR(-EINVAL); 165} 166 167static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink, 168 struct genl_info *info) 169{ 170 return devlink_port_get_from_attrs(devlink, info->attrs); 171} 172 173struct devlink_sb { 174 struct list_head list; 175 unsigned int index; 176 u32 size; 177 u16 ingress_pools_count; 178 u16 egress_pools_count; 179 u16 ingress_tc_count; 180 u16 egress_tc_count; 181}; 182 183static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb) 184{ 185 return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count; 186} 187 188static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink, 189 unsigned int sb_index) 190{ 191 struct devlink_sb *devlink_sb; 192 193 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 194 if (devlink_sb->index == sb_index) 195 return devlink_sb; 196 } 197 return NULL; 198} 199 200static bool devlink_sb_index_exists(struct devlink *devlink, 201 unsigned int sb_index) 202{ 203 return devlink_sb_get_by_index(devlink, sb_index); 204} 205 206static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink, 207 struct nlattr **attrs) 208{ 209 if (attrs[DEVLINK_ATTR_SB_INDEX]) { 210 u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]); 211 struct devlink_sb *devlink_sb; 212 213 devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 214 if (!devlink_sb) 215 return ERR_PTR(-ENODEV); 216 return devlink_sb; 217 } 218 return ERR_PTR(-EINVAL); 219} 220 221static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink, 222 struct genl_info *info) 223{ 224 return devlink_sb_get_from_attrs(devlink, info->attrs); 225} 226 227static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb, 228 struct nlattr **attrs, 229 u16 *p_pool_index) 230{ 231 u16 val; 232 233 if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX]) 234 return -EINVAL; 235 236 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]); 237 if (val >= devlink_sb_pool_count(devlink_sb)) 238 return -EINVAL; 239 *p_pool_index = val; 240 return 0; 241} 242 243static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb, 244 struct genl_info *info, 245 u16 *p_pool_index) 246{ 247 return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs, 248 p_pool_index); 249} 250 251static int 252devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs, 253 enum devlink_sb_pool_type *p_pool_type) 254{ 255 u8 val; 256 257 if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE]) 258 return -EINVAL; 259 260 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]); 261 if (val != DEVLINK_SB_POOL_TYPE_INGRESS && 262 val != DEVLINK_SB_POOL_TYPE_EGRESS) 263 return -EINVAL; 264 *p_pool_type = val; 265 return 0; 266} 267 268static int 269devlink_sb_pool_type_get_from_info(struct genl_info *info, 270 enum devlink_sb_pool_type *p_pool_type) 271{ 272 return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type); 273} 274 275static int 276devlink_sb_th_type_get_from_attrs(struct nlattr **attrs, 277 enum devlink_sb_threshold_type *p_th_type) 278{ 279 u8 val; 280 281 if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]) 282 return -EINVAL; 283 284 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]); 285 if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC && 286 val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC) 287 return -EINVAL; 288 *p_th_type = val; 289 return 0; 290} 291 292static int 293devlink_sb_th_type_get_from_info(struct genl_info *info, 294 enum devlink_sb_threshold_type *p_th_type) 295{ 296 return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type); 297} 298 299static int 300devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb, 301 struct nlattr **attrs, 302 enum devlink_sb_pool_type pool_type, 303 u16 *p_tc_index) 304{ 305 u16 val; 306 307 if (!attrs[DEVLINK_ATTR_SB_TC_INDEX]) 308 return -EINVAL; 309 310 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]); 311 if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS && 312 val >= devlink_sb->ingress_tc_count) 313 return -EINVAL; 314 if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS && 315 val >= devlink_sb->egress_tc_count) 316 return -EINVAL; 317 *p_tc_index = val; 318 return 0; 319} 320 321static int 322devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb, 323 struct genl_info *info, 324 enum devlink_sb_pool_type pool_type, 325 u16 *p_tc_index) 326{ 327 return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs, 328 pool_type, p_tc_index); 329} 330 331struct devlink_region { 332 struct devlink *devlink; 333 struct list_head list; 334 const char *name; 335 struct list_head snapshot_list; 336 u32 max_snapshots; 337 u32 cur_snapshots; 338 u64 size; 339}; 340 341struct devlink_snapshot { 342 struct list_head list; 343 struct devlink_region *region; 344 devlink_snapshot_data_dest_t *data_destructor; 345 u64 data_len; 346 u8 *data; 347 u32 id; 348}; 349 350static struct devlink_region * 351devlink_region_get_by_name(struct devlink *devlink, const char *region_name) 352{ 353 struct devlink_region *region; 354 355 list_for_each_entry(region, &devlink->region_list, list) 356 if (!strcmp(region->name, region_name)) 357 return region; 358 359 return NULL; 360} 361 362static struct devlink_snapshot * 363devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id) 364{ 365 struct devlink_snapshot *snapshot; 366 367 list_for_each_entry(snapshot, &region->snapshot_list, list) 368 if (snapshot->id == id) 369 return snapshot; 370 371 return NULL; 372} 373 374static void devlink_region_snapshot_del(struct devlink_snapshot *snapshot) 375{ 376 snapshot->region->cur_snapshots--; 377 list_del(&snapshot->list); 378 (*snapshot->data_destructor)(snapshot->data); 379 kfree(snapshot); 380} 381 382#define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0) 383#define DEVLINK_NL_FLAG_NEED_PORT BIT(1) 384#define DEVLINK_NL_FLAG_NEED_SB BIT(2) 385 386/* The per devlink instance lock is taken by default in the pre-doit 387 * operation, yet several commands do not require this. The global 388 * devlink lock is taken and protects from disruption by user-calls. 389 */ 390#define DEVLINK_NL_FLAG_NO_LOCK BIT(3) 391 392static int devlink_nl_pre_doit(const struct genl_ops *ops, 393 struct sk_buff *skb, struct genl_info *info) 394{ 395 struct devlink *devlink; 396 int err; 397 398 mutex_lock(&devlink_mutex); 399 devlink = devlink_get_from_info(info); 400 if (IS_ERR(devlink)) { 401 mutex_unlock(&devlink_mutex); 402 return PTR_ERR(devlink); 403 } 404 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 405 mutex_lock(&devlink->lock); 406 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) { 407 info->user_ptr[0] = devlink; 408 } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) { 409 struct devlink_port *devlink_port; 410 411 devlink_port = devlink_port_get_from_info(devlink, info); 412 if (IS_ERR(devlink_port)) { 413 err = PTR_ERR(devlink_port); 414 goto unlock; 415 } 416 info->user_ptr[0] = devlink_port; 417 } 418 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) { 419 struct devlink_sb *devlink_sb; 420 421 devlink_sb = devlink_sb_get_from_info(devlink, info); 422 if (IS_ERR(devlink_sb)) { 423 err = PTR_ERR(devlink_sb); 424 goto unlock; 425 } 426 info->user_ptr[1] = devlink_sb; 427 } 428 return 0; 429 430unlock: 431 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 432 mutex_unlock(&devlink->lock); 433 mutex_unlock(&devlink_mutex); 434 return err; 435} 436 437static void devlink_nl_post_doit(const struct genl_ops *ops, 438 struct sk_buff *skb, struct genl_info *info) 439{ 440 struct devlink *devlink; 441 442 devlink = devlink_get_from_info(info); 443 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 444 mutex_unlock(&devlink->lock); 445 mutex_unlock(&devlink_mutex); 446} 447 448static struct genl_family devlink_nl_family; 449 450enum devlink_multicast_groups { 451 DEVLINK_MCGRP_CONFIG, 452}; 453 454static const struct genl_multicast_group devlink_nl_mcgrps[] = { 455 [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME }, 456}; 457 458static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink) 459{ 460 if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name)) 461 return -EMSGSIZE; 462 if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev))) 463 return -EMSGSIZE; 464 return 0; 465} 466 467static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink, 468 enum devlink_command cmd, u32 portid, 469 u32 seq, int flags) 470{ 471 void *hdr; 472 473 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 474 if (!hdr) 475 return -EMSGSIZE; 476 477 if (devlink_nl_put_handle(msg, devlink)) 478 goto nla_put_failure; 479 480 genlmsg_end(msg, hdr); 481 return 0; 482 483nla_put_failure: 484 genlmsg_cancel(msg, hdr); 485 return -EMSGSIZE; 486} 487 488static void devlink_notify(struct devlink *devlink, enum devlink_command cmd) 489{ 490 struct sk_buff *msg; 491 int err; 492 493 WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL); 494 495 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 496 if (!msg) 497 return; 498 499 err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0); 500 if (err) { 501 nlmsg_free(msg); 502 return; 503 } 504 505 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 506 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 507} 508 509static int devlink_nl_port_attrs_put(struct sk_buff *msg, 510 struct devlink_port *devlink_port) 511{ 512 struct devlink_port_attrs *attrs = &devlink_port->attrs; 513 514 if (!attrs->set) 515 return 0; 516 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour)) 517 return -EMSGSIZE; 518 if (devlink_port->attrs.flavour == DEVLINK_PORT_FLAVOUR_PCI_PF) { 519 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, 520 attrs->pci_pf.pf)) 521 return -EMSGSIZE; 522 } else if (devlink_port->attrs.flavour == DEVLINK_PORT_FLAVOUR_PCI_VF) { 523 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, 524 attrs->pci_vf.pf) || 525 nla_put_u16(msg, DEVLINK_ATTR_PORT_PCI_VF_NUMBER, 526 attrs->pci_vf.vf)) 527 return -EMSGSIZE; 528 } 529 if (devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PHYSICAL && 530 devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_CPU && 531 devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_DSA) 532 return 0; 533 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER, 534 attrs->phys.port_number)) 535 return -EMSGSIZE; 536 if (!attrs->split) 537 return 0; 538 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP, 539 attrs->phys.port_number)) 540 return -EMSGSIZE; 541 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER, 542 attrs->phys.split_subport_number)) 543 return -EMSGSIZE; 544 return 0; 545} 546 547static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink, 548 struct devlink_port *devlink_port, 549 enum devlink_command cmd, u32 portid, 550 u32 seq, int flags) 551{ 552 void *hdr; 553 554 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 555 if (!hdr) 556 return -EMSGSIZE; 557 558 if (devlink_nl_put_handle(msg, devlink)) 559 goto nla_put_failure; 560 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 561 goto nla_put_failure; 562 563 spin_lock(&devlink_port->type_lock); 564 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type)) 565 goto nla_put_failure_type_locked; 566 if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET && 567 nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE, 568 devlink_port->desired_type)) 569 goto nla_put_failure_type_locked; 570 if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) { 571 struct net_device *netdev = devlink_port->type_dev; 572 573 if (netdev && 574 (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX, 575 netdev->ifindex) || 576 nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME, 577 netdev->name))) 578 goto nla_put_failure_type_locked; 579 } 580 if (devlink_port->type == DEVLINK_PORT_TYPE_IB) { 581 struct ib_device *ibdev = devlink_port->type_dev; 582 583 if (ibdev && 584 nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME, 585 ibdev->name)) 586 goto nla_put_failure_type_locked; 587 } 588 spin_unlock(&devlink_port->type_lock); 589 if (devlink_nl_port_attrs_put(msg, devlink_port)) 590 goto nla_put_failure; 591 592 genlmsg_end(msg, hdr); 593 return 0; 594 595nla_put_failure_type_locked: 596 spin_unlock(&devlink_port->type_lock); 597nla_put_failure: 598 genlmsg_cancel(msg, hdr); 599 return -EMSGSIZE; 600} 601 602static void devlink_port_notify(struct devlink_port *devlink_port, 603 enum devlink_command cmd) 604{ 605 struct devlink *devlink = devlink_port->devlink; 606 struct sk_buff *msg; 607 int err; 608 609 if (!devlink_port->registered) 610 return; 611 612 WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL); 613 614 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 615 if (!msg) 616 return; 617 618 err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0); 619 if (err) { 620 nlmsg_free(msg); 621 return; 622 } 623 624 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 625 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 626} 627 628static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info) 629{ 630 struct devlink *devlink = info->user_ptr[0]; 631 struct sk_buff *msg; 632 int err; 633 634 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 635 if (!msg) 636 return -ENOMEM; 637 638 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW, 639 info->snd_portid, info->snd_seq, 0); 640 if (err) { 641 nlmsg_free(msg); 642 return err; 643 } 644 645 return genlmsg_reply(msg, info); 646} 647 648static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg, 649 struct netlink_callback *cb) 650{ 651 struct devlink *devlink; 652 int start = cb->args[0]; 653 int idx = 0; 654 int err; 655 656 mutex_lock(&devlink_mutex); 657 list_for_each_entry(devlink, &devlink_list, list) { 658 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 659 continue; 660 if (idx < start) { 661 idx++; 662 continue; 663 } 664 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW, 665 NETLINK_CB(cb->skb).portid, 666 cb->nlh->nlmsg_seq, NLM_F_MULTI); 667 if (err) 668 goto out; 669 idx++; 670 } 671out: 672 mutex_unlock(&devlink_mutex); 673 674 cb->args[0] = idx; 675 return msg->len; 676} 677 678static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb, 679 struct genl_info *info) 680{ 681 struct devlink_port *devlink_port = info->user_ptr[0]; 682 struct devlink *devlink = devlink_port->devlink; 683 struct sk_buff *msg; 684 int err; 685 686 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 687 if (!msg) 688 return -ENOMEM; 689 690 err = devlink_nl_port_fill(msg, devlink, devlink_port, 691 DEVLINK_CMD_PORT_NEW, 692 info->snd_portid, info->snd_seq, 0); 693 if (err) { 694 nlmsg_free(msg); 695 return err; 696 } 697 698 return genlmsg_reply(msg, info); 699} 700 701static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg, 702 struct netlink_callback *cb) 703{ 704 struct devlink *devlink; 705 struct devlink_port *devlink_port; 706 int start = cb->args[0]; 707 int idx = 0; 708 int err; 709 710 mutex_lock(&devlink_mutex); 711 list_for_each_entry(devlink, &devlink_list, list) { 712 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 713 continue; 714 mutex_lock(&devlink->lock); 715 list_for_each_entry(devlink_port, &devlink->port_list, list) { 716 if (idx < start) { 717 idx++; 718 continue; 719 } 720 err = devlink_nl_port_fill(msg, devlink, devlink_port, 721 DEVLINK_CMD_NEW, 722 NETLINK_CB(cb->skb).portid, 723 cb->nlh->nlmsg_seq, 724 NLM_F_MULTI); 725 if (err) { 726 mutex_unlock(&devlink->lock); 727 goto out; 728 } 729 idx++; 730 } 731 mutex_unlock(&devlink->lock); 732 } 733out: 734 mutex_unlock(&devlink_mutex); 735 736 cb->args[0] = idx; 737 return msg->len; 738} 739 740static int devlink_port_type_set(struct devlink *devlink, 741 struct devlink_port *devlink_port, 742 enum devlink_port_type port_type) 743 744{ 745 int err; 746 747 if (devlink->ops->port_type_set) { 748 if (port_type == DEVLINK_PORT_TYPE_NOTSET) 749 return -EINVAL; 750 if (port_type == devlink_port->type) 751 return 0; 752 err = devlink->ops->port_type_set(devlink_port, port_type); 753 if (err) 754 return err; 755 devlink_port->desired_type = port_type; 756 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 757 return 0; 758 } 759 return -EOPNOTSUPP; 760} 761 762static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb, 763 struct genl_info *info) 764{ 765 struct devlink_port *devlink_port = info->user_ptr[0]; 766 struct devlink *devlink = devlink_port->devlink; 767 int err; 768 769 if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) { 770 enum devlink_port_type port_type; 771 772 port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]); 773 err = devlink_port_type_set(devlink, devlink_port, port_type); 774 if (err) 775 return err; 776 } 777 return 0; 778} 779 780static int devlink_port_split(struct devlink *devlink, u32 port_index, 781 u32 count, struct netlink_ext_ack *extack) 782 783{ 784 if (devlink->ops->port_split) 785 return devlink->ops->port_split(devlink, port_index, count, 786 extack); 787 return -EOPNOTSUPP; 788} 789 790static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb, 791 struct genl_info *info) 792{ 793 struct devlink *devlink = info->user_ptr[0]; 794 u32 port_index; 795 u32 count; 796 797 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] || 798 !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]) 799 return -EINVAL; 800 801 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 802 count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]); 803 return devlink_port_split(devlink, port_index, count, info->extack); 804} 805 806static int devlink_port_unsplit(struct devlink *devlink, u32 port_index, 807 struct netlink_ext_ack *extack) 808 809{ 810 if (devlink->ops->port_unsplit) 811 return devlink->ops->port_unsplit(devlink, port_index, extack); 812 return -EOPNOTSUPP; 813} 814 815static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb, 816 struct genl_info *info) 817{ 818 struct devlink *devlink = info->user_ptr[0]; 819 u32 port_index; 820 821 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX]) 822 return -EINVAL; 823 824 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 825 return devlink_port_unsplit(devlink, port_index, info->extack); 826} 827 828static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink, 829 struct devlink_sb *devlink_sb, 830 enum devlink_command cmd, u32 portid, 831 u32 seq, int flags) 832{ 833 void *hdr; 834 835 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 836 if (!hdr) 837 return -EMSGSIZE; 838 839 if (devlink_nl_put_handle(msg, devlink)) 840 goto nla_put_failure; 841 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 842 goto nla_put_failure; 843 if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size)) 844 goto nla_put_failure; 845 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT, 846 devlink_sb->ingress_pools_count)) 847 goto nla_put_failure; 848 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT, 849 devlink_sb->egress_pools_count)) 850 goto nla_put_failure; 851 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT, 852 devlink_sb->ingress_tc_count)) 853 goto nla_put_failure; 854 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT, 855 devlink_sb->egress_tc_count)) 856 goto nla_put_failure; 857 858 genlmsg_end(msg, hdr); 859 return 0; 860 861nla_put_failure: 862 genlmsg_cancel(msg, hdr); 863 return -EMSGSIZE; 864} 865 866static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb, 867 struct genl_info *info) 868{ 869 struct devlink *devlink = info->user_ptr[0]; 870 struct devlink_sb *devlink_sb = info->user_ptr[1]; 871 struct sk_buff *msg; 872 int err; 873 874 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 875 if (!msg) 876 return -ENOMEM; 877 878 err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 879 DEVLINK_CMD_SB_NEW, 880 info->snd_portid, info->snd_seq, 0); 881 if (err) { 882 nlmsg_free(msg); 883 return err; 884 } 885 886 return genlmsg_reply(msg, info); 887} 888 889static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg, 890 struct netlink_callback *cb) 891{ 892 struct devlink *devlink; 893 struct devlink_sb *devlink_sb; 894 int start = cb->args[0]; 895 int idx = 0; 896 int err; 897 898 mutex_lock(&devlink_mutex); 899 list_for_each_entry(devlink, &devlink_list, list) { 900 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 901 continue; 902 mutex_lock(&devlink->lock); 903 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 904 if (idx < start) { 905 idx++; 906 continue; 907 } 908 err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 909 DEVLINK_CMD_SB_NEW, 910 NETLINK_CB(cb->skb).portid, 911 cb->nlh->nlmsg_seq, 912 NLM_F_MULTI); 913 if (err) { 914 mutex_unlock(&devlink->lock); 915 goto out; 916 } 917 idx++; 918 } 919 mutex_unlock(&devlink->lock); 920 } 921out: 922 mutex_unlock(&devlink_mutex); 923 924 cb->args[0] = idx; 925 return msg->len; 926} 927 928static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink, 929 struct devlink_sb *devlink_sb, 930 u16 pool_index, enum devlink_command cmd, 931 u32 portid, u32 seq, int flags) 932{ 933 struct devlink_sb_pool_info pool_info; 934 void *hdr; 935 int err; 936 937 err = devlink->ops->sb_pool_get(devlink, devlink_sb->index, 938 pool_index, &pool_info); 939 if (err) 940 return err; 941 942 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 943 if (!hdr) 944 return -EMSGSIZE; 945 946 if (devlink_nl_put_handle(msg, devlink)) 947 goto nla_put_failure; 948 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 949 goto nla_put_failure; 950 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 951 goto nla_put_failure; 952 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type)) 953 goto nla_put_failure; 954 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size)) 955 goto nla_put_failure; 956 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, 957 pool_info.threshold_type)) 958 goto nla_put_failure; 959 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_CELL_SIZE, 960 pool_info.cell_size)) 961 goto nla_put_failure; 962 963 genlmsg_end(msg, hdr); 964 return 0; 965 966nla_put_failure: 967 genlmsg_cancel(msg, hdr); 968 return -EMSGSIZE; 969} 970 971static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb, 972 struct genl_info *info) 973{ 974 struct devlink *devlink = info->user_ptr[0]; 975 struct devlink_sb *devlink_sb = info->user_ptr[1]; 976 struct sk_buff *msg; 977 u16 pool_index; 978 int err; 979 980 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 981 &pool_index); 982 if (err) 983 return err; 984 985 if (!devlink->ops->sb_pool_get) 986 return -EOPNOTSUPP; 987 988 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 989 if (!msg) 990 return -ENOMEM; 991 992 err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index, 993 DEVLINK_CMD_SB_POOL_NEW, 994 info->snd_portid, info->snd_seq, 0); 995 if (err) { 996 nlmsg_free(msg); 997 return err; 998 } 999 1000 return genlmsg_reply(msg, info); 1001} 1002 1003static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 1004 struct devlink *devlink, 1005 struct devlink_sb *devlink_sb, 1006 u32 portid, u32 seq) 1007{ 1008 u16 pool_count = devlink_sb_pool_count(devlink_sb); 1009 u16 pool_index; 1010 int err; 1011 1012 for (pool_index = 0; pool_index < pool_count; pool_index++) { 1013 if (*p_idx < start) { 1014 (*p_idx)++; 1015 continue; 1016 } 1017 err = devlink_nl_sb_pool_fill(msg, devlink, 1018 devlink_sb, 1019 pool_index, 1020 DEVLINK_CMD_SB_POOL_NEW, 1021 portid, seq, NLM_F_MULTI); 1022 if (err) 1023 return err; 1024 (*p_idx)++; 1025 } 1026 return 0; 1027} 1028 1029static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg, 1030 struct netlink_callback *cb) 1031{ 1032 struct devlink *devlink; 1033 struct devlink_sb *devlink_sb; 1034 int start = cb->args[0]; 1035 int idx = 0; 1036 int err; 1037 1038 mutex_lock(&devlink_mutex); 1039 list_for_each_entry(devlink, &devlink_list, list) { 1040 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 1041 !devlink->ops->sb_pool_get) 1042 continue; 1043 mutex_lock(&devlink->lock); 1044 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 1045 err = __sb_pool_get_dumpit(msg, start, &idx, devlink, 1046 devlink_sb, 1047 NETLINK_CB(cb->skb).portid, 1048 cb->nlh->nlmsg_seq); 1049 if (err && err != -EOPNOTSUPP) { 1050 mutex_unlock(&devlink->lock); 1051 goto out; 1052 } 1053 } 1054 mutex_unlock(&devlink->lock); 1055 } 1056out: 1057 mutex_unlock(&devlink_mutex); 1058 1059 cb->args[0] = idx; 1060 return msg->len; 1061} 1062 1063static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index, 1064 u16 pool_index, u32 size, 1065 enum devlink_sb_threshold_type threshold_type, 1066 struct netlink_ext_ack *extack) 1067 1068{ 1069 const struct devlink_ops *ops = devlink->ops; 1070 1071 if (ops->sb_pool_set) 1072 return ops->sb_pool_set(devlink, sb_index, pool_index, 1073 size, threshold_type, extack); 1074 return -EOPNOTSUPP; 1075} 1076 1077static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb, 1078 struct genl_info *info) 1079{ 1080 struct devlink *devlink = info->user_ptr[0]; 1081 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1082 enum devlink_sb_threshold_type threshold_type; 1083 u16 pool_index; 1084 u32 size; 1085 int err; 1086 1087 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1088 &pool_index); 1089 if (err) 1090 return err; 1091 1092 err = devlink_sb_th_type_get_from_info(info, &threshold_type); 1093 if (err) 1094 return err; 1095 1096 if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]) 1097 return -EINVAL; 1098 1099 size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]); 1100 return devlink_sb_pool_set(devlink, devlink_sb->index, 1101 pool_index, size, threshold_type, 1102 info->extack); 1103} 1104 1105static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg, 1106 struct devlink *devlink, 1107 struct devlink_port *devlink_port, 1108 struct devlink_sb *devlink_sb, 1109 u16 pool_index, 1110 enum devlink_command cmd, 1111 u32 portid, u32 seq, int flags) 1112{ 1113 const struct devlink_ops *ops = devlink->ops; 1114 u32 threshold; 1115 void *hdr; 1116 int err; 1117 1118 err = ops->sb_port_pool_get(devlink_port, devlink_sb->index, 1119 pool_index, &threshold); 1120 if (err) 1121 return err; 1122 1123 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1124 if (!hdr) 1125 return -EMSGSIZE; 1126 1127 if (devlink_nl_put_handle(msg, devlink)) 1128 goto nla_put_failure; 1129 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 1130 goto nla_put_failure; 1131 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 1132 goto nla_put_failure; 1133 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 1134 goto nla_put_failure; 1135 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 1136 goto nla_put_failure; 1137 1138 if (ops->sb_occ_port_pool_get) { 1139 u32 cur; 1140 u32 max; 1141 1142 err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index, 1143 pool_index, &cur, &max); 1144 if (err && err != -EOPNOTSUPP) 1145 return err; 1146 if (!err) { 1147 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 1148 goto nla_put_failure; 1149 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 1150 goto nla_put_failure; 1151 } 1152 } 1153 1154 genlmsg_end(msg, hdr); 1155 return 0; 1156 1157nla_put_failure: 1158 genlmsg_cancel(msg, hdr); 1159 return -EMSGSIZE; 1160} 1161 1162static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb, 1163 struct genl_info *info) 1164{ 1165 struct devlink_port *devlink_port = info->user_ptr[0]; 1166 struct devlink *devlink = devlink_port->devlink; 1167 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1168 struct sk_buff *msg; 1169 u16 pool_index; 1170 int err; 1171 1172 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1173 &pool_index); 1174 if (err) 1175 return err; 1176 1177 if (!devlink->ops->sb_port_pool_get) 1178 return -EOPNOTSUPP; 1179 1180 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1181 if (!msg) 1182 return -ENOMEM; 1183 1184 err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port, 1185 devlink_sb, pool_index, 1186 DEVLINK_CMD_SB_PORT_POOL_NEW, 1187 info->snd_portid, info->snd_seq, 0); 1188 if (err) { 1189 nlmsg_free(msg); 1190 return err; 1191 } 1192 1193 return genlmsg_reply(msg, info); 1194} 1195 1196static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 1197 struct devlink *devlink, 1198 struct devlink_sb *devlink_sb, 1199 u32 portid, u32 seq) 1200{ 1201 struct devlink_port *devlink_port; 1202 u16 pool_count = devlink_sb_pool_count(devlink_sb); 1203 u16 pool_index; 1204 int err; 1205 1206 list_for_each_entry(devlink_port, &devlink->port_list, list) { 1207 for (pool_index = 0; pool_index < pool_count; pool_index++) { 1208 if (*p_idx < start) { 1209 (*p_idx)++; 1210 continue; 1211 } 1212 err = devlink_nl_sb_port_pool_fill(msg, devlink, 1213 devlink_port, 1214 devlink_sb, 1215 pool_index, 1216 DEVLINK_CMD_SB_PORT_POOL_NEW, 1217 portid, seq, 1218 NLM_F_MULTI); 1219 if (err) 1220 return err; 1221 (*p_idx)++; 1222 } 1223 } 1224 return 0; 1225} 1226 1227static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg, 1228 struct netlink_callback *cb) 1229{ 1230 struct devlink *devlink; 1231 struct devlink_sb *devlink_sb; 1232 int start = cb->args[0]; 1233 int idx = 0; 1234 int err; 1235 1236 mutex_lock(&devlink_mutex); 1237 list_for_each_entry(devlink, &devlink_list, list) { 1238 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 1239 !devlink->ops->sb_port_pool_get) 1240 continue; 1241 mutex_lock(&devlink->lock); 1242 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 1243 err = __sb_port_pool_get_dumpit(msg, start, &idx, 1244 devlink, devlink_sb, 1245 NETLINK_CB(cb->skb).portid, 1246 cb->nlh->nlmsg_seq); 1247 if (err && err != -EOPNOTSUPP) { 1248 mutex_unlock(&devlink->lock); 1249 goto out; 1250 } 1251 } 1252 mutex_unlock(&devlink->lock); 1253 } 1254out: 1255 mutex_unlock(&devlink_mutex); 1256 1257 cb->args[0] = idx; 1258 return msg->len; 1259} 1260 1261static int devlink_sb_port_pool_set(struct devlink_port *devlink_port, 1262 unsigned int sb_index, u16 pool_index, 1263 u32 threshold, 1264 struct netlink_ext_ack *extack) 1265 1266{ 1267 const struct devlink_ops *ops = devlink_port->devlink->ops; 1268 1269 if (ops->sb_port_pool_set) 1270 return ops->sb_port_pool_set(devlink_port, sb_index, 1271 pool_index, threshold, extack); 1272 return -EOPNOTSUPP; 1273} 1274 1275static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb, 1276 struct genl_info *info) 1277{ 1278 struct devlink_port *devlink_port = info->user_ptr[0]; 1279 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1280 u16 pool_index; 1281 u32 threshold; 1282 int err; 1283 1284 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1285 &pool_index); 1286 if (err) 1287 return err; 1288 1289 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD]) 1290 return -EINVAL; 1291 1292 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 1293 return devlink_sb_port_pool_set(devlink_port, devlink_sb->index, 1294 pool_index, threshold, info->extack); 1295} 1296 1297static int 1298devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink, 1299 struct devlink_port *devlink_port, 1300 struct devlink_sb *devlink_sb, u16 tc_index, 1301 enum devlink_sb_pool_type pool_type, 1302 enum devlink_command cmd, 1303 u32 portid, u32 seq, int flags) 1304{ 1305 const struct devlink_ops *ops = devlink->ops; 1306 u16 pool_index; 1307 u32 threshold; 1308 void *hdr; 1309 int err; 1310 1311 err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index, 1312 tc_index, pool_type, 1313 &pool_index, &threshold); 1314 if (err) 1315 return err; 1316 1317 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1318 if (!hdr) 1319 return -EMSGSIZE; 1320 1321 if (devlink_nl_put_handle(msg, devlink)) 1322 goto nla_put_failure; 1323 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 1324 goto nla_put_failure; 1325 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 1326 goto nla_put_failure; 1327 if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index)) 1328 goto nla_put_failure; 1329 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type)) 1330 goto nla_put_failure; 1331 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 1332 goto nla_put_failure; 1333 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 1334 goto nla_put_failure; 1335 1336 if (ops->sb_occ_tc_port_bind_get) { 1337 u32 cur; 1338 u32 max; 1339 1340 err = ops->sb_occ_tc_port_bind_get(devlink_port, 1341 devlink_sb->index, 1342 tc_index, pool_type, 1343 &cur, &max); 1344 if (err && err != -EOPNOTSUPP) 1345 return err; 1346 if (!err) { 1347 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 1348 goto nla_put_failure; 1349 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 1350 goto nla_put_failure; 1351 } 1352 } 1353 1354 genlmsg_end(msg, hdr); 1355 return 0; 1356 1357nla_put_failure: 1358 genlmsg_cancel(msg, hdr); 1359 return -EMSGSIZE; 1360} 1361 1362static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb, 1363 struct genl_info *info) 1364{ 1365 struct devlink_port *devlink_port = info->user_ptr[0]; 1366 struct devlink *devlink = devlink_port->devlink; 1367 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1368 struct sk_buff *msg; 1369 enum devlink_sb_pool_type pool_type; 1370 u16 tc_index; 1371 int err; 1372 1373 err = devlink_sb_pool_type_get_from_info(info, &pool_type); 1374 if (err) 1375 return err; 1376 1377 err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 1378 pool_type, &tc_index); 1379 if (err) 1380 return err; 1381 1382 if (!devlink->ops->sb_tc_pool_bind_get) 1383 return -EOPNOTSUPP; 1384 1385 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1386 if (!msg) 1387 return -ENOMEM; 1388 1389 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port, 1390 devlink_sb, tc_index, pool_type, 1391 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1392 info->snd_portid, 1393 info->snd_seq, 0); 1394 if (err) { 1395 nlmsg_free(msg); 1396 return err; 1397 } 1398 1399 return genlmsg_reply(msg, info); 1400} 1401 1402static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, 1403 int start, int *p_idx, 1404 struct devlink *devlink, 1405 struct devlink_sb *devlink_sb, 1406 u32 portid, u32 seq) 1407{ 1408 struct devlink_port *devlink_port; 1409 u16 tc_index; 1410 int err; 1411 1412 list_for_each_entry(devlink_port, &devlink->port_list, list) { 1413 for (tc_index = 0; 1414 tc_index < devlink_sb->ingress_tc_count; tc_index++) { 1415 if (*p_idx < start) { 1416 (*p_idx)++; 1417 continue; 1418 } 1419 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 1420 devlink_port, 1421 devlink_sb, 1422 tc_index, 1423 DEVLINK_SB_POOL_TYPE_INGRESS, 1424 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1425 portid, seq, 1426 NLM_F_MULTI); 1427 if (err) 1428 return err; 1429 (*p_idx)++; 1430 } 1431 for (tc_index = 0; 1432 tc_index < devlink_sb->egress_tc_count; tc_index++) { 1433 if (*p_idx < start) { 1434 (*p_idx)++; 1435 continue; 1436 } 1437 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 1438 devlink_port, 1439 devlink_sb, 1440 tc_index, 1441 DEVLINK_SB_POOL_TYPE_EGRESS, 1442 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1443 portid, seq, 1444 NLM_F_MULTI); 1445 if (err) 1446 return err; 1447 (*p_idx)++; 1448 } 1449 } 1450 return 0; 1451} 1452 1453static int 1454devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, 1455 struct netlink_callback *cb) 1456{ 1457 struct devlink *devlink; 1458 struct devlink_sb *devlink_sb; 1459 int start = cb->args[0]; 1460 int idx = 0; 1461 int err; 1462 1463 mutex_lock(&devlink_mutex); 1464 list_for_each_entry(devlink, &devlink_list, list) { 1465 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 1466 !devlink->ops->sb_tc_pool_bind_get) 1467 continue; 1468 1469 mutex_lock(&devlink->lock); 1470 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 1471 err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx, 1472 devlink, 1473 devlink_sb, 1474 NETLINK_CB(cb->skb).portid, 1475 cb->nlh->nlmsg_seq); 1476 if (err && err != -EOPNOTSUPP) { 1477 mutex_unlock(&devlink->lock); 1478 goto out; 1479 } 1480 } 1481 mutex_unlock(&devlink->lock); 1482 } 1483out: 1484 mutex_unlock(&devlink_mutex); 1485 1486 cb->args[0] = idx; 1487 return msg->len; 1488} 1489 1490static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port, 1491 unsigned int sb_index, u16 tc_index, 1492 enum devlink_sb_pool_type pool_type, 1493 u16 pool_index, u32 threshold, 1494 struct netlink_ext_ack *extack) 1495 1496{ 1497 const struct devlink_ops *ops = devlink_port->devlink->ops; 1498 1499 if (ops->sb_tc_pool_bind_set) 1500 return ops->sb_tc_pool_bind_set(devlink_port, sb_index, 1501 tc_index, pool_type, 1502 pool_index, threshold, extack); 1503 return -EOPNOTSUPP; 1504} 1505 1506static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb, 1507 struct genl_info *info) 1508{ 1509 struct devlink_port *devlink_port = info->user_ptr[0]; 1510 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1511 enum devlink_sb_pool_type pool_type; 1512 u16 tc_index; 1513 u16 pool_index; 1514 u32 threshold; 1515 int err; 1516 1517 err = devlink_sb_pool_type_get_from_info(info, &pool_type); 1518 if (err) 1519 return err; 1520 1521 err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 1522 pool_type, &tc_index); 1523 if (err) 1524 return err; 1525 1526 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1527 &pool_index); 1528 if (err) 1529 return err; 1530 1531 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD]) 1532 return -EINVAL; 1533 1534 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 1535 return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index, 1536 tc_index, pool_type, 1537 pool_index, threshold, info->extack); 1538} 1539 1540static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb, 1541 struct genl_info *info) 1542{ 1543 struct devlink *devlink = info->user_ptr[0]; 1544 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1545 const struct devlink_ops *ops = devlink->ops; 1546 1547 if (ops->sb_occ_snapshot) 1548 return ops->sb_occ_snapshot(devlink, devlink_sb->index); 1549 return -EOPNOTSUPP; 1550} 1551 1552static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb, 1553 struct genl_info *info) 1554{ 1555 struct devlink *devlink = info->user_ptr[0]; 1556 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1557 const struct devlink_ops *ops = devlink->ops; 1558 1559 if (ops->sb_occ_max_clear) 1560 return ops->sb_occ_max_clear(devlink, devlink_sb->index); 1561 return -EOPNOTSUPP; 1562} 1563 1564static int devlink_nl_eswitch_fill(struct sk_buff *msg, struct devlink *devlink, 1565 enum devlink_command cmd, u32 portid, 1566 u32 seq, int flags) 1567{ 1568 const struct devlink_ops *ops = devlink->ops; 1569 enum devlink_eswitch_encap_mode encap_mode; 1570 u8 inline_mode; 1571 void *hdr; 1572 int err = 0; 1573 u16 mode; 1574 1575 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1576 if (!hdr) 1577 return -EMSGSIZE; 1578 1579 err = devlink_nl_put_handle(msg, devlink); 1580 if (err) 1581 goto nla_put_failure; 1582 1583 if (ops->eswitch_mode_get) { 1584 err = ops->eswitch_mode_get(devlink, &mode); 1585 if (err) 1586 goto nla_put_failure; 1587 err = nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode); 1588 if (err) 1589 goto nla_put_failure; 1590 } 1591 1592 if (ops->eswitch_inline_mode_get) { 1593 err = ops->eswitch_inline_mode_get(devlink, &inline_mode); 1594 if (err) 1595 goto nla_put_failure; 1596 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE, 1597 inline_mode); 1598 if (err) 1599 goto nla_put_failure; 1600 } 1601 1602 if (ops->eswitch_encap_mode_get) { 1603 err = ops->eswitch_encap_mode_get(devlink, &encap_mode); 1604 if (err) 1605 goto nla_put_failure; 1606 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, encap_mode); 1607 if (err) 1608 goto nla_put_failure; 1609 } 1610 1611 genlmsg_end(msg, hdr); 1612 return 0; 1613 1614nla_put_failure: 1615 genlmsg_cancel(msg, hdr); 1616 return err; 1617} 1618 1619static int devlink_nl_cmd_eswitch_get_doit(struct sk_buff *skb, 1620 struct genl_info *info) 1621{ 1622 struct devlink *devlink = info->user_ptr[0]; 1623 struct sk_buff *msg; 1624 int err; 1625 1626 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1627 if (!msg) 1628 return -ENOMEM; 1629 1630 err = devlink_nl_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_GET, 1631 info->snd_portid, info->snd_seq, 0); 1632 1633 if (err) { 1634 nlmsg_free(msg); 1635 return err; 1636 } 1637 1638 return genlmsg_reply(msg, info); 1639} 1640 1641static int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb, 1642 struct genl_info *info) 1643{ 1644 struct devlink *devlink = info->user_ptr[0]; 1645 const struct devlink_ops *ops = devlink->ops; 1646 enum devlink_eswitch_encap_mode encap_mode; 1647 u8 inline_mode; 1648 int err = 0; 1649 u16 mode; 1650 1651 if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) { 1652 if (!ops->eswitch_mode_set) 1653 return -EOPNOTSUPP; 1654 mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]); 1655 err = ops->eswitch_mode_set(devlink, mode, info->extack); 1656 if (err) 1657 return err; 1658 } 1659 1660 if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) { 1661 if (!ops->eswitch_inline_mode_set) 1662 return -EOPNOTSUPP; 1663 inline_mode = nla_get_u8( 1664 info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]); 1665 err = ops->eswitch_inline_mode_set(devlink, inline_mode, 1666 info->extack); 1667 if (err) 1668 return err; 1669 } 1670 1671 if (info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]) { 1672 if (!ops->eswitch_encap_mode_set) 1673 return -EOPNOTSUPP; 1674 encap_mode = nla_get_u8(info->attrs[DEVLINK_ATTR_ESWITCH_ENCAP_MODE]); 1675 err = ops->eswitch_encap_mode_set(devlink, encap_mode, 1676 info->extack); 1677 if (err) 1678 return err; 1679 } 1680 1681 return 0; 1682} 1683 1684int devlink_dpipe_match_put(struct sk_buff *skb, 1685 struct devlink_dpipe_match *match) 1686{ 1687 struct devlink_dpipe_header *header = match->header; 1688 struct devlink_dpipe_field *field = &header->fields[match->field_id]; 1689 struct nlattr *match_attr; 1690 1691 match_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_MATCH); 1692 if (!match_attr) 1693 return -EMSGSIZE; 1694 1695 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_MATCH_TYPE, match->type) || 1696 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, match->header_index) || 1697 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 1698 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 1699 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 1700 goto nla_put_failure; 1701 1702 nla_nest_end(skb, match_attr); 1703 return 0; 1704 1705nla_put_failure: 1706 nla_nest_cancel(skb, match_attr); 1707 return -EMSGSIZE; 1708} 1709EXPORT_SYMBOL_GPL(devlink_dpipe_match_put); 1710 1711static int devlink_dpipe_matches_put(struct devlink_dpipe_table *table, 1712 struct sk_buff *skb) 1713{ 1714 struct nlattr *matches_attr; 1715 1716 matches_attr = nla_nest_start_noflag(skb, 1717 DEVLINK_ATTR_DPIPE_TABLE_MATCHES); 1718 if (!matches_attr) 1719 return -EMSGSIZE; 1720 1721 if (table->table_ops->matches_dump(table->priv, skb)) 1722 goto nla_put_failure; 1723 1724 nla_nest_end(skb, matches_attr); 1725 return 0; 1726 1727nla_put_failure: 1728 nla_nest_cancel(skb, matches_attr); 1729 return -EMSGSIZE; 1730} 1731 1732int devlink_dpipe_action_put(struct sk_buff *skb, 1733 struct devlink_dpipe_action *action) 1734{ 1735 struct devlink_dpipe_header *header = action->header; 1736 struct devlink_dpipe_field *field = &header->fields[action->field_id]; 1737 struct nlattr *action_attr; 1738 1739 action_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ACTION); 1740 if (!action_attr) 1741 return -EMSGSIZE; 1742 1743 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_ACTION_TYPE, action->type) || 1744 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, action->header_index) || 1745 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 1746 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 1747 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 1748 goto nla_put_failure; 1749 1750 nla_nest_end(skb, action_attr); 1751 return 0; 1752 1753nla_put_failure: 1754 nla_nest_cancel(skb, action_attr); 1755 return -EMSGSIZE; 1756} 1757EXPORT_SYMBOL_GPL(devlink_dpipe_action_put); 1758 1759static int devlink_dpipe_actions_put(struct devlink_dpipe_table *table, 1760 struct sk_buff *skb) 1761{ 1762 struct nlattr *actions_attr; 1763 1764 actions_attr = nla_nest_start_noflag(skb, 1765 DEVLINK_ATTR_DPIPE_TABLE_ACTIONS); 1766 if (!actions_attr) 1767 return -EMSGSIZE; 1768 1769 if (table->table_ops->actions_dump(table->priv, skb)) 1770 goto nla_put_failure; 1771 1772 nla_nest_end(skb, actions_attr); 1773 return 0; 1774 1775nla_put_failure: 1776 nla_nest_cancel(skb, actions_attr); 1777 return -EMSGSIZE; 1778} 1779 1780static int devlink_dpipe_table_put(struct sk_buff *skb, 1781 struct devlink_dpipe_table *table) 1782{ 1783 struct nlattr *table_attr; 1784 u64 table_size; 1785 1786 table_size = table->table_ops->size_get(table->priv); 1787 table_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLE); 1788 if (!table_attr) 1789 return -EMSGSIZE; 1790 1791 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) || 1792 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table_size, 1793 DEVLINK_ATTR_PAD)) 1794 goto nla_put_failure; 1795 if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED, 1796 table->counters_enabled)) 1797 goto nla_put_failure; 1798 1799 if (table->resource_valid) { 1800 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID, 1801 table->resource_id, DEVLINK_ATTR_PAD) || 1802 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS, 1803 table->resource_units, DEVLINK_ATTR_PAD)) 1804 goto nla_put_failure; 1805 } 1806 if (devlink_dpipe_matches_put(table, skb)) 1807 goto nla_put_failure; 1808 1809 if (devlink_dpipe_actions_put(table, skb)) 1810 goto nla_put_failure; 1811 1812 nla_nest_end(skb, table_attr); 1813 return 0; 1814 1815nla_put_failure: 1816 nla_nest_cancel(skb, table_attr); 1817 return -EMSGSIZE; 1818} 1819 1820static int devlink_dpipe_send_and_alloc_skb(struct sk_buff **pskb, 1821 struct genl_info *info) 1822{ 1823 int err; 1824 1825 if (*pskb) { 1826 err = genlmsg_reply(*pskb, info); 1827 if (err) 1828 return err; 1829 } 1830 *pskb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 1831 if (!*pskb) 1832 return -ENOMEM; 1833 return 0; 1834} 1835 1836static int devlink_dpipe_tables_fill(struct genl_info *info, 1837 enum devlink_command cmd, int flags, 1838 struct list_head *dpipe_tables, 1839 const char *table_name) 1840{ 1841 struct devlink *devlink = info->user_ptr[0]; 1842 struct devlink_dpipe_table *table; 1843 struct nlattr *tables_attr; 1844 struct sk_buff *skb = NULL; 1845 struct nlmsghdr *nlh; 1846 bool incomplete; 1847 void *hdr; 1848 int i; 1849 int err; 1850 1851 table = list_first_entry(dpipe_tables, 1852 struct devlink_dpipe_table, list); 1853start_again: 1854 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 1855 if (err) 1856 return err; 1857 1858 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 1859 &devlink_nl_family, NLM_F_MULTI, cmd); 1860 if (!hdr) { 1861 nlmsg_free(skb); 1862 return -EMSGSIZE; 1863 } 1864 1865 if (devlink_nl_put_handle(skb, devlink)) 1866 goto nla_put_failure; 1867 tables_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_TABLES); 1868 if (!tables_attr) 1869 goto nla_put_failure; 1870 1871 i = 0; 1872 incomplete = false; 1873 list_for_each_entry_from(table, dpipe_tables, list) { 1874 if (!table_name) { 1875 err = devlink_dpipe_table_put(skb, table); 1876 if (err) { 1877 if (!i) 1878 goto err_table_put; 1879 incomplete = true; 1880 break; 1881 } 1882 } else { 1883 if (!strcmp(table->name, table_name)) { 1884 err = devlink_dpipe_table_put(skb, table); 1885 if (err) 1886 break; 1887 } 1888 } 1889 i++; 1890 } 1891 1892 nla_nest_end(skb, tables_attr); 1893 genlmsg_end(skb, hdr); 1894 if (incomplete) 1895 goto start_again; 1896 1897send_done: 1898 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 1899 NLMSG_DONE, 0, flags | NLM_F_MULTI); 1900 if (!nlh) { 1901 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 1902 if (err) 1903 return err; 1904 goto send_done; 1905 } 1906 1907 return genlmsg_reply(skb, info); 1908 1909nla_put_failure: 1910 err = -EMSGSIZE; 1911err_table_put: 1912 nlmsg_free(skb); 1913 return err; 1914} 1915 1916static int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb, 1917 struct genl_info *info) 1918{ 1919 struct devlink *devlink = info->user_ptr[0]; 1920 const char *table_name = NULL; 1921 1922 if (info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]) 1923 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 1924 1925 return devlink_dpipe_tables_fill(info, DEVLINK_CMD_DPIPE_TABLE_GET, 0, 1926 &devlink->dpipe_table_list, 1927 table_name); 1928} 1929 1930static int devlink_dpipe_value_put(struct sk_buff *skb, 1931 struct devlink_dpipe_value *value) 1932{ 1933 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE, 1934 value->value_size, value->value)) 1935 return -EMSGSIZE; 1936 if (value->mask) 1937 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE_MASK, 1938 value->value_size, value->mask)) 1939 return -EMSGSIZE; 1940 if (value->mapping_valid) 1941 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_VALUE_MAPPING, 1942 value->mapping_value)) 1943 return -EMSGSIZE; 1944 return 0; 1945} 1946 1947static int devlink_dpipe_action_value_put(struct sk_buff *skb, 1948 struct devlink_dpipe_value *value) 1949{ 1950 if (!value->action) 1951 return -EINVAL; 1952 if (devlink_dpipe_action_put(skb, value->action)) 1953 return -EMSGSIZE; 1954 if (devlink_dpipe_value_put(skb, value)) 1955 return -EMSGSIZE; 1956 return 0; 1957} 1958 1959static int devlink_dpipe_action_values_put(struct sk_buff *skb, 1960 struct devlink_dpipe_value *values, 1961 unsigned int values_count) 1962{ 1963 struct nlattr *action_attr; 1964 int i; 1965 int err; 1966 1967 for (i = 0; i < values_count; i++) { 1968 action_attr = nla_nest_start_noflag(skb, 1969 DEVLINK_ATTR_DPIPE_ACTION_VALUE); 1970 if (!action_attr) 1971 return -EMSGSIZE; 1972 err = devlink_dpipe_action_value_put(skb, &values[i]); 1973 if (err) 1974 goto err_action_value_put; 1975 nla_nest_end(skb, action_attr); 1976 } 1977 return 0; 1978 1979err_action_value_put: 1980 nla_nest_cancel(skb, action_attr); 1981 return err; 1982} 1983 1984static int devlink_dpipe_match_value_put(struct sk_buff *skb, 1985 struct devlink_dpipe_value *value) 1986{ 1987 if (!value->match) 1988 return -EINVAL; 1989 if (devlink_dpipe_match_put(skb, value->match)) 1990 return -EMSGSIZE; 1991 if (devlink_dpipe_value_put(skb, value)) 1992 return -EMSGSIZE; 1993 return 0; 1994} 1995 1996static int devlink_dpipe_match_values_put(struct sk_buff *skb, 1997 struct devlink_dpipe_value *values, 1998 unsigned int values_count) 1999{ 2000 struct nlattr *match_attr; 2001 int i; 2002 int err; 2003 2004 for (i = 0; i < values_count; i++) { 2005 match_attr = nla_nest_start_noflag(skb, 2006 DEVLINK_ATTR_DPIPE_MATCH_VALUE); 2007 if (!match_attr) 2008 return -EMSGSIZE; 2009 err = devlink_dpipe_match_value_put(skb, &values[i]); 2010 if (err) 2011 goto err_match_value_put; 2012 nla_nest_end(skb, match_attr); 2013 } 2014 return 0; 2015 2016err_match_value_put: 2017 nla_nest_cancel(skb, match_attr); 2018 return err; 2019} 2020 2021static int devlink_dpipe_entry_put(struct sk_buff *skb, 2022 struct devlink_dpipe_entry *entry) 2023{ 2024 struct nlattr *entry_attr, *matches_attr, *actions_attr; 2025 int err; 2026 2027 entry_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_ENTRY); 2028 if (!entry_attr) 2029 return -EMSGSIZE; 2030 2031 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_INDEX, entry->index, 2032 DEVLINK_ATTR_PAD)) 2033 goto nla_put_failure; 2034 if (entry->counter_valid) 2035 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_COUNTER, 2036 entry->counter, DEVLINK_ATTR_PAD)) 2037 goto nla_put_failure; 2038 2039 matches_attr = nla_nest_start_noflag(skb, 2040 DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES); 2041 if (!matches_attr) 2042 goto nla_put_failure; 2043 2044 err = devlink_dpipe_match_values_put(skb, entry->match_values, 2045 entry->match_values_count); 2046 if (err) { 2047 nla_nest_cancel(skb, matches_attr); 2048 goto err_match_values_put; 2049 } 2050 nla_nest_end(skb, matches_attr); 2051 2052 actions_attr = nla_nest_start_noflag(skb, 2053 DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES); 2054 if (!actions_attr) 2055 goto nla_put_failure; 2056 2057 err = devlink_dpipe_action_values_put(skb, entry->action_values, 2058 entry->action_values_count); 2059 if (err) { 2060 nla_nest_cancel(skb, actions_attr); 2061 goto err_action_values_put; 2062 } 2063 nla_nest_end(skb, actions_attr); 2064 2065 nla_nest_end(skb, entry_attr); 2066 return 0; 2067 2068nla_put_failure: 2069 err = -EMSGSIZE; 2070err_match_values_put: 2071err_action_values_put: 2072 nla_nest_cancel(skb, entry_attr); 2073 return err; 2074} 2075 2076static struct devlink_dpipe_table * 2077devlink_dpipe_table_find(struct list_head *dpipe_tables, 2078 const char *table_name) 2079{ 2080 struct devlink_dpipe_table *table; 2081 2082 list_for_each_entry_rcu(table, dpipe_tables, list) { 2083 if (!strcmp(table->name, table_name)) 2084 return table; 2085 } 2086 return NULL; 2087} 2088 2089int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx) 2090{ 2091 struct devlink *devlink; 2092 int err; 2093 2094 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx->skb, 2095 dump_ctx->info); 2096 if (err) 2097 return err; 2098 2099 dump_ctx->hdr = genlmsg_put(dump_ctx->skb, 2100 dump_ctx->info->snd_portid, 2101 dump_ctx->info->snd_seq, 2102 &devlink_nl_family, NLM_F_MULTI, 2103 dump_ctx->cmd); 2104 if (!dump_ctx->hdr) 2105 goto nla_put_failure; 2106 2107 devlink = dump_ctx->info->user_ptr[0]; 2108 if (devlink_nl_put_handle(dump_ctx->skb, devlink)) 2109 goto nla_put_failure; 2110 dump_ctx->nest = nla_nest_start_noflag(dump_ctx->skb, 2111 DEVLINK_ATTR_DPIPE_ENTRIES); 2112 if (!dump_ctx->nest) 2113 goto nla_put_failure; 2114 return 0; 2115 2116nla_put_failure: 2117 nlmsg_free(dump_ctx->skb); 2118 return -EMSGSIZE; 2119} 2120EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_prepare); 2121 2122int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx, 2123 struct devlink_dpipe_entry *entry) 2124{ 2125 return devlink_dpipe_entry_put(dump_ctx->skb, entry); 2126} 2127EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_append); 2128 2129int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx) 2130{ 2131 nla_nest_end(dump_ctx->skb, dump_ctx->nest); 2132 genlmsg_end(dump_ctx->skb, dump_ctx->hdr); 2133 return 0; 2134} 2135EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close); 2136 2137void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry) 2138 2139{ 2140 unsigned int value_count, value_index; 2141 struct devlink_dpipe_value *value; 2142 2143 value = entry->action_values; 2144 value_count = entry->action_values_count; 2145 for (value_index = 0; value_index < value_count; value_index++) { 2146 kfree(value[value_index].value); 2147 kfree(value[value_index].mask); 2148 } 2149 2150 value = entry->match_values; 2151 value_count = entry->match_values_count; 2152 for (value_index = 0; value_index < value_count; value_index++) { 2153 kfree(value[value_index].value); 2154 kfree(value[value_index].mask); 2155 } 2156} 2157EXPORT_SYMBOL(devlink_dpipe_entry_clear); 2158 2159static int devlink_dpipe_entries_fill(struct genl_info *info, 2160 enum devlink_command cmd, int flags, 2161 struct devlink_dpipe_table *table) 2162{ 2163 struct devlink_dpipe_dump_ctx dump_ctx; 2164 struct nlmsghdr *nlh; 2165 int err; 2166 2167 dump_ctx.skb = NULL; 2168 dump_ctx.cmd = cmd; 2169 dump_ctx.info = info; 2170 2171 err = table->table_ops->entries_dump(table->priv, 2172 table->counters_enabled, 2173 &dump_ctx); 2174 if (err) 2175 return err; 2176 2177send_done: 2178 nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq, 2179 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2180 if (!nlh) { 2181 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info); 2182 if (err) 2183 return err; 2184 goto send_done; 2185 } 2186 return genlmsg_reply(dump_ctx.skb, info); 2187} 2188 2189static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb, 2190 struct genl_info *info) 2191{ 2192 struct devlink *devlink = info->user_ptr[0]; 2193 struct devlink_dpipe_table *table; 2194 const char *table_name; 2195 2196 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]) 2197 return -EINVAL; 2198 2199 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 2200 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 2201 table_name); 2202 if (!table) 2203 return -EINVAL; 2204 2205 if (!table->table_ops->entries_dump) 2206 return -EINVAL; 2207 2208 return devlink_dpipe_entries_fill(info, DEVLINK_CMD_DPIPE_ENTRIES_GET, 2209 0, table); 2210} 2211 2212static int devlink_dpipe_fields_put(struct sk_buff *skb, 2213 const struct devlink_dpipe_header *header) 2214{ 2215 struct devlink_dpipe_field *field; 2216 struct nlattr *field_attr; 2217 int i; 2218 2219 for (i = 0; i < header->fields_count; i++) { 2220 field = &header->fields[i]; 2221 field_attr = nla_nest_start_noflag(skb, 2222 DEVLINK_ATTR_DPIPE_FIELD); 2223 if (!field_attr) 2224 return -EMSGSIZE; 2225 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_FIELD_NAME, field->name) || 2226 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 2227 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, field->bitwidth) || 2228 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, field->mapping_type)) 2229 goto nla_put_failure; 2230 nla_nest_end(skb, field_attr); 2231 } 2232 return 0; 2233 2234nla_put_failure: 2235 nla_nest_cancel(skb, field_attr); 2236 return -EMSGSIZE; 2237} 2238 2239static int devlink_dpipe_header_put(struct sk_buff *skb, 2240 struct devlink_dpipe_header *header) 2241{ 2242 struct nlattr *fields_attr, *header_attr; 2243 int err; 2244 2245 header_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADER); 2246 if (!header_attr) 2247 return -EMSGSIZE; 2248 2249 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_HEADER_NAME, header->name) || 2250 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 2251 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 2252 goto nla_put_failure; 2253 2254 fields_attr = nla_nest_start_noflag(skb, 2255 DEVLINK_ATTR_DPIPE_HEADER_FIELDS); 2256 if (!fields_attr) 2257 goto nla_put_failure; 2258 2259 err = devlink_dpipe_fields_put(skb, header); 2260 if (err) { 2261 nla_nest_cancel(skb, fields_attr); 2262 goto nla_put_failure; 2263 } 2264 nla_nest_end(skb, fields_attr); 2265 nla_nest_end(skb, header_attr); 2266 return 0; 2267 2268nla_put_failure: 2269 err = -EMSGSIZE; 2270 nla_nest_cancel(skb, header_attr); 2271 return err; 2272} 2273 2274static int devlink_dpipe_headers_fill(struct genl_info *info, 2275 enum devlink_command cmd, int flags, 2276 struct devlink_dpipe_headers * 2277 dpipe_headers) 2278{ 2279 struct devlink *devlink = info->user_ptr[0]; 2280 struct nlattr *headers_attr; 2281 struct sk_buff *skb = NULL; 2282 struct nlmsghdr *nlh; 2283 void *hdr; 2284 int i, j; 2285 int err; 2286 2287 i = 0; 2288start_again: 2289 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2290 if (err) 2291 return err; 2292 2293 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 2294 &devlink_nl_family, NLM_F_MULTI, cmd); 2295 if (!hdr) { 2296 nlmsg_free(skb); 2297 return -EMSGSIZE; 2298 } 2299 2300 if (devlink_nl_put_handle(skb, devlink)) 2301 goto nla_put_failure; 2302 headers_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_DPIPE_HEADERS); 2303 if (!headers_attr) 2304 goto nla_put_failure; 2305 2306 j = 0; 2307 for (; i < dpipe_headers->headers_count; i++) { 2308 err = devlink_dpipe_header_put(skb, dpipe_headers->headers[i]); 2309 if (err) { 2310 if (!j) 2311 goto err_table_put; 2312 break; 2313 } 2314 j++; 2315 } 2316 nla_nest_end(skb, headers_attr); 2317 genlmsg_end(skb, hdr); 2318 if (i != dpipe_headers->headers_count) 2319 goto start_again; 2320 2321send_done: 2322 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 2323 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2324 if (!nlh) { 2325 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2326 if (err) 2327 return err; 2328 goto send_done; 2329 } 2330 return genlmsg_reply(skb, info); 2331 2332nla_put_failure: 2333 err = -EMSGSIZE; 2334err_table_put: 2335 nlmsg_free(skb); 2336 return err; 2337} 2338 2339static int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb, 2340 struct genl_info *info) 2341{ 2342 struct devlink *devlink = info->user_ptr[0]; 2343 2344 if (!devlink->dpipe_headers) 2345 return -EOPNOTSUPP; 2346 return devlink_dpipe_headers_fill(info, DEVLINK_CMD_DPIPE_HEADERS_GET, 2347 0, devlink->dpipe_headers); 2348} 2349 2350static int devlink_dpipe_table_counters_set(struct devlink *devlink, 2351 const char *table_name, 2352 bool enable) 2353{ 2354 struct devlink_dpipe_table *table; 2355 2356 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 2357 table_name); 2358 if (!table) 2359 return -EINVAL; 2360 2361 if (table->counter_control_extern) 2362 return -EOPNOTSUPP; 2363 2364 if (!(table->counters_enabled ^ enable)) 2365 return 0; 2366 2367 table->counters_enabled = enable; 2368 if (table->table_ops->counters_set_update) 2369 table->table_ops->counters_set_update(table->priv, enable); 2370 return 0; 2371} 2372 2373static int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb, 2374 struct genl_info *info) 2375{ 2376 struct devlink *devlink = info->user_ptr[0]; 2377 const char *table_name; 2378 bool counters_enable; 2379 2380 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME] || 2381 !info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]) 2382 return -EINVAL; 2383 2384 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 2385 counters_enable = !!nla_get_u8(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]); 2386 2387 return devlink_dpipe_table_counters_set(devlink, table_name, 2388 counters_enable); 2389} 2390 2391static struct devlink_resource * 2392devlink_resource_find(struct devlink *devlink, 2393 struct devlink_resource *resource, u64 resource_id) 2394{ 2395 struct list_head *resource_list; 2396 2397 if (resource) 2398 resource_list = &resource->resource_list; 2399 else 2400 resource_list = &devlink->resource_list; 2401 2402 list_for_each_entry(resource, resource_list, list) { 2403 struct devlink_resource *child_resource; 2404 2405 if (resource->id == resource_id) 2406 return resource; 2407 2408 child_resource = devlink_resource_find(devlink, resource, 2409 resource_id); 2410 if (child_resource) 2411 return child_resource; 2412 } 2413 return NULL; 2414} 2415 2416static void 2417devlink_resource_validate_children(struct devlink_resource *resource) 2418{ 2419 struct devlink_resource *child_resource; 2420 bool size_valid = true; 2421 u64 parts_size = 0; 2422 2423 if (list_empty(&resource->resource_list)) 2424 goto out; 2425 2426 list_for_each_entry(child_resource, &resource->resource_list, list) 2427 parts_size += child_resource->size_new; 2428 2429 if (parts_size > resource->size_new) 2430 size_valid = false; 2431out: 2432 resource->size_valid = size_valid; 2433} 2434 2435static int 2436devlink_resource_validate_size(struct devlink_resource *resource, u64 size, 2437 struct netlink_ext_ack *extack) 2438{ 2439 u64 reminder; 2440 int err = 0; 2441 2442 if (size > resource->size_params.size_max) { 2443 NL_SET_ERR_MSG_MOD(extack, "Size larger than maximum"); 2444 err = -EINVAL; 2445 } 2446 2447 if (size < resource->size_params.size_min) { 2448 NL_SET_ERR_MSG_MOD(extack, "Size smaller than minimum"); 2449 err = -EINVAL; 2450 } 2451 2452 div64_u64_rem(size, resource->size_params.size_granularity, &reminder); 2453 if (reminder) { 2454 NL_SET_ERR_MSG_MOD(extack, "Wrong granularity"); 2455 err = -EINVAL; 2456 } 2457 2458 return err; 2459} 2460 2461static int devlink_nl_cmd_resource_set(struct sk_buff *skb, 2462 struct genl_info *info) 2463{ 2464 struct devlink *devlink = info->user_ptr[0]; 2465 struct devlink_resource *resource; 2466 u64 resource_id; 2467 u64 size; 2468 int err; 2469 2470 if (!info->attrs[DEVLINK_ATTR_RESOURCE_ID] || 2471 !info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]) 2472 return -EINVAL; 2473 resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]); 2474 2475 resource = devlink_resource_find(devlink, NULL, resource_id); 2476 if (!resource) 2477 return -EINVAL; 2478 2479 size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]); 2480 err = devlink_resource_validate_size(resource, size, info->extack); 2481 if (err) 2482 return err; 2483 2484 resource->size_new = size; 2485 devlink_resource_validate_children(resource); 2486 if (resource->parent) 2487 devlink_resource_validate_children(resource->parent); 2488 return 0; 2489} 2490 2491static int 2492devlink_resource_size_params_put(struct devlink_resource *resource, 2493 struct sk_buff *skb) 2494{ 2495 struct devlink_resource_size_params *size_params; 2496 2497 size_params = &resource->size_params; 2498 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN, 2499 size_params->size_granularity, DEVLINK_ATTR_PAD) || 2500 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX, 2501 size_params->size_max, DEVLINK_ATTR_PAD) || 2502 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN, 2503 size_params->size_min, DEVLINK_ATTR_PAD) || 2504 nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit)) 2505 return -EMSGSIZE; 2506 return 0; 2507} 2508 2509static int devlink_resource_occ_put(struct devlink_resource *resource, 2510 struct sk_buff *skb) 2511{ 2512 if (!resource->occ_get) 2513 return 0; 2514 return nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC, 2515 resource->occ_get(resource->occ_get_priv), 2516 DEVLINK_ATTR_PAD); 2517} 2518 2519static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb, 2520 struct devlink_resource *resource) 2521{ 2522 struct devlink_resource *child_resource; 2523 struct nlattr *child_resource_attr; 2524 struct nlattr *resource_attr; 2525 2526 resource_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_RESOURCE); 2527 if (!resource_attr) 2528 return -EMSGSIZE; 2529 2530 if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) || 2531 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size, 2532 DEVLINK_ATTR_PAD) || 2533 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id, 2534 DEVLINK_ATTR_PAD)) 2535 goto nla_put_failure; 2536 if (resource->size != resource->size_new) 2537 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW, 2538 resource->size_new, DEVLINK_ATTR_PAD); 2539 if (devlink_resource_occ_put(resource, skb)) 2540 goto nla_put_failure; 2541 if (devlink_resource_size_params_put(resource, skb)) 2542 goto nla_put_failure; 2543 if (list_empty(&resource->resource_list)) 2544 goto out; 2545 2546 if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID, 2547 resource->size_valid)) 2548 goto nla_put_failure; 2549 2550 child_resource_attr = nla_nest_start_noflag(skb, 2551 DEVLINK_ATTR_RESOURCE_LIST); 2552 if (!child_resource_attr) 2553 goto nla_put_failure; 2554 2555 list_for_each_entry(child_resource, &resource->resource_list, list) { 2556 if (devlink_resource_put(devlink, skb, child_resource)) 2557 goto resource_put_failure; 2558 } 2559 2560 nla_nest_end(skb, child_resource_attr); 2561out: 2562 nla_nest_end(skb, resource_attr); 2563 return 0; 2564 2565resource_put_failure: 2566 nla_nest_cancel(skb, child_resource_attr); 2567nla_put_failure: 2568 nla_nest_cancel(skb, resource_attr); 2569 return -EMSGSIZE; 2570} 2571 2572static int devlink_resource_fill(struct genl_info *info, 2573 enum devlink_command cmd, int flags) 2574{ 2575 struct devlink *devlink = info->user_ptr[0]; 2576 struct devlink_resource *resource; 2577 struct nlattr *resources_attr; 2578 struct sk_buff *skb = NULL; 2579 struct nlmsghdr *nlh; 2580 bool incomplete; 2581 void *hdr; 2582 int i; 2583 int err; 2584 2585 resource = list_first_entry(&devlink->resource_list, 2586 struct devlink_resource, list); 2587start_again: 2588 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2589 if (err) 2590 return err; 2591 2592 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 2593 &devlink_nl_family, NLM_F_MULTI, cmd); 2594 if (!hdr) { 2595 nlmsg_free(skb); 2596 return -EMSGSIZE; 2597 } 2598 2599 if (devlink_nl_put_handle(skb, devlink)) 2600 goto nla_put_failure; 2601 2602 resources_attr = nla_nest_start_noflag(skb, 2603 DEVLINK_ATTR_RESOURCE_LIST); 2604 if (!resources_attr) 2605 goto nla_put_failure; 2606 2607 incomplete = false; 2608 i = 0; 2609 list_for_each_entry_from(resource, &devlink->resource_list, list) { 2610 err = devlink_resource_put(devlink, skb, resource); 2611 if (err) { 2612 if (!i) 2613 goto err_resource_put; 2614 incomplete = true; 2615 break; 2616 } 2617 i++; 2618 } 2619 nla_nest_end(skb, resources_attr); 2620 genlmsg_end(skb, hdr); 2621 if (incomplete) 2622 goto start_again; 2623send_done: 2624 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 2625 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2626 if (!nlh) { 2627 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2628 if (err) 2629 return err; 2630 goto send_done; 2631 } 2632 return genlmsg_reply(skb, info); 2633 2634nla_put_failure: 2635 err = -EMSGSIZE; 2636err_resource_put: 2637 nlmsg_free(skb); 2638 return err; 2639} 2640 2641static int devlink_nl_cmd_resource_dump(struct sk_buff *skb, 2642 struct genl_info *info) 2643{ 2644 struct devlink *devlink = info->user_ptr[0]; 2645 2646 if (list_empty(&devlink->resource_list)) 2647 return -EOPNOTSUPP; 2648 2649 return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0); 2650} 2651 2652static int 2653devlink_resources_validate(struct devlink *devlink, 2654 struct devlink_resource *resource, 2655 struct genl_info *info) 2656{ 2657 struct list_head *resource_list; 2658 int err = 0; 2659 2660 if (resource) 2661 resource_list = &resource->resource_list; 2662 else 2663 resource_list = &devlink->resource_list; 2664 2665 list_for_each_entry(resource, resource_list, list) { 2666 if (!resource->size_valid) 2667 return -EINVAL; 2668 err = devlink_resources_validate(devlink, resource, info); 2669 if (err) 2670 return err; 2671 } 2672 return err; 2673} 2674 2675static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info) 2676{ 2677 struct devlink *devlink = info->user_ptr[0]; 2678 int err; 2679 2680 if (!devlink->ops->reload) 2681 return -EOPNOTSUPP; 2682 2683 err = devlink_resources_validate(devlink, NULL, info); 2684 if (err) { 2685 NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed"); 2686 return err; 2687 } 2688 return devlink->ops->reload(devlink, info->extack); 2689} 2690 2691static int devlink_nl_flash_update_fill(struct sk_buff *msg, 2692 struct devlink *devlink, 2693 enum devlink_command cmd, 2694 const char *status_msg, 2695 const char *component, 2696 unsigned long done, unsigned long total) 2697{ 2698 void *hdr; 2699 2700 hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd); 2701 if (!hdr) 2702 return -EMSGSIZE; 2703 2704 if (devlink_nl_put_handle(msg, devlink)) 2705 goto nla_put_failure; 2706 2707 if (cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS) 2708 goto out; 2709 2710 if (status_msg && 2711 nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_MSG, 2712 status_msg)) 2713 goto nla_put_failure; 2714 if (component && 2715 nla_put_string(msg, DEVLINK_ATTR_FLASH_UPDATE_COMPONENT, 2716 component)) 2717 goto nla_put_failure; 2718 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_DONE, 2719 done, DEVLINK_ATTR_PAD)) 2720 goto nla_put_failure; 2721 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_FLASH_UPDATE_STATUS_TOTAL, 2722 total, DEVLINK_ATTR_PAD)) 2723 goto nla_put_failure; 2724 2725out: 2726 genlmsg_end(msg, hdr); 2727 return 0; 2728 2729nla_put_failure: 2730 genlmsg_cancel(msg, hdr); 2731 return -EMSGSIZE; 2732} 2733 2734static void __devlink_flash_update_notify(struct devlink *devlink, 2735 enum devlink_command cmd, 2736 const char *status_msg, 2737 const char *component, 2738 unsigned long done, 2739 unsigned long total) 2740{ 2741 struct sk_buff *msg; 2742 int err; 2743 2744 WARN_ON(cmd != DEVLINK_CMD_FLASH_UPDATE && 2745 cmd != DEVLINK_CMD_FLASH_UPDATE_END && 2746 cmd != DEVLINK_CMD_FLASH_UPDATE_STATUS); 2747 2748 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 2749 if (!msg) 2750 return; 2751 2752 err = devlink_nl_flash_update_fill(msg, devlink, cmd, status_msg, 2753 component, done, total); 2754 if (err) 2755 goto out_free_msg; 2756 2757 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 2758 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 2759 return; 2760 2761out_free_msg: 2762 nlmsg_free(msg); 2763} 2764 2765void devlink_flash_update_begin_notify(struct devlink *devlink) 2766{ 2767 __devlink_flash_update_notify(devlink, 2768 DEVLINK_CMD_FLASH_UPDATE, 2769 NULL, NULL, 0, 0); 2770} 2771EXPORT_SYMBOL_GPL(devlink_flash_update_begin_notify); 2772 2773void devlink_flash_update_end_notify(struct devlink *devlink) 2774{ 2775 __devlink_flash_update_notify(devlink, 2776 DEVLINK_CMD_FLASH_UPDATE_END, 2777 NULL, NULL, 0, 0); 2778} 2779EXPORT_SYMBOL_GPL(devlink_flash_update_end_notify); 2780 2781void devlink_flash_update_status_notify(struct devlink *devlink, 2782 const char *status_msg, 2783 const char *component, 2784 unsigned long done, 2785 unsigned long total) 2786{ 2787 __devlink_flash_update_notify(devlink, 2788 DEVLINK_CMD_FLASH_UPDATE_STATUS, 2789 status_msg, component, done, total); 2790} 2791EXPORT_SYMBOL_GPL(devlink_flash_update_status_notify); 2792 2793static int devlink_nl_cmd_flash_update(struct sk_buff *skb, 2794 struct genl_info *info) 2795{ 2796 struct devlink *devlink = info->user_ptr[0]; 2797 const char *file_name, *component; 2798 struct nlattr *nla_component; 2799 2800 if (!devlink->ops->flash_update) 2801 return -EOPNOTSUPP; 2802 2803 if (!info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME]) 2804 return -EINVAL; 2805 file_name = nla_data(info->attrs[DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME]); 2806 2807 nla_component = info->attrs[DEVLINK_ATTR_FLASH_UPDATE_COMPONENT]; 2808 component = nla_component ? nla_data(nla_component) : NULL; 2809 2810 return devlink->ops->flash_update(devlink, file_name, component, 2811 info->extack); 2812} 2813 2814static const struct devlink_param devlink_param_generic[] = { 2815 { 2816 .id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET, 2817 .name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME, 2818 .type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE, 2819 }, 2820 { 2821 .id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS, 2822 .name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME, 2823 .type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE, 2824 }, 2825 { 2826 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV, 2827 .name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME, 2828 .type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE, 2829 }, 2830 { 2831 .id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT, 2832 .name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME, 2833 .type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE, 2834 }, 2835 { 2836 .id = DEVLINK_PARAM_GENERIC_ID_IGNORE_ARI, 2837 .name = DEVLINK_PARAM_GENERIC_IGNORE_ARI_NAME, 2838 .type = DEVLINK_PARAM_GENERIC_IGNORE_ARI_TYPE, 2839 }, 2840 { 2841 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MAX, 2842 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_NAME, 2843 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MAX_TYPE, 2844 }, 2845 { 2846 .id = DEVLINK_PARAM_GENERIC_ID_MSIX_VEC_PER_PF_MIN, 2847 .name = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_NAME, 2848 .type = DEVLINK_PARAM_GENERIC_MSIX_VEC_PER_PF_MIN_TYPE, 2849 }, 2850 { 2851 .id = DEVLINK_PARAM_GENERIC_ID_FW_LOAD_POLICY, 2852 .name = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_NAME, 2853 .type = DEVLINK_PARAM_GENERIC_FW_LOAD_POLICY_TYPE, 2854 }, 2855}; 2856 2857static int devlink_param_generic_verify(const struct devlink_param *param) 2858{ 2859 /* verify it match generic parameter by id and name */ 2860 if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX) 2861 return -EINVAL; 2862 if (strcmp(param->name, devlink_param_generic[param->id].name)) 2863 return -ENOENT; 2864 2865 WARN_ON(param->type != devlink_param_generic[param->id].type); 2866 2867 return 0; 2868} 2869 2870static int devlink_param_driver_verify(const struct devlink_param *param) 2871{ 2872 int i; 2873 2874 if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX) 2875 return -EINVAL; 2876 /* verify no such name in generic params */ 2877 for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++) 2878 if (!strcmp(param->name, devlink_param_generic[i].name)) 2879 return -EEXIST; 2880 2881 return 0; 2882} 2883 2884static struct devlink_param_item * 2885devlink_param_find_by_name(struct list_head *param_list, 2886 const char *param_name) 2887{ 2888 struct devlink_param_item *param_item; 2889 2890 list_for_each_entry(param_item, param_list, list) 2891 if (!strcmp(param_item->param->name, param_name)) 2892 return param_item; 2893 return NULL; 2894} 2895 2896static struct devlink_param_item * 2897devlink_param_find_by_id(struct list_head *param_list, u32 param_id) 2898{ 2899 struct devlink_param_item *param_item; 2900 2901 list_for_each_entry(param_item, param_list, list) 2902 if (param_item->param->id == param_id) 2903 return param_item; 2904 return NULL; 2905} 2906 2907static bool 2908devlink_param_cmode_is_supported(const struct devlink_param *param, 2909 enum devlink_param_cmode cmode) 2910{ 2911 return test_bit(cmode, &param->supported_cmodes); 2912} 2913 2914static int devlink_param_get(struct devlink *devlink, 2915 const struct devlink_param *param, 2916 struct devlink_param_gset_ctx *ctx) 2917{ 2918 if (!param->get) 2919 return -EOPNOTSUPP; 2920 return param->get(devlink, param->id, ctx); 2921} 2922 2923static int devlink_param_set(struct devlink *devlink, 2924 const struct devlink_param *param, 2925 struct devlink_param_gset_ctx *ctx) 2926{ 2927 if (!param->set) 2928 return -EOPNOTSUPP; 2929 return param->set(devlink, param->id, ctx); 2930} 2931 2932static int 2933devlink_param_type_to_nla_type(enum devlink_param_type param_type) 2934{ 2935 switch (param_type) { 2936 case DEVLINK_PARAM_TYPE_U8: 2937 return NLA_U8; 2938 case DEVLINK_PARAM_TYPE_U16: 2939 return NLA_U16; 2940 case DEVLINK_PARAM_TYPE_U32: 2941 return NLA_U32; 2942 case DEVLINK_PARAM_TYPE_STRING: 2943 return NLA_STRING; 2944 case DEVLINK_PARAM_TYPE_BOOL: 2945 return NLA_FLAG; 2946 default: 2947 return -EINVAL; 2948 } 2949} 2950 2951static int 2952devlink_nl_param_value_fill_one(struct sk_buff *msg, 2953 enum devlink_param_type type, 2954 enum devlink_param_cmode cmode, 2955 union devlink_param_value val) 2956{ 2957 struct nlattr *param_value_attr; 2958 2959 param_value_attr = nla_nest_start_noflag(msg, 2960 DEVLINK_ATTR_PARAM_VALUE); 2961 if (!param_value_attr) 2962 goto nla_put_failure; 2963 2964 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode)) 2965 goto value_nest_cancel; 2966 2967 switch (type) { 2968 case DEVLINK_PARAM_TYPE_U8: 2969 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8)) 2970 goto value_nest_cancel; 2971 break; 2972 case DEVLINK_PARAM_TYPE_U16: 2973 if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16)) 2974 goto value_nest_cancel; 2975 break; 2976 case DEVLINK_PARAM_TYPE_U32: 2977 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32)) 2978 goto value_nest_cancel; 2979 break; 2980 case DEVLINK_PARAM_TYPE_STRING: 2981 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, 2982 val.vstr)) 2983 goto value_nest_cancel; 2984 break; 2985 case DEVLINK_PARAM_TYPE_BOOL: 2986 if (val.vbool && 2987 nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA)) 2988 goto value_nest_cancel; 2989 break; 2990 } 2991 2992 nla_nest_end(msg, param_value_attr); 2993 return 0; 2994 2995value_nest_cancel: 2996 nla_nest_cancel(msg, param_value_attr); 2997nla_put_failure: 2998 return -EMSGSIZE; 2999} 3000 3001static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, 3002 unsigned int port_index, 3003 struct devlink_param_item *param_item, 3004 enum devlink_command cmd, 3005 u32 portid, u32 seq, int flags) 3006{ 3007 union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1]; 3008 bool param_value_set[DEVLINK_PARAM_CMODE_MAX + 1] = {}; 3009 const struct devlink_param *param = param_item->param; 3010 struct devlink_param_gset_ctx ctx; 3011 struct nlattr *param_values_list; 3012 struct nlattr *param_attr; 3013 int nla_type; 3014 void *hdr; 3015 int err; 3016 int i; 3017 3018 /* Get value from driver part to driverinit configuration mode */ 3019 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 3020 if (!devlink_param_cmode_is_supported(param, i)) 3021 continue; 3022 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) { 3023 if (!param_item->driverinit_value_valid) 3024 return -EOPNOTSUPP; 3025 param_value[i] = param_item->driverinit_value; 3026 } else { 3027 if (!param_item->published) 3028 continue; 3029 ctx.cmode = i; 3030 err = devlink_param_get(devlink, param, &ctx); 3031 if (err) 3032 return err; 3033 param_value[i] = ctx.val; 3034 } 3035 param_value_set[i] = true; 3036 } 3037 3038 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 3039 if (!hdr) 3040 return -EMSGSIZE; 3041 3042 if (devlink_nl_put_handle(msg, devlink)) 3043 goto genlmsg_cancel; 3044 3045 if (cmd == DEVLINK_CMD_PORT_PARAM_GET || 3046 cmd == DEVLINK_CMD_PORT_PARAM_NEW || 3047 cmd == DEVLINK_CMD_PORT_PARAM_DEL) 3048 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, port_index)) 3049 goto genlmsg_cancel; 3050 3051 param_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_PARAM); 3052 if (!param_attr) 3053 goto genlmsg_cancel; 3054 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name)) 3055 goto param_nest_cancel; 3056 if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC)) 3057 goto param_nest_cancel; 3058 3059 nla_type = devlink_param_type_to_nla_type(param->type); 3060 if (nla_type < 0) 3061 goto param_nest_cancel; 3062 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type)) 3063 goto param_nest_cancel; 3064 3065 param_values_list = nla_nest_start_noflag(msg, 3066 DEVLINK_ATTR_PARAM_VALUES_LIST); 3067 if (!param_values_list) 3068 goto param_nest_cancel; 3069 3070 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 3071 if (!param_value_set[i]) 3072 continue; 3073 err = devlink_nl_param_value_fill_one(msg, param->type, 3074 i, param_value[i]); 3075 if (err) 3076 goto values_list_nest_cancel; 3077 } 3078 3079 nla_nest_end(msg, param_values_list); 3080 nla_nest_end(msg, param_attr); 3081 genlmsg_end(msg, hdr); 3082 return 0; 3083 3084values_list_nest_cancel: 3085 nla_nest_end(msg, param_values_list); 3086param_nest_cancel: 3087 nla_nest_cancel(msg, param_attr); 3088genlmsg_cancel: 3089 genlmsg_cancel(msg, hdr); 3090 return -EMSGSIZE; 3091} 3092 3093static void devlink_param_notify(struct devlink *devlink, 3094 unsigned int port_index, 3095 struct devlink_param_item *param_item, 3096 enum devlink_command cmd) 3097{ 3098 struct sk_buff *msg; 3099 int err; 3100 3101 WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL && 3102 cmd != DEVLINK_CMD_PORT_PARAM_NEW && 3103 cmd != DEVLINK_CMD_PORT_PARAM_DEL); 3104 3105 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3106 if (!msg) 3107 return; 3108 err = devlink_nl_param_fill(msg, devlink, port_index, param_item, cmd, 3109 0, 0, 0); 3110 if (err) { 3111 nlmsg_free(msg); 3112 return; 3113 } 3114 3115 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 3116 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 3117} 3118 3119static int devlink_nl_cmd_param_get_dumpit(struct sk_buff *msg, 3120 struct netlink_callback *cb) 3121{ 3122 struct devlink_param_item *param_item; 3123 struct devlink *devlink; 3124 int start = cb->args[0]; 3125 int idx = 0; 3126 int err; 3127 3128 mutex_lock(&devlink_mutex); 3129 list_for_each_entry(devlink, &devlink_list, list) { 3130 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 3131 continue; 3132 mutex_lock(&devlink->lock); 3133 list_for_each_entry(param_item, &devlink->param_list, list) { 3134 if (idx < start) { 3135 idx++; 3136 continue; 3137 } 3138 err = devlink_nl_param_fill(msg, devlink, 0, param_item, 3139 DEVLINK_CMD_PARAM_GET, 3140 NETLINK_CB(cb->skb).portid, 3141 cb->nlh->nlmsg_seq, 3142 NLM_F_MULTI); 3143 if (err) { 3144 mutex_unlock(&devlink->lock); 3145 goto out; 3146 } 3147 idx++; 3148 } 3149 mutex_unlock(&devlink->lock); 3150 } 3151out: 3152 mutex_unlock(&devlink_mutex); 3153 3154 cb->args[0] = idx; 3155 return msg->len; 3156} 3157 3158static int 3159devlink_param_type_get_from_info(struct genl_info *info, 3160 enum devlink_param_type *param_type) 3161{ 3162 if (!info->attrs[DEVLINK_ATTR_PARAM_TYPE]) 3163 return -EINVAL; 3164 3165 switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) { 3166 case NLA_U8: 3167 *param_type = DEVLINK_PARAM_TYPE_U8; 3168 break; 3169 case NLA_U16: 3170 *param_type = DEVLINK_PARAM_TYPE_U16; 3171 break; 3172 case NLA_U32: 3173 *param_type = DEVLINK_PARAM_TYPE_U32; 3174 break; 3175 case NLA_STRING: 3176 *param_type = DEVLINK_PARAM_TYPE_STRING; 3177 break; 3178 case NLA_FLAG: 3179 *param_type = DEVLINK_PARAM_TYPE_BOOL; 3180 break; 3181 default: 3182 return -EINVAL; 3183 } 3184 3185 return 0; 3186} 3187 3188static int 3189devlink_param_value_get_from_info(const struct devlink_param *param, 3190 struct genl_info *info, 3191 union devlink_param_value *value) 3192{ 3193 int len; 3194 3195 if (param->type != DEVLINK_PARAM_TYPE_BOOL && 3196 !info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) 3197 return -EINVAL; 3198 3199 switch (param->type) { 3200 case DEVLINK_PARAM_TYPE_U8: 3201 value->vu8 = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3202 break; 3203 case DEVLINK_PARAM_TYPE_U16: 3204 value->vu16 = nla_get_u16(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3205 break; 3206 case DEVLINK_PARAM_TYPE_U32: 3207 value->vu32 = nla_get_u32(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3208 break; 3209 case DEVLINK_PARAM_TYPE_STRING: 3210 len = strnlen(nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]), 3211 nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])); 3212 if (len == nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) || 3213 len >= __DEVLINK_PARAM_MAX_STRING_VALUE) 3214 return -EINVAL; 3215 strcpy(value->vstr, 3216 nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])); 3217 break; 3218 case DEVLINK_PARAM_TYPE_BOOL: 3219 value->vbool = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA] ? 3220 true : false; 3221 break; 3222 } 3223 return 0; 3224} 3225 3226static struct devlink_param_item * 3227devlink_param_get_from_info(struct list_head *param_list, 3228 struct genl_info *info) 3229{ 3230 char *param_name; 3231 3232 if (!info->attrs[DEVLINK_ATTR_PARAM_NAME]) 3233 return NULL; 3234 3235 param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]); 3236 return devlink_param_find_by_name(param_list, param_name); 3237} 3238 3239static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb, 3240 struct genl_info *info) 3241{ 3242 struct devlink *devlink = info->user_ptr[0]; 3243 struct devlink_param_item *param_item; 3244 struct sk_buff *msg; 3245 int err; 3246 3247 param_item = devlink_param_get_from_info(&devlink->param_list, info); 3248 if (!param_item) 3249 return -EINVAL; 3250 3251 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3252 if (!msg) 3253 return -ENOMEM; 3254 3255 err = devlink_nl_param_fill(msg, devlink, 0, param_item, 3256 DEVLINK_CMD_PARAM_GET, 3257 info->snd_portid, info->snd_seq, 0); 3258 if (err) { 3259 nlmsg_free(msg); 3260 return err; 3261 } 3262 3263 return genlmsg_reply(msg, info); 3264} 3265 3266static int __devlink_nl_cmd_param_set_doit(struct devlink *devlink, 3267 unsigned int port_index, 3268 struct list_head *param_list, 3269 struct genl_info *info, 3270 enum devlink_command cmd) 3271{ 3272 enum devlink_param_type param_type; 3273 struct devlink_param_gset_ctx ctx; 3274 enum devlink_param_cmode cmode; 3275 struct devlink_param_item *param_item; 3276 const struct devlink_param *param; 3277 union devlink_param_value value; 3278 int err = 0; 3279 3280 param_item = devlink_param_get_from_info(param_list, info); 3281 if (!param_item) 3282 return -EINVAL; 3283 param = param_item->param; 3284 err = devlink_param_type_get_from_info(info, &param_type); 3285 if (err) 3286 return err; 3287 if (param_type != param->type) 3288 return -EINVAL; 3289 err = devlink_param_value_get_from_info(param, info, &value); 3290 if (err) 3291 return err; 3292 if (param->validate) { 3293 err = param->validate(devlink, param->id, value, info->extack); 3294 if (err) 3295 return err; 3296 } 3297 3298 if (!info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]) 3299 return -EINVAL; 3300 cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]); 3301 if (!devlink_param_cmode_is_supported(param, cmode)) 3302 return -EOPNOTSUPP; 3303 3304 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) { 3305 if (param->type == DEVLINK_PARAM_TYPE_STRING) 3306 strcpy(param_item->driverinit_value.vstr, value.vstr); 3307 else 3308 param_item->driverinit_value = value; 3309 param_item->driverinit_value_valid = true; 3310 } else { 3311 if (!param->set) 3312 return -EOPNOTSUPP; 3313 ctx.val = value; 3314 ctx.cmode = cmode; 3315 err = devlink_param_set(devlink, param, &ctx); 3316 if (err) 3317 return err; 3318 } 3319 3320 devlink_param_notify(devlink, port_index, param_item, cmd); 3321 return 0; 3322} 3323 3324static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb, 3325 struct genl_info *info) 3326{ 3327 struct devlink *devlink = info->user_ptr[0]; 3328 3329 return __devlink_nl_cmd_param_set_doit(devlink, 0, &devlink->param_list, 3330 info, DEVLINK_CMD_PARAM_NEW); 3331} 3332 3333static int devlink_param_register_one(struct devlink *devlink, 3334 unsigned int port_index, 3335 struct list_head *param_list, 3336 const struct devlink_param *param, 3337 enum devlink_command cmd) 3338{ 3339 struct devlink_param_item *param_item; 3340 3341 if (devlink_param_find_by_name(param_list, param->name)) 3342 return -EEXIST; 3343 3344 if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT)) 3345 WARN_ON(param->get || param->set); 3346 else 3347 WARN_ON(!param->get || !param->set); 3348 3349 param_item = kzalloc(sizeof(*param_item), GFP_KERNEL); 3350 if (!param_item) 3351 return -ENOMEM; 3352 param_item->param = param; 3353 3354 list_add_tail(&param_item->list, param_list); 3355 devlink_param_notify(devlink, port_index, param_item, cmd); 3356 return 0; 3357} 3358 3359static void devlink_param_unregister_one(struct devlink *devlink, 3360 unsigned int port_index, 3361 struct list_head *param_list, 3362 const struct devlink_param *param, 3363 enum devlink_command cmd) 3364{ 3365 struct devlink_param_item *param_item; 3366 3367 param_item = devlink_param_find_by_name(param_list, param->name); 3368 WARN_ON(!param_item); 3369 devlink_param_notify(devlink, port_index, param_item, cmd); 3370 list_del(&param_item->list); 3371 kfree(param_item); 3372} 3373 3374static int devlink_nl_cmd_port_param_get_dumpit(struct sk_buff *msg, 3375 struct netlink_callback *cb) 3376{ 3377 struct devlink_param_item *param_item; 3378 struct devlink_port *devlink_port; 3379 struct devlink *devlink; 3380 int start = cb->args[0]; 3381 int idx = 0; 3382 int err; 3383 3384 mutex_lock(&devlink_mutex); 3385 list_for_each_entry(devlink, &devlink_list, list) { 3386 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 3387 continue; 3388 mutex_lock(&devlink->lock); 3389 list_for_each_entry(devlink_port, &devlink->port_list, list) { 3390 list_for_each_entry(param_item, 3391 &devlink_port->param_list, list) { 3392 if (idx < start) { 3393 idx++; 3394 continue; 3395 } 3396 err = devlink_nl_param_fill(msg, 3397 devlink_port->devlink, 3398 devlink_port->index, param_item, 3399 DEVLINK_CMD_PORT_PARAM_GET, 3400 NETLINK_CB(cb->skb).portid, 3401 cb->nlh->nlmsg_seq, 3402 NLM_F_MULTI); 3403 if (err) { 3404 mutex_unlock(&devlink->lock); 3405 goto out; 3406 } 3407 idx++; 3408 } 3409 } 3410 mutex_unlock(&devlink->lock); 3411 } 3412out: 3413 mutex_unlock(&devlink_mutex); 3414 3415 cb->args[0] = idx; 3416 return msg->len; 3417} 3418 3419static int devlink_nl_cmd_port_param_get_doit(struct sk_buff *skb, 3420 struct genl_info *info) 3421{ 3422 struct devlink_port *devlink_port = info->user_ptr[0]; 3423 struct devlink_param_item *param_item; 3424 struct sk_buff *msg; 3425 int err; 3426 3427 param_item = devlink_param_get_from_info(&devlink_port->param_list, 3428 info); 3429 if (!param_item) 3430 return -EINVAL; 3431 3432 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3433 if (!msg) 3434 return -ENOMEM; 3435 3436 err = devlink_nl_param_fill(msg, devlink_port->devlink, 3437 devlink_port->index, param_item, 3438 DEVLINK_CMD_PORT_PARAM_GET, 3439 info->snd_portid, info->snd_seq, 0); 3440 if (err) { 3441 nlmsg_free(msg); 3442 return err; 3443 } 3444 3445 return genlmsg_reply(msg, info); 3446} 3447 3448static int devlink_nl_cmd_port_param_set_doit(struct sk_buff *skb, 3449 struct genl_info *info) 3450{ 3451 struct devlink_port *devlink_port = info->user_ptr[0]; 3452 3453 return __devlink_nl_cmd_param_set_doit(devlink_port->devlink, 3454 devlink_port->index, 3455 &devlink_port->param_list, info, 3456 DEVLINK_CMD_PORT_PARAM_NEW); 3457} 3458 3459static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg, 3460 struct devlink *devlink, 3461 struct devlink_snapshot *snapshot) 3462{ 3463 struct nlattr *snap_attr; 3464 int err; 3465 3466 snap_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_SNAPSHOT); 3467 if (!snap_attr) 3468 return -EINVAL; 3469 3470 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id); 3471 if (err) 3472 goto nla_put_failure; 3473 3474 nla_nest_end(msg, snap_attr); 3475 return 0; 3476 3477nla_put_failure: 3478 nla_nest_cancel(msg, snap_attr); 3479 return err; 3480} 3481 3482static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg, 3483 struct devlink *devlink, 3484 struct devlink_region *region) 3485{ 3486 struct devlink_snapshot *snapshot; 3487 struct nlattr *snapshots_attr; 3488 int err; 3489 3490 snapshots_attr = nla_nest_start_noflag(msg, 3491 DEVLINK_ATTR_REGION_SNAPSHOTS); 3492 if (!snapshots_attr) 3493 return -EINVAL; 3494 3495 list_for_each_entry(snapshot, &region->snapshot_list, list) { 3496 err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot); 3497 if (err) 3498 goto nla_put_failure; 3499 } 3500 3501 nla_nest_end(msg, snapshots_attr); 3502 return 0; 3503 3504nla_put_failure: 3505 nla_nest_cancel(msg, snapshots_attr); 3506 return err; 3507} 3508 3509static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink, 3510 enum devlink_command cmd, u32 portid, 3511 u32 seq, int flags, 3512 struct devlink_region *region) 3513{ 3514 void *hdr; 3515 int err; 3516 3517 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 3518 if (!hdr) 3519 return -EMSGSIZE; 3520 3521 err = devlink_nl_put_handle(msg, devlink); 3522 if (err) 3523 goto nla_put_failure; 3524 3525 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->name); 3526 if (err) 3527 goto nla_put_failure; 3528 3529 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE, 3530 region->size, 3531 DEVLINK_ATTR_PAD); 3532 if (err) 3533 goto nla_put_failure; 3534 3535 err = devlink_nl_region_snapshots_id_put(msg, devlink, region); 3536 if (err) 3537 goto nla_put_failure; 3538 3539 genlmsg_end(msg, hdr); 3540 return 0; 3541 3542nla_put_failure: 3543 genlmsg_cancel(msg, hdr); 3544 return err; 3545} 3546 3547static void devlink_nl_region_notify(struct devlink_region *region, 3548 struct devlink_snapshot *snapshot, 3549 enum devlink_command cmd) 3550{ 3551 struct devlink *devlink = region->devlink; 3552 struct sk_buff *msg; 3553 void *hdr; 3554 int err; 3555 3556 WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL); 3557 3558 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3559 if (!msg) 3560 return; 3561 3562 hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd); 3563 if (!hdr) 3564 goto out_free_msg; 3565 3566 err = devlink_nl_put_handle(msg, devlink); 3567 if (err) 3568 goto out_cancel_msg; 3569 3570 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, 3571 region->name); 3572 if (err) 3573 goto out_cancel_msg; 3574 3575 if (snapshot) { 3576 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, 3577 snapshot->id); 3578 if (err) 3579 goto out_cancel_msg; 3580 } else { 3581 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE, 3582 region->size, DEVLINK_ATTR_PAD); 3583 if (err) 3584 goto out_cancel_msg; 3585 } 3586 genlmsg_end(msg, hdr); 3587 3588 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 3589 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 3590 3591 return; 3592 3593out_cancel_msg: 3594 genlmsg_cancel(msg, hdr); 3595out_free_msg: 3596 nlmsg_free(msg); 3597} 3598 3599static int devlink_nl_cmd_region_get_doit(struct sk_buff *skb, 3600 struct genl_info *info) 3601{ 3602 struct devlink *devlink = info->user_ptr[0]; 3603 struct devlink_region *region; 3604 const char *region_name; 3605 struct sk_buff *msg; 3606 int err; 3607 3608 if (!info->attrs[DEVLINK_ATTR_REGION_NAME]) 3609 return -EINVAL; 3610 3611 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 3612 region = devlink_region_get_by_name(devlink, region_name); 3613 if (!region) 3614 return -EINVAL; 3615 3616 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3617 if (!msg) 3618 return -ENOMEM; 3619 3620 err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET, 3621 info->snd_portid, info->snd_seq, 0, 3622 region); 3623 if (err) { 3624 nlmsg_free(msg); 3625 return err; 3626 } 3627 3628 return genlmsg_reply(msg, info); 3629} 3630 3631static int devlink_nl_cmd_region_get_dumpit(struct sk_buff *msg, 3632 struct netlink_callback *cb) 3633{ 3634 struct devlink_region *region; 3635 struct devlink *devlink; 3636 int start = cb->args[0]; 3637 int idx = 0; 3638 int err; 3639 3640 mutex_lock(&devlink_mutex); 3641 list_for_each_entry(devlink, &devlink_list, list) { 3642 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 3643 continue; 3644 3645 mutex_lock(&devlink->lock); 3646 list_for_each_entry(region, &devlink->region_list, list) { 3647 if (idx < start) { 3648 idx++; 3649 continue; 3650 } 3651 err = devlink_nl_region_fill(msg, devlink, 3652 DEVLINK_CMD_REGION_GET, 3653 NETLINK_CB(cb->skb).portid, 3654 cb->nlh->nlmsg_seq, 3655 NLM_F_MULTI, region); 3656 if (err) { 3657 mutex_unlock(&devlink->lock); 3658 goto out; 3659 } 3660 idx++; 3661 } 3662 mutex_unlock(&devlink->lock); 3663 } 3664out: 3665 mutex_unlock(&devlink_mutex); 3666 cb->args[0] = idx; 3667 return msg->len; 3668} 3669 3670static int devlink_nl_cmd_region_del(struct sk_buff *skb, 3671 struct genl_info *info) 3672{ 3673 struct devlink *devlink = info->user_ptr[0]; 3674 struct devlink_snapshot *snapshot; 3675 struct devlink_region *region; 3676 const char *region_name; 3677 u32 snapshot_id; 3678 3679 if (!info->attrs[DEVLINK_ATTR_REGION_NAME] || 3680 !info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) 3681 return -EINVAL; 3682 3683 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 3684 snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); 3685 3686 region = devlink_region_get_by_name(devlink, region_name); 3687 if (!region) 3688 return -EINVAL; 3689 3690 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); 3691 if (!snapshot) 3692 return -EINVAL; 3693 3694 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL); 3695 devlink_region_snapshot_del(snapshot); 3696 return 0; 3697} 3698 3699static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg, 3700 struct devlink *devlink, 3701 u8 *chunk, u32 chunk_size, 3702 u64 addr) 3703{ 3704 struct nlattr *chunk_attr; 3705 int err; 3706 3707 chunk_attr = nla_nest_start_noflag(msg, DEVLINK_ATTR_REGION_CHUNK); 3708 if (!chunk_attr) 3709 return -EINVAL; 3710 3711 err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk); 3712 if (err) 3713 goto nla_put_failure; 3714 3715 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr, 3716 DEVLINK_ATTR_PAD); 3717 if (err) 3718 goto nla_put_failure; 3719 3720 nla_nest_end(msg, chunk_attr); 3721 return 0; 3722 3723nla_put_failure: 3724 nla_nest_cancel(msg, chunk_attr); 3725 return err; 3726} 3727 3728#define DEVLINK_REGION_READ_CHUNK_SIZE 256 3729 3730static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb, 3731 struct devlink *devlink, 3732 struct devlink_region *region, 3733 struct nlattr **attrs, 3734 u64 start_offset, 3735 u64 end_offset, 3736 bool dump, 3737 u64 *new_offset) 3738{ 3739 struct devlink_snapshot *snapshot; 3740 u64 curr_offset = start_offset; 3741 u32 snapshot_id; 3742 int err = 0; 3743 3744 *new_offset = start_offset; 3745 3746 snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); 3747 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); 3748 if (!snapshot) 3749 return -EINVAL; 3750 3751 if (end_offset > snapshot->data_len || dump) 3752 end_offset = snapshot->data_len; 3753 3754 while (curr_offset < end_offset) { 3755 u32 data_size; 3756 u8 *data; 3757 3758 if (end_offset - curr_offset < DEVLINK_REGION_READ_CHUNK_SIZE) 3759 data_size = end_offset - curr_offset; 3760 else 3761 data_size = DEVLINK_REGION_READ_CHUNK_SIZE; 3762 3763 data = &snapshot->data[curr_offset]; 3764 err = devlink_nl_cmd_region_read_chunk_fill(skb, devlink, 3765 data, data_size, 3766 curr_offset); 3767 if (err) 3768 break; 3769 3770 curr_offset += data_size; 3771 } 3772 *new_offset = curr_offset; 3773 3774 return err; 3775} 3776 3777static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, 3778 struct netlink_callback *cb) 3779{ 3780 u64 ret_offset, start_offset, end_offset = 0; 3781 struct devlink_region *region; 3782 struct nlattr *chunks_attr; 3783 const char *region_name; 3784 struct devlink *devlink; 3785 struct nlattr **attrs; 3786 bool dump = true; 3787 void *hdr; 3788 int err; 3789 3790 start_offset = *((u64 *)&cb->args[0]); 3791 3792 attrs = kmalloc_array(DEVLINK_ATTR_MAX + 1, sizeof(*attrs), GFP_KERNEL); 3793 if (!attrs) 3794 return -ENOMEM; 3795 3796 err = nlmsg_parse_deprecated(cb->nlh, 3797 GENL_HDRLEN + devlink_nl_family.hdrsize, 3798 attrs, DEVLINK_ATTR_MAX, 3799 devlink_nl_family.policy, cb->extack); 3800 if (err) 3801 goto out_free; 3802 3803 mutex_lock(&devlink_mutex); 3804 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs); 3805 if (IS_ERR(devlink)) { 3806 err = PTR_ERR(devlink); 3807 goto out_dev; 3808 } 3809 3810 mutex_lock(&devlink->lock); 3811 3812 if (!attrs[DEVLINK_ATTR_REGION_NAME] || 3813 !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) { 3814 err = -EINVAL; 3815 goto out_unlock; 3816 } 3817 3818 region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]); 3819 region = devlink_region_get_by_name(devlink, region_name); 3820 if (!region) { 3821 err = -EINVAL; 3822 goto out_unlock; 3823 } 3824 3825 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 3826 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, 3827 DEVLINK_CMD_REGION_READ); 3828 if (!hdr) { 3829 err = -EMSGSIZE; 3830 goto out_unlock; 3831 } 3832 3833 err = devlink_nl_put_handle(skb, devlink); 3834 if (err) 3835 goto nla_put_failure; 3836 3837 err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name); 3838 if (err) 3839 goto nla_put_failure; 3840 3841 chunks_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_REGION_CHUNKS); 3842 if (!chunks_attr) { 3843 err = -EMSGSIZE; 3844 goto nla_put_failure; 3845 } 3846 3847 if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] && 3848 attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) { 3849 if (!start_offset) 3850 start_offset = 3851 nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); 3852 3853 end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); 3854 end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]); 3855 dump = false; 3856 } 3857 3858 err = devlink_nl_region_read_snapshot_fill(skb, devlink, 3859 region, attrs, 3860 start_offset, 3861 end_offset, dump, 3862 &ret_offset); 3863 3864 if (err && err != -EMSGSIZE) 3865 goto nla_put_failure; 3866 3867 /* Check if there was any progress done to prevent infinite loop */ 3868 if (ret_offset == start_offset) { 3869 err = -EINVAL; 3870 goto nla_put_failure; 3871 } 3872 3873 *((u64 *)&cb->args[0]) = ret_offset; 3874 3875 nla_nest_end(skb, chunks_attr); 3876 genlmsg_end(skb, hdr); 3877 mutex_unlock(&devlink->lock); 3878 mutex_unlock(&devlink_mutex); 3879 kfree(attrs); 3880 3881 return skb->len; 3882 3883nla_put_failure: 3884 genlmsg_cancel(skb, hdr); 3885out_unlock: 3886 mutex_unlock(&devlink->lock); 3887out_dev: 3888 mutex_unlock(&devlink_mutex); 3889out_free: 3890 kfree(attrs); 3891 return err; 3892} 3893 3894struct devlink_info_req { 3895 struct sk_buff *msg; 3896}; 3897 3898int devlink_info_driver_name_put(struct devlink_info_req *req, const char *name) 3899{ 3900 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_DRIVER_NAME, name); 3901} 3902EXPORT_SYMBOL_GPL(devlink_info_driver_name_put); 3903 3904int devlink_info_serial_number_put(struct devlink_info_req *req, const char *sn) 3905{ 3906 return nla_put_string(req->msg, DEVLINK_ATTR_INFO_SERIAL_NUMBER, sn); 3907} 3908EXPORT_SYMBOL_GPL(devlink_info_serial_number_put); 3909 3910static int devlink_info_version_put(struct devlink_info_req *req, int attr, 3911 const char *version_name, 3912 const char *version_value) 3913{ 3914 struct nlattr *nest; 3915 int err; 3916 3917 nest = nla_nest_start_noflag(req->msg, attr); 3918 if (!nest) 3919 return -EMSGSIZE; 3920 3921 err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_NAME, 3922 version_name); 3923 if (err) 3924 goto nla_put_failure; 3925 3926 err = nla_put_string(req->msg, DEVLINK_ATTR_INFO_VERSION_VALUE, 3927 version_value); 3928 if (err) 3929 goto nla_put_failure; 3930 3931 nla_nest_end(req->msg, nest); 3932 3933 return 0; 3934 3935nla_put_failure: 3936 nla_nest_cancel(req->msg, nest); 3937 return err; 3938} 3939 3940int devlink_info_version_fixed_put(struct devlink_info_req *req, 3941 const char *version_name, 3942 const char *version_value) 3943{ 3944 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_FIXED, 3945 version_name, version_value); 3946} 3947EXPORT_SYMBOL_GPL(devlink_info_version_fixed_put); 3948 3949int devlink_info_version_stored_put(struct devlink_info_req *req, 3950 const char *version_name, 3951 const char *version_value) 3952{ 3953 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_STORED, 3954 version_name, version_value); 3955} 3956EXPORT_SYMBOL_GPL(devlink_info_version_stored_put); 3957 3958int devlink_info_version_running_put(struct devlink_info_req *req, 3959 const char *version_name, 3960 const char *version_value) 3961{ 3962 return devlink_info_version_put(req, DEVLINK_ATTR_INFO_VERSION_RUNNING, 3963 version_name, version_value); 3964} 3965EXPORT_SYMBOL_GPL(devlink_info_version_running_put); 3966 3967static int 3968devlink_nl_info_fill(struct sk_buff *msg, struct devlink *devlink, 3969 enum devlink_command cmd, u32 portid, 3970 u32 seq, int flags, struct netlink_ext_ack *extack) 3971{ 3972 struct devlink_info_req req; 3973 void *hdr; 3974 int err; 3975 3976 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 3977 if (!hdr) 3978 return -EMSGSIZE; 3979 3980 err = -EMSGSIZE; 3981 if (devlink_nl_put_handle(msg, devlink)) 3982 goto err_cancel_msg; 3983 3984 req.msg = msg; 3985 err = devlink->ops->info_get(devlink, &req, extack); 3986 if (err) 3987 goto err_cancel_msg; 3988 3989 genlmsg_end(msg, hdr); 3990 return 0; 3991 3992err_cancel_msg: 3993 genlmsg_cancel(msg, hdr); 3994 return err; 3995} 3996 3997static int devlink_nl_cmd_info_get_doit(struct sk_buff *skb, 3998 struct genl_info *info) 3999{ 4000 struct devlink *devlink = info->user_ptr[0]; 4001 struct sk_buff *msg; 4002 int err; 4003 4004 if (!devlink->ops->info_get) 4005 return -EOPNOTSUPP; 4006 4007 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 4008 if (!msg) 4009 return -ENOMEM; 4010 4011 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET, 4012 info->snd_portid, info->snd_seq, 0, 4013 info->extack); 4014 if (err) { 4015 nlmsg_free(msg); 4016 return err; 4017 } 4018 4019 return genlmsg_reply(msg, info); 4020} 4021 4022static int devlink_nl_cmd_info_get_dumpit(struct sk_buff *msg, 4023 struct netlink_callback *cb) 4024{ 4025 struct devlink *devlink; 4026 int start = cb->args[0]; 4027 int idx = 0; 4028 int err; 4029 4030 mutex_lock(&devlink_mutex); 4031 list_for_each_entry(devlink, &devlink_list, list) { 4032 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 4033 continue; 4034 if (idx < start) { 4035 idx++; 4036 continue; 4037 } 4038 4039 if (!devlink->ops->info_get) { 4040 idx++; 4041 continue; 4042 } 4043 4044 mutex_lock(&devlink->lock); 4045 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET, 4046 NETLINK_CB(cb->skb).portid, 4047 cb->nlh->nlmsg_seq, NLM_F_MULTI, 4048 cb->extack); 4049 mutex_unlock(&devlink->lock); 4050 if (err) 4051 break; 4052 idx++; 4053 } 4054 mutex_unlock(&devlink_mutex); 4055 4056 cb->args[0] = idx; 4057 return msg->len; 4058} 4059 4060struct devlink_fmsg_item { 4061 struct list_head list; 4062 int attrtype; 4063 u8 nla_type; 4064 u16 len; 4065 int value[0]; 4066}; 4067 4068struct devlink_fmsg { 4069 struct list_head item_list; 4070}; 4071 4072static struct devlink_fmsg *devlink_fmsg_alloc(void) 4073{ 4074 struct devlink_fmsg *fmsg; 4075 4076 fmsg = kzalloc(sizeof(*fmsg), GFP_KERNEL); 4077 if (!fmsg) 4078 return NULL; 4079 4080 INIT_LIST_HEAD(&fmsg->item_list); 4081 4082 return fmsg; 4083} 4084 4085static void devlink_fmsg_free(struct devlink_fmsg *fmsg) 4086{ 4087 struct devlink_fmsg_item *item, *tmp; 4088 4089 list_for_each_entry_safe(item, tmp, &fmsg->item_list, list) { 4090 list_del(&item->list); 4091 kfree(item); 4092 } 4093 kfree(fmsg); 4094} 4095 4096static int devlink_fmsg_nest_common(struct devlink_fmsg *fmsg, 4097 int attrtype) 4098{ 4099 struct devlink_fmsg_item *item; 4100 4101 item = kzalloc(sizeof(*item), GFP_KERNEL); 4102 if (!item) 4103 return -ENOMEM; 4104 4105 item->attrtype = attrtype; 4106 list_add_tail(&item->list, &fmsg->item_list); 4107 4108 return 0; 4109} 4110 4111int devlink_fmsg_obj_nest_start(struct devlink_fmsg *fmsg) 4112{ 4113 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_OBJ_NEST_START); 4114} 4115EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_start); 4116 4117static int devlink_fmsg_nest_end(struct devlink_fmsg *fmsg) 4118{ 4119 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_NEST_END); 4120} 4121 4122int devlink_fmsg_obj_nest_end(struct devlink_fmsg *fmsg) 4123{ 4124 return devlink_fmsg_nest_end(fmsg); 4125} 4126EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_end); 4127 4128#define DEVLINK_FMSG_MAX_SIZE (GENLMSG_DEFAULT_SIZE - GENL_HDRLEN - NLA_HDRLEN) 4129 4130static int devlink_fmsg_put_name(struct devlink_fmsg *fmsg, const char *name) 4131{ 4132 struct devlink_fmsg_item *item; 4133 4134 if (strlen(name) + 1 > DEVLINK_FMSG_MAX_SIZE) 4135 return -EMSGSIZE; 4136 4137 item = kzalloc(sizeof(*item) + strlen(name) + 1, GFP_KERNEL); 4138 if (!item) 4139 return -ENOMEM; 4140 4141 item->nla_type = NLA_NUL_STRING; 4142 item->len = strlen(name) + 1; 4143 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_NAME; 4144 memcpy(&item->value, name, item->len); 4145 list_add_tail(&item->list, &fmsg->item_list); 4146 4147 return 0; 4148} 4149 4150int devlink_fmsg_pair_nest_start(struct devlink_fmsg *fmsg, const char *name) 4151{ 4152 int err; 4153 4154 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_PAIR_NEST_START); 4155 if (err) 4156 return err; 4157 4158 err = devlink_fmsg_put_name(fmsg, name); 4159 if (err) 4160 return err; 4161 4162 return 0; 4163} 4164EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_start); 4165 4166int devlink_fmsg_pair_nest_end(struct devlink_fmsg *fmsg) 4167{ 4168 return devlink_fmsg_nest_end(fmsg); 4169} 4170EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_end); 4171 4172int devlink_fmsg_arr_pair_nest_start(struct devlink_fmsg *fmsg, 4173 const char *name) 4174{ 4175 int err; 4176 4177 err = devlink_fmsg_pair_nest_start(fmsg, name); 4178 if (err) 4179 return err; 4180 4181 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_ARR_NEST_START); 4182 if (err) 4183 return err; 4184 4185 return 0; 4186} 4187EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_start); 4188 4189int devlink_fmsg_arr_pair_nest_end(struct devlink_fmsg *fmsg) 4190{ 4191 int err; 4192 4193 err = devlink_fmsg_nest_end(fmsg); 4194 if (err) 4195 return err; 4196 4197 err = devlink_fmsg_nest_end(fmsg); 4198 if (err) 4199 return err; 4200 4201 return 0; 4202} 4203EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_end); 4204 4205static int devlink_fmsg_put_value(struct devlink_fmsg *fmsg, 4206 const void *value, u16 value_len, 4207 u8 value_nla_type) 4208{ 4209 struct devlink_fmsg_item *item; 4210 4211 if (value_len > DEVLINK_FMSG_MAX_SIZE) 4212 return -EMSGSIZE; 4213 4214 item = kzalloc(sizeof(*item) + value_len, GFP_KERNEL); 4215 if (!item) 4216 return -ENOMEM; 4217 4218 item->nla_type = value_nla_type; 4219 item->len = value_len; 4220 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA; 4221 memcpy(&item->value, value, item->len); 4222 list_add_tail(&item->list, &fmsg->item_list); 4223 4224 return 0; 4225} 4226 4227int devlink_fmsg_bool_put(struct devlink_fmsg *fmsg, bool value) 4228{ 4229 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_FLAG); 4230} 4231EXPORT_SYMBOL_GPL(devlink_fmsg_bool_put); 4232 4233int devlink_fmsg_u8_put(struct devlink_fmsg *fmsg, u8 value) 4234{ 4235 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U8); 4236} 4237EXPORT_SYMBOL_GPL(devlink_fmsg_u8_put); 4238 4239int devlink_fmsg_u32_put(struct devlink_fmsg *fmsg, u32 value) 4240{ 4241 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U32); 4242} 4243EXPORT_SYMBOL_GPL(devlink_fmsg_u32_put); 4244 4245int devlink_fmsg_u64_put(struct devlink_fmsg *fmsg, u64 value) 4246{ 4247 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U64); 4248} 4249EXPORT_SYMBOL_GPL(devlink_fmsg_u64_put); 4250 4251int devlink_fmsg_string_put(struct devlink_fmsg *fmsg, const char *value) 4252{ 4253 return devlink_fmsg_put_value(fmsg, value, strlen(value) + 1, 4254 NLA_NUL_STRING); 4255} 4256EXPORT_SYMBOL_GPL(devlink_fmsg_string_put); 4257 4258int devlink_fmsg_binary_put(struct devlink_fmsg *fmsg, const void *value, 4259 u16 value_len) 4260{ 4261 return devlink_fmsg_put_value(fmsg, value, value_len, NLA_BINARY); 4262} 4263EXPORT_SYMBOL_GPL(devlink_fmsg_binary_put); 4264 4265int devlink_fmsg_bool_pair_put(struct devlink_fmsg *fmsg, const char *name, 4266 bool value) 4267{ 4268 int err; 4269 4270 err = devlink_fmsg_pair_nest_start(fmsg, name); 4271 if (err) 4272 return err; 4273 4274 err = devlink_fmsg_bool_put(fmsg, value); 4275 if (err) 4276 return err; 4277 4278 err = devlink_fmsg_pair_nest_end(fmsg); 4279 if (err) 4280 return err; 4281 4282 return 0; 4283} 4284EXPORT_SYMBOL_GPL(devlink_fmsg_bool_pair_put); 4285 4286int devlink_fmsg_u8_pair_put(struct devlink_fmsg *fmsg, const char *name, 4287 u8 value) 4288{ 4289 int err; 4290 4291 err = devlink_fmsg_pair_nest_start(fmsg, name); 4292 if (err) 4293 return err; 4294 4295 err = devlink_fmsg_u8_put(fmsg, value); 4296 if (err) 4297 return err; 4298 4299 err = devlink_fmsg_pair_nest_end(fmsg); 4300 if (err) 4301 return err; 4302 4303 return 0; 4304} 4305EXPORT_SYMBOL_GPL(devlink_fmsg_u8_pair_put); 4306 4307int devlink_fmsg_u32_pair_put(struct devlink_fmsg *fmsg, const char *name, 4308 u32 value) 4309{ 4310 int err; 4311 4312 err = devlink_fmsg_pair_nest_start(fmsg, name); 4313 if (err) 4314 return err; 4315 4316 err = devlink_fmsg_u32_put(fmsg, value); 4317 if (err) 4318 return err; 4319 4320 err = devlink_fmsg_pair_nest_end(fmsg); 4321 if (err) 4322 return err; 4323 4324 return 0; 4325} 4326EXPORT_SYMBOL_GPL(devlink_fmsg_u32_pair_put); 4327 4328int devlink_fmsg_u64_pair_put(struct devlink_fmsg *fmsg, const char *name, 4329 u64 value) 4330{ 4331 int err; 4332 4333 err = devlink_fmsg_pair_nest_start(fmsg, name); 4334 if (err) 4335 return err; 4336 4337 err = devlink_fmsg_u64_put(fmsg, value); 4338 if (err) 4339 return err; 4340 4341 err = devlink_fmsg_pair_nest_end(fmsg); 4342 if (err) 4343 return err; 4344 4345 return 0; 4346} 4347EXPORT_SYMBOL_GPL(devlink_fmsg_u64_pair_put); 4348 4349int devlink_fmsg_string_pair_put(struct devlink_fmsg *fmsg, const char *name, 4350 const char *value) 4351{ 4352 int err; 4353 4354 err = devlink_fmsg_pair_nest_start(fmsg, name); 4355 if (err) 4356 return err; 4357 4358 err = devlink_fmsg_string_put(fmsg, value); 4359 if (err) 4360 return err; 4361 4362 err = devlink_fmsg_pair_nest_end(fmsg); 4363 if (err) 4364 return err; 4365 4366 return 0; 4367} 4368EXPORT_SYMBOL_GPL(devlink_fmsg_string_pair_put); 4369 4370int devlink_fmsg_binary_pair_put(struct devlink_fmsg *fmsg, const char *name, 4371 const void *value, u16 value_len) 4372{ 4373 int err; 4374 4375 err = devlink_fmsg_pair_nest_start(fmsg, name); 4376 if (err) 4377 return err; 4378 4379 err = devlink_fmsg_binary_put(fmsg, value, value_len); 4380 if (err) 4381 return err; 4382 4383 err = devlink_fmsg_pair_nest_end(fmsg); 4384 if (err) 4385 return err; 4386 4387 return 0; 4388} 4389EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_put); 4390 4391static int 4392devlink_fmsg_item_fill_type(struct devlink_fmsg_item *msg, struct sk_buff *skb) 4393{ 4394 switch (msg->nla_type) { 4395 case NLA_FLAG: 4396 case NLA_U8: 4397 case NLA_U32: 4398 case NLA_U64: 4399 case NLA_NUL_STRING: 4400 case NLA_BINARY: 4401 return nla_put_u8(skb, DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE, 4402 msg->nla_type); 4403 default: 4404 return -EINVAL; 4405 } 4406} 4407 4408static int 4409devlink_fmsg_item_fill_data(struct devlink_fmsg_item *msg, struct sk_buff *skb) 4410{ 4411 int attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA; 4412 u8 tmp; 4413 4414 switch (msg->nla_type) { 4415 case NLA_FLAG: 4416 /* Always provide flag data, regardless of its value */ 4417 tmp = *(bool *) msg->value; 4418 4419 return nla_put_u8(skb, attrtype, tmp); 4420 case NLA_U8: 4421 return nla_put_u8(skb, attrtype, *(u8 *) msg->value); 4422 case NLA_U32: 4423 return nla_put_u32(skb, attrtype, *(u32 *) msg->value); 4424 case NLA_U64: 4425 return nla_put_u64_64bit(skb, attrtype, *(u64 *) msg->value, 4426 DEVLINK_ATTR_PAD); 4427 case NLA_NUL_STRING: 4428 return nla_put_string(skb, attrtype, (char *) &msg->value); 4429 case NLA_BINARY: 4430 return nla_put(skb, attrtype, msg->len, (void *) &msg->value); 4431 default: 4432 return -EINVAL; 4433 } 4434} 4435 4436static int 4437devlink_fmsg_prepare_skb(struct devlink_fmsg *fmsg, struct sk_buff *skb, 4438 int *start) 4439{ 4440 struct devlink_fmsg_item *item; 4441 struct nlattr *fmsg_nlattr; 4442 int i = 0; 4443 int err; 4444 4445 fmsg_nlattr = nla_nest_start_noflag(skb, DEVLINK_ATTR_FMSG); 4446 if (!fmsg_nlattr) 4447 return -EMSGSIZE; 4448 4449 list_for_each_entry(item, &fmsg->item_list, list) { 4450 if (i < *start) { 4451 i++; 4452 continue; 4453 } 4454 4455 switch (item->attrtype) { 4456 case DEVLINK_ATTR_FMSG_OBJ_NEST_START: 4457 case DEVLINK_ATTR_FMSG_PAIR_NEST_START: 4458 case DEVLINK_ATTR_FMSG_ARR_NEST_START: 4459 case DEVLINK_ATTR_FMSG_NEST_END: 4460 err = nla_put_flag(skb, item->attrtype); 4461 break; 4462 case DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA: 4463 err = devlink_fmsg_item_fill_type(item, skb); 4464 if (err) 4465 break; 4466 err = devlink_fmsg_item_fill_data(item, skb); 4467 break; 4468 case DEVLINK_ATTR_FMSG_OBJ_NAME: 4469 err = nla_put_string(skb, item->attrtype, 4470 (char *) &item->value); 4471 break; 4472 default: 4473 err = -EINVAL; 4474 break; 4475 } 4476 if (!err) 4477 *start = ++i; 4478 else 4479 break; 4480 } 4481 4482 nla_nest_end(skb, fmsg_nlattr); 4483 return err; 4484} 4485 4486static int devlink_fmsg_snd(struct devlink_fmsg *fmsg, 4487 struct genl_info *info, 4488 enum devlink_command cmd, int flags) 4489{ 4490 struct nlmsghdr *nlh; 4491 struct sk_buff *skb; 4492 bool last = false; 4493 int index = 0; 4494 void *hdr; 4495 int err; 4496 4497 while (!last) { 4498 int tmp_index = index; 4499 4500 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 4501 if (!skb) 4502 return -ENOMEM; 4503 4504 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 4505 &devlink_nl_family, flags | NLM_F_MULTI, cmd); 4506 if (!hdr) { 4507 err = -EMSGSIZE; 4508 goto nla_put_failure; 4509 } 4510 4511 err = devlink_fmsg_prepare_skb(fmsg, skb, &index); 4512 if (!err) 4513 last = true; 4514 else if (err != -EMSGSIZE || tmp_index == index) 4515 goto nla_put_failure; 4516 4517 genlmsg_end(skb, hdr); 4518 err = genlmsg_reply(skb, info); 4519 if (err) 4520 return err; 4521 } 4522 4523 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 4524 if (!skb) 4525 return -ENOMEM; 4526 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 4527 NLMSG_DONE, 0, flags | NLM_F_MULTI); 4528 if (!nlh) { 4529 err = -EMSGSIZE; 4530 goto nla_put_failure; 4531 } 4532 4533 return genlmsg_reply(skb, info); 4534 4535nla_put_failure: 4536 nlmsg_free(skb); 4537 return err; 4538} 4539 4540static int devlink_fmsg_dumpit(struct devlink_fmsg *fmsg, struct sk_buff *skb, 4541 struct netlink_callback *cb, 4542 enum devlink_command cmd) 4543{ 4544 int index = cb->args[0]; 4545 int tmp_index = index; 4546 void *hdr; 4547 int err; 4548 4549 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 4550 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, cmd); 4551 if (!hdr) { 4552 err = -EMSGSIZE; 4553 goto nla_put_failure; 4554 } 4555 4556 err = devlink_fmsg_prepare_skb(fmsg, skb, &index); 4557 if ((err && err != -EMSGSIZE) || tmp_index == index) 4558 goto nla_put_failure; 4559 4560 cb->args[0] = index; 4561 genlmsg_end(skb, hdr); 4562 return skb->len; 4563 4564nla_put_failure: 4565 genlmsg_cancel(skb, hdr); 4566 return err; 4567} 4568 4569struct devlink_health_reporter { 4570 struct list_head list; 4571 void *priv; 4572 const struct devlink_health_reporter_ops *ops; 4573 struct devlink *devlink; 4574 struct devlink_fmsg *dump_fmsg; 4575 struct mutex dump_lock; /* lock parallel read/write from dump buffers */ 4576 u64 graceful_period; 4577 bool auto_recover; 4578 u8 health_state; 4579 u64 dump_ts; 4580 u64 error_count; 4581 u64 recovery_count; 4582 u64 last_recovery_ts; 4583 refcount_t refcount; 4584}; 4585 4586void * 4587devlink_health_reporter_priv(struct devlink_health_reporter *reporter) 4588{ 4589 return reporter->priv; 4590} 4591EXPORT_SYMBOL_GPL(devlink_health_reporter_priv); 4592 4593static struct devlink_health_reporter * 4594devlink_health_reporter_find_by_name(struct devlink *devlink, 4595 const char *reporter_name) 4596{ 4597 struct devlink_health_reporter *reporter; 4598 4599 lockdep_assert_held(&devlink->reporters_lock); 4600 list_for_each_entry(reporter, &devlink->reporter_list, list) 4601 if (!strcmp(reporter->ops->name, reporter_name)) 4602 return reporter; 4603 return NULL; 4604} 4605 4606/** 4607 * devlink_health_reporter_create - create devlink health reporter 4608 * 4609 * @devlink: devlink 4610 * @ops: ops 4611 * @graceful_period: to avoid recovery loops, in msecs 4612 * @auto_recover: auto recover when error occurs 4613 * @priv: priv 4614 */ 4615struct devlink_health_reporter * 4616devlink_health_reporter_create(struct devlink *devlink, 4617 const struct devlink_health_reporter_ops *ops, 4618 u64 graceful_period, bool auto_recover, 4619 void *priv) 4620{ 4621 struct devlink_health_reporter *reporter; 4622 4623 mutex_lock(&devlink->reporters_lock); 4624 if (devlink_health_reporter_find_by_name(devlink, ops->name)) { 4625 reporter = ERR_PTR(-EEXIST); 4626 goto unlock; 4627 } 4628 4629 if (WARN_ON(auto_recover && !ops->recover) || 4630 WARN_ON(graceful_period && !ops->recover)) { 4631 reporter = ERR_PTR(-EINVAL); 4632 goto unlock; 4633 } 4634 4635 reporter = kzalloc(sizeof(*reporter), GFP_KERNEL); 4636 if (!reporter) { 4637 reporter = ERR_PTR(-ENOMEM); 4638 goto unlock; 4639 } 4640 4641 reporter->priv = priv; 4642 reporter->ops = ops; 4643 reporter->devlink = devlink; 4644 reporter->graceful_period = graceful_period; 4645 reporter->auto_recover = auto_recover; 4646 mutex_init(&reporter->dump_lock); 4647 refcount_set(&reporter->refcount, 1); 4648 list_add_tail(&reporter->list, &devlink->reporter_list); 4649unlock: 4650 mutex_unlock(&devlink->reporters_lock); 4651 return reporter; 4652} 4653EXPORT_SYMBOL_GPL(devlink_health_reporter_create); 4654 4655/** 4656 * devlink_health_reporter_destroy - destroy devlink health reporter 4657 * 4658 * @reporter: devlink health reporter to destroy 4659 */ 4660void 4661devlink_health_reporter_destroy(struct devlink_health_reporter *reporter) 4662{ 4663 mutex_lock(&reporter->devlink->reporters_lock); 4664 list_del(&reporter->list); 4665 mutex_unlock(&reporter->devlink->reporters_lock); 4666 while (refcount_read(&reporter->refcount) > 1) 4667 msleep(100); 4668 mutex_destroy(&reporter->dump_lock); 4669 if (reporter->dump_fmsg) 4670 devlink_fmsg_free(reporter->dump_fmsg); 4671 kfree(reporter); 4672} 4673EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy); 4674 4675void 4676devlink_health_reporter_state_update(struct devlink_health_reporter *reporter, 4677 enum devlink_health_reporter_state state) 4678{ 4679 if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY && 4680 state != DEVLINK_HEALTH_REPORTER_STATE_ERROR)) 4681 return; 4682 4683 if (reporter->health_state == state) 4684 return; 4685 4686 reporter->health_state = state; 4687 trace_devlink_health_reporter_state_update(reporter->devlink, 4688 reporter->ops->name, state); 4689} 4690EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update); 4691 4692static int 4693devlink_health_reporter_recover(struct devlink_health_reporter *reporter, 4694 void *priv_ctx) 4695{ 4696 int err; 4697 4698 if (!reporter->ops->recover) 4699 return -EOPNOTSUPP; 4700 4701 err = reporter->ops->recover(reporter, priv_ctx); 4702 if (err) 4703 return err; 4704 4705 reporter->recovery_count++; 4706 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY; 4707 reporter->last_recovery_ts = jiffies; 4708 4709 return 0; 4710} 4711 4712static void 4713devlink_health_dump_clear(struct devlink_health_reporter *reporter) 4714{ 4715 if (!reporter->dump_fmsg) 4716 return; 4717 devlink_fmsg_free(reporter->dump_fmsg); 4718 reporter->dump_fmsg = NULL; 4719} 4720 4721static int devlink_health_do_dump(struct devlink_health_reporter *reporter, 4722 void *priv_ctx) 4723{ 4724 int err; 4725 4726 if (!reporter->ops->dump) 4727 return 0; 4728 4729 if (reporter->dump_fmsg) 4730 return 0; 4731 4732 reporter->dump_fmsg = devlink_fmsg_alloc(); 4733 if (!reporter->dump_fmsg) { 4734 err = -ENOMEM; 4735 return err; 4736 } 4737 4738 err = devlink_fmsg_obj_nest_start(reporter->dump_fmsg); 4739 if (err) 4740 goto dump_err; 4741 4742 err = reporter->ops->dump(reporter, reporter->dump_fmsg, 4743 priv_ctx); 4744 if (err) 4745 goto dump_err; 4746 4747 err = devlink_fmsg_obj_nest_end(reporter->dump_fmsg); 4748 if (err) 4749 goto dump_err; 4750 4751 reporter->dump_ts = jiffies; 4752 4753 return 0; 4754 4755dump_err: 4756 devlink_health_dump_clear(reporter); 4757 return err; 4758} 4759 4760int devlink_health_report(struct devlink_health_reporter *reporter, 4761 const char *msg, void *priv_ctx) 4762{ 4763 enum devlink_health_reporter_state prev_health_state; 4764 struct devlink *devlink = reporter->devlink; 4765 4766 /* write a log message of the current error */ 4767 WARN_ON(!msg); 4768 trace_devlink_health_report(devlink, reporter->ops->name, msg); 4769 reporter->error_count++; 4770 prev_health_state = reporter->health_state; 4771 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR; 4772 4773 /* abort if the previous error wasn't recovered */ 4774 if (reporter->auto_recover && 4775 (prev_health_state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY || 4776 jiffies - reporter->last_recovery_ts < 4777 msecs_to_jiffies(reporter->graceful_period))) { 4778 trace_devlink_health_recover_aborted(devlink, 4779 reporter->ops->name, 4780 reporter->health_state, 4781 jiffies - 4782 reporter->last_recovery_ts); 4783 return -ECANCELED; 4784 } 4785 4786 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR; 4787 4788 mutex_lock(&reporter->dump_lock); 4789 /* store current dump of current error, for later analysis */ 4790 devlink_health_do_dump(reporter, priv_ctx); 4791 mutex_unlock(&reporter->dump_lock); 4792 4793 if (reporter->auto_recover) 4794 return devlink_health_reporter_recover(reporter, priv_ctx); 4795 4796 return 0; 4797} 4798EXPORT_SYMBOL_GPL(devlink_health_report); 4799 4800static struct devlink_health_reporter * 4801devlink_health_reporter_get_from_attrs(struct devlink *devlink, 4802 struct nlattr **attrs) 4803{ 4804 struct devlink_health_reporter *reporter; 4805 char *reporter_name; 4806 4807 if (!attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]) 4808 return NULL; 4809 4810 reporter_name = nla_data(attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]); 4811 mutex_lock(&devlink->reporters_lock); 4812 reporter = devlink_health_reporter_find_by_name(devlink, reporter_name); 4813 if (reporter) 4814 refcount_inc(&reporter->refcount); 4815 mutex_unlock(&devlink->reporters_lock); 4816 return reporter; 4817} 4818 4819static struct devlink_health_reporter * 4820devlink_health_reporter_get_from_info(struct devlink *devlink, 4821 struct genl_info *info) 4822{ 4823 return devlink_health_reporter_get_from_attrs(devlink, info->attrs); 4824} 4825 4826static struct devlink_health_reporter * 4827devlink_health_reporter_get_from_cb(struct netlink_callback *cb) 4828{ 4829 struct devlink_health_reporter *reporter; 4830 struct devlink *devlink; 4831 struct nlattr **attrs; 4832 int err; 4833 4834 attrs = kmalloc_array(DEVLINK_ATTR_MAX + 1, sizeof(*attrs), GFP_KERNEL); 4835 if (!attrs) 4836 return NULL; 4837 4838 err = nlmsg_parse_deprecated(cb->nlh, 4839 GENL_HDRLEN + devlink_nl_family.hdrsize, 4840 attrs, DEVLINK_ATTR_MAX, 4841 devlink_nl_family.policy, cb->extack); 4842 if (err) 4843 goto free; 4844 4845 mutex_lock(&devlink_mutex); 4846 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs); 4847 if (IS_ERR(devlink)) 4848 goto unlock; 4849 4850 reporter = devlink_health_reporter_get_from_attrs(devlink, attrs); 4851 mutex_unlock(&devlink_mutex); 4852 kfree(attrs); 4853 return reporter; 4854unlock: 4855 mutex_unlock(&devlink_mutex); 4856free: 4857 kfree(attrs); 4858 return NULL; 4859} 4860 4861static void 4862devlink_health_reporter_put(struct devlink_health_reporter *reporter) 4863{ 4864 refcount_dec(&reporter->refcount); 4865} 4866 4867static int 4868devlink_nl_health_reporter_fill(struct sk_buff *msg, 4869 struct devlink *devlink, 4870 struct devlink_health_reporter *reporter, 4871 enum devlink_command cmd, u32 portid, 4872 u32 seq, int flags) 4873{ 4874 struct nlattr *reporter_attr; 4875 void *hdr; 4876 4877 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 4878 if (!hdr) 4879 return -EMSGSIZE; 4880 4881 if (devlink_nl_put_handle(msg, devlink)) 4882 goto genlmsg_cancel; 4883 4884 reporter_attr = nla_nest_start_noflag(msg, 4885 DEVLINK_ATTR_HEALTH_REPORTER); 4886 if (!reporter_attr) 4887 goto genlmsg_cancel; 4888 if (nla_put_string(msg, DEVLINK_ATTR_HEALTH_REPORTER_NAME, 4889 reporter->ops->name)) 4890 goto reporter_nest_cancel; 4891 if (nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_STATE, 4892 reporter->health_state)) 4893 goto reporter_nest_cancel; 4894 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_ERR_COUNT, 4895 reporter->error_count, DEVLINK_ATTR_PAD)) 4896 goto reporter_nest_cancel; 4897 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_RECOVER_COUNT, 4898 reporter->recovery_count, DEVLINK_ATTR_PAD)) 4899 goto reporter_nest_cancel; 4900 if (reporter->ops->recover && 4901 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD, 4902 reporter->graceful_period, 4903 DEVLINK_ATTR_PAD)) 4904 goto reporter_nest_cancel; 4905 if (reporter->ops->recover && 4906 nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER, 4907 reporter->auto_recover)) 4908 goto reporter_nest_cancel; 4909 if (reporter->dump_fmsg && 4910 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS, 4911 jiffies_to_msecs(reporter->dump_ts), 4912 DEVLINK_ATTR_PAD)) 4913 goto reporter_nest_cancel; 4914 4915 nla_nest_end(msg, reporter_attr); 4916 genlmsg_end(msg, hdr); 4917 return 0; 4918 4919reporter_nest_cancel: 4920 nla_nest_end(msg, reporter_attr); 4921genlmsg_cancel: 4922 genlmsg_cancel(msg, hdr); 4923 return -EMSGSIZE; 4924} 4925 4926static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb, 4927 struct genl_info *info) 4928{ 4929 struct devlink *devlink = info->user_ptr[0]; 4930 struct devlink_health_reporter *reporter; 4931 struct sk_buff *msg; 4932 int err; 4933 4934 reporter = devlink_health_reporter_get_from_info(devlink, info); 4935 if (!reporter) 4936 return -EINVAL; 4937 4938 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 4939 if (!msg) { 4940 err = -ENOMEM; 4941 goto out; 4942 } 4943 4944 err = devlink_nl_health_reporter_fill(msg, devlink, reporter, 4945 DEVLINK_CMD_HEALTH_REPORTER_GET, 4946 info->snd_portid, info->snd_seq, 4947 0); 4948 if (err) { 4949 nlmsg_free(msg); 4950 goto out; 4951 } 4952 4953 err = genlmsg_reply(msg, info); 4954out: 4955 devlink_health_reporter_put(reporter); 4956 return err; 4957} 4958 4959static int 4960devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg, 4961 struct netlink_callback *cb) 4962{ 4963 struct devlink_health_reporter *reporter; 4964 struct devlink *devlink; 4965 int start = cb->args[0]; 4966 int idx = 0; 4967 int err; 4968 4969 mutex_lock(&devlink_mutex); 4970 list_for_each_entry(devlink, &devlink_list, list) { 4971 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 4972 continue; 4973 mutex_lock(&devlink->reporters_lock); 4974 list_for_each_entry(reporter, &devlink->reporter_list, 4975 list) { 4976 if (idx < start) { 4977 idx++; 4978 continue; 4979 } 4980 err = devlink_nl_health_reporter_fill(msg, devlink, 4981 reporter, 4982 DEVLINK_CMD_HEALTH_REPORTER_GET, 4983 NETLINK_CB(cb->skb).portid, 4984 cb->nlh->nlmsg_seq, 4985 NLM_F_MULTI); 4986 if (err) { 4987 mutex_unlock(&devlink->reporters_lock); 4988 goto out; 4989 } 4990 idx++; 4991 } 4992 mutex_unlock(&devlink->reporters_lock); 4993 } 4994out: 4995 mutex_unlock(&devlink_mutex); 4996 4997 cb->args[0] = idx; 4998 return msg->len; 4999} 5000 5001static int 5002devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb, 5003 struct genl_info *info) 5004{ 5005 struct devlink *devlink = info->user_ptr[0]; 5006 struct devlink_health_reporter *reporter; 5007 int err; 5008 5009 reporter = devlink_health_reporter_get_from_info(devlink, info); 5010 if (!reporter) 5011 return -EINVAL; 5012 5013 if (!reporter->ops->recover && 5014 (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] || 5015 info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])) { 5016 err = -EOPNOTSUPP; 5017 goto out; 5018 } 5019 5020 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]) 5021 reporter->graceful_period = 5022 nla_get_u64(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]); 5023 5024 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]) 5025 reporter->auto_recover = 5026 nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]); 5027 5028 devlink_health_reporter_put(reporter); 5029 return 0; 5030out: 5031 devlink_health_reporter_put(reporter); 5032 return err; 5033} 5034 5035static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb, 5036 struct genl_info *info) 5037{ 5038 struct devlink *devlink = info->user_ptr[0]; 5039 struct devlink_health_reporter *reporter; 5040 int err; 5041 5042 reporter = devlink_health_reporter_get_from_info(devlink, info); 5043 if (!reporter) 5044 return -EINVAL; 5045 5046 err = devlink_health_reporter_recover(reporter, NULL); 5047 5048 devlink_health_reporter_put(reporter); 5049 return err; 5050} 5051 5052static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb, 5053 struct genl_info *info) 5054{ 5055 struct devlink *devlink = info->user_ptr[0]; 5056 struct devlink_health_reporter *reporter; 5057 struct devlink_fmsg *fmsg; 5058 int err; 5059 5060 reporter = devlink_health_reporter_get_from_info(devlink, info); 5061 if (!reporter) 5062 return -EINVAL; 5063 5064 if (!reporter->ops->diagnose) { 5065 devlink_health_reporter_put(reporter); 5066 return -EOPNOTSUPP; 5067 } 5068 5069 fmsg = devlink_fmsg_alloc(); 5070 if (!fmsg) { 5071 devlink_health_reporter_put(reporter); 5072 return -ENOMEM; 5073 } 5074 5075 err = devlink_fmsg_obj_nest_start(fmsg); 5076 if (err) 5077 goto out; 5078 5079 err = reporter->ops->diagnose(reporter, fmsg); 5080 if (err) 5081 goto out; 5082 5083 err = devlink_fmsg_obj_nest_end(fmsg); 5084 if (err) 5085 goto out; 5086 5087 err = devlink_fmsg_snd(fmsg, info, 5088 DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 0); 5089 5090out: 5091 devlink_fmsg_free(fmsg); 5092 devlink_health_reporter_put(reporter); 5093 return err; 5094} 5095 5096static int 5097devlink_nl_cmd_health_reporter_dump_get_dumpit(struct sk_buff *skb, 5098 struct netlink_callback *cb) 5099{ 5100 struct devlink_health_reporter *reporter; 5101 u64 start = cb->args[0]; 5102 int err; 5103 5104 reporter = devlink_health_reporter_get_from_cb(cb); 5105 if (!reporter) 5106 return -EINVAL; 5107 5108 if (!reporter->ops->dump) { 5109 err = -EOPNOTSUPP; 5110 goto out; 5111 } 5112 mutex_lock(&reporter->dump_lock); 5113 if (!start) { 5114 err = devlink_health_do_dump(reporter, NULL); 5115 if (err) 5116 goto unlock; 5117 cb->args[1] = reporter->dump_ts; 5118 } 5119 if (!reporter->dump_fmsg || cb->args[1] != reporter->dump_ts) { 5120 NL_SET_ERR_MSG_MOD(cb->extack, "Dump trampled, please retry"); 5121 err = -EAGAIN; 5122 goto unlock; 5123 } 5124 5125 err = devlink_fmsg_dumpit(reporter->dump_fmsg, skb, cb, 5126 DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET); 5127unlock: 5128 mutex_unlock(&reporter->dump_lock); 5129out: 5130 devlink_health_reporter_put(reporter); 5131 return err; 5132} 5133 5134static int 5135devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb, 5136 struct genl_info *info) 5137{ 5138 struct devlink *devlink = info->user_ptr[0]; 5139 struct devlink_health_reporter *reporter; 5140 5141 reporter = devlink_health_reporter_get_from_info(devlink, info); 5142 if (!reporter) 5143 return -EINVAL; 5144 5145 if (!reporter->ops->dump) { 5146 devlink_health_reporter_put(reporter); 5147 return -EOPNOTSUPP; 5148 } 5149 5150 mutex_lock(&reporter->dump_lock); 5151 devlink_health_dump_clear(reporter); 5152 mutex_unlock(&reporter->dump_lock); 5153 devlink_health_reporter_put(reporter); 5154 return 0; 5155} 5156 5157static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { 5158 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING }, 5159 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING }, 5160 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 }, 5161 [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 }, 5162 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 }, 5163 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 }, 5164 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 }, 5165 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 }, 5166 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 }, 5167 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 }, 5168 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 }, 5169 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 }, 5170 [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 }, 5171 [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 }, 5172 [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 }, 5173 [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING }, 5174 [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 }, 5175 [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64}, 5176 [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64}, 5177 [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING }, 5178 [DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 }, 5179 [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 }, 5180 [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING }, 5181 [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 }, 5182 [DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING }, 5183 [DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] = { .type = NLA_U64 }, 5184 [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER] = { .type = NLA_U8 }, 5185 [DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME] = { .type = NLA_NUL_STRING }, 5186 [DEVLINK_ATTR_FLASH_UPDATE_COMPONENT] = { .type = NLA_NUL_STRING }, 5187}; 5188 5189static const struct genl_ops devlink_nl_ops[] = { 5190 { 5191 .cmd = DEVLINK_CMD_GET, 5192 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5193 .doit = devlink_nl_cmd_get_doit, 5194 .dumpit = devlink_nl_cmd_get_dumpit, 5195 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5196 /* can be retrieved by unprivileged users */ 5197 }, 5198 { 5199 .cmd = DEVLINK_CMD_PORT_GET, 5200 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5201 .doit = devlink_nl_cmd_port_get_doit, 5202 .dumpit = devlink_nl_cmd_port_get_dumpit, 5203 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 5204 /* can be retrieved by unprivileged users */ 5205 }, 5206 { 5207 .cmd = DEVLINK_CMD_PORT_SET, 5208 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5209 .doit = devlink_nl_cmd_port_set_doit, 5210 .flags = GENL_ADMIN_PERM, 5211 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 5212 }, 5213 { 5214 .cmd = DEVLINK_CMD_PORT_SPLIT, 5215 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5216 .doit = devlink_nl_cmd_port_split_doit, 5217 .flags = GENL_ADMIN_PERM, 5218 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5219 DEVLINK_NL_FLAG_NO_LOCK, 5220 }, 5221 { 5222 .cmd = DEVLINK_CMD_PORT_UNSPLIT, 5223 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5224 .doit = devlink_nl_cmd_port_unsplit_doit, 5225 .flags = GENL_ADMIN_PERM, 5226 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5227 DEVLINK_NL_FLAG_NO_LOCK, 5228 }, 5229 { 5230 .cmd = DEVLINK_CMD_SB_GET, 5231 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5232 .doit = devlink_nl_cmd_sb_get_doit, 5233 .dumpit = devlink_nl_cmd_sb_get_dumpit, 5234 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5235 DEVLINK_NL_FLAG_NEED_SB, 5236 /* can be retrieved by unprivileged users */ 5237 }, 5238 { 5239 .cmd = DEVLINK_CMD_SB_POOL_GET, 5240 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5241 .doit = devlink_nl_cmd_sb_pool_get_doit, 5242 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit, 5243 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5244 DEVLINK_NL_FLAG_NEED_SB, 5245 /* can be retrieved by unprivileged users */ 5246 }, 5247 { 5248 .cmd = DEVLINK_CMD_SB_POOL_SET, 5249 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5250 .doit = devlink_nl_cmd_sb_pool_set_doit, 5251 .flags = GENL_ADMIN_PERM, 5252 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5253 DEVLINK_NL_FLAG_NEED_SB, 5254 }, 5255 { 5256 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET, 5257 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5258 .doit = devlink_nl_cmd_sb_port_pool_get_doit, 5259 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit, 5260 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 5261 DEVLINK_NL_FLAG_NEED_SB, 5262 /* can be retrieved by unprivileged users */ 5263 }, 5264 { 5265 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET, 5266 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5267 .doit = devlink_nl_cmd_sb_port_pool_set_doit, 5268 .flags = GENL_ADMIN_PERM, 5269 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 5270 DEVLINK_NL_FLAG_NEED_SB, 5271 }, 5272 { 5273 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET, 5274 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5275 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit, 5276 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit, 5277 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 5278 DEVLINK_NL_FLAG_NEED_SB, 5279 /* can be retrieved by unprivileged users */ 5280 }, 5281 { 5282 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET, 5283 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5284 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit, 5285 .flags = GENL_ADMIN_PERM, 5286 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 5287 DEVLINK_NL_FLAG_NEED_SB, 5288 }, 5289 { 5290 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT, 5291 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5292 .doit = devlink_nl_cmd_sb_occ_snapshot_doit, 5293 .flags = GENL_ADMIN_PERM, 5294 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5295 DEVLINK_NL_FLAG_NEED_SB, 5296 }, 5297 { 5298 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR, 5299 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5300 .doit = devlink_nl_cmd_sb_occ_max_clear_doit, 5301 .flags = GENL_ADMIN_PERM, 5302 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5303 DEVLINK_NL_FLAG_NEED_SB, 5304 }, 5305 { 5306 .cmd = DEVLINK_CMD_ESWITCH_GET, 5307 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5308 .doit = devlink_nl_cmd_eswitch_get_doit, 5309 .flags = GENL_ADMIN_PERM, 5310 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5311 }, 5312 { 5313 .cmd = DEVLINK_CMD_ESWITCH_SET, 5314 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5315 .doit = devlink_nl_cmd_eswitch_set_doit, 5316 .flags = GENL_ADMIN_PERM, 5317 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5318 DEVLINK_NL_FLAG_NO_LOCK, 5319 }, 5320 { 5321 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET, 5322 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5323 .doit = devlink_nl_cmd_dpipe_table_get, 5324 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5325 /* can be retrieved by unprivileged users */ 5326 }, 5327 { 5328 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET, 5329 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5330 .doit = devlink_nl_cmd_dpipe_entries_get, 5331 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5332 /* can be retrieved by unprivileged users */ 5333 }, 5334 { 5335 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET, 5336 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5337 .doit = devlink_nl_cmd_dpipe_headers_get, 5338 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5339 /* can be retrieved by unprivileged users */ 5340 }, 5341 { 5342 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET, 5343 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5344 .doit = devlink_nl_cmd_dpipe_table_counters_set, 5345 .flags = GENL_ADMIN_PERM, 5346 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5347 }, 5348 { 5349 .cmd = DEVLINK_CMD_RESOURCE_SET, 5350 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5351 .doit = devlink_nl_cmd_resource_set, 5352 .flags = GENL_ADMIN_PERM, 5353 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5354 }, 5355 { 5356 .cmd = DEVLINK_CMD_RESOURCE_DUMP, 5357 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5358 .doit = devlink_nl_cmd_resource_dump, 5359 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5360 /* can be retrieved by unprivileged users */ 5361 }, 5362 { 5363 .cmd = DEVLINK_CMD_RELOAD, 5364 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5365 .doit = devlink_nl_cmd_reload, 5366 .flags = GENL_ADMIN_PERM, 5367 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5368 DEVLINK_NL_FLAG_NO_LOCK, 5369 }, 5370 { 5371 .cmd = DEVLINK_CMD_PARAM_GET, 5372 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5373 .doit = devlink_nl_cmd_param_get_doit, 5374 .dumpit = devlink_nl_cmd_param_get_dumpit, 5375 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5376 /* can be retrieved by unprivileged users */ 5377 }, 5378 { 5379 .cmd = DEVLINK_CMD_PARAM_SET, 5380 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5381 .doit = devlink_nl_cmd_param_set_doit, 5382 .flags = GENL_ADMIN_PERM, 5383 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5384 }, 5385 { 5386 .cmd = DEVLINK_CMD_PORT_PARAM_GET, 5387 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5388 .doit = devlink_nl_cmd_port_param_get_doit, 5389 .dumpit = devlink_nl_cmd_port_param_get_dumpit, 5390 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 5391 /* can be retrieved by unprivileged users */ 5392 }, 5393 { 5394 .cmd = DEVLINK_CMD_PORT_PARAM_SET, 5395 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5396 .doit = devlink_nl_cmd_port_param_set_doit, 5397 .flags = GENL_ADMIN_PERM, 5398 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 5399 }, 5400 { 5401 .cmd = DEVLINK_CMD_REGION_GET, 5402 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5403 .doit = devlink_nl_cmd_region_get_doit, 5404 .dumpit = devlink_nl_cmd_region_get_dumpit, 5405 .flags = GENL_ADMIN_PERM, 5406 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5407 }, 5408 { 5409 .cmd = DEVLINK_CMD_REGION_DEL, 5410 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5411 .doit = devlink_nl_cmd_region_del, 5412 .flags = GENL_ADMIN_PERM, 5413 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5414 }, 5415 { 5416 .cmd = DEVLINK_CMD_REGION_READ, 5417 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5418 .dumpit = devlink_nl_cmd_region_read_dumpit, 5419 .flags = GENL_ADMIN_PERM, 5420 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5421 }, 5422 { 5423 .cmd = DEVLINK_CMD_INFO_GET, 5424 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5425 .doit = devlink_nl_cmd_info_get_doit, 5426 .dumpit = devlink_nl_cmd_info_get_dumpit, 5427 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5428 /* can be retrieved by unprivileged users */ 5429 }, 5430 { 5431 .cmd = DEVLINK_CMD_HEALTH_REPORTER_GET, 5432 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5433 .doit = devlink_nl_cmd_health_reporter_get_doit, 5434 .dumpit = devlink_nl_cmd_health_reporter_get_dumpit, 5435 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5436 DEVLINK_NL_FLAG_NO_LOCK, 5437 /* can be retrieved by unprivileged users */ 5438 }, 5439 { 5440 .cmd = DEVLINK_CMD_HEALTH_REPORTER_SET, 5441 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5442 .doit = devlink_nl_cmd_health_reporter_set_doit, 5443 .flags = GENL_ADMIN_PERM, 5444 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5445 DEVLINK_NL_FLAG_NO_LOCK, 5446 }, 5447 { 5448 .cmd = DEVLINK_CMD_HEALTH_REPORTER_RECOVER, 5449 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5450 .doit = devlink_nl_cmd_health_reporter_recover_doit, 5451 .flags = GENL_ADMIN_PERM, 5452 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5453 DEVLINK_NL_FLAG_NO_LOCK, 5454 }, 5455 { 5456 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 5457 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5458 .doit = devlink_nl_cmd_health_reporter_diagnose_doit, 5459 .flags = GENL_ADMIN_PERM, 5460 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5461 DEVLINK_NL_FLAG_NO_LOCK, 5462 }, 5463 { 5464 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET, 5465 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5466 .dumpit = devlink_nl_cmd_health_reporter_dump_get_dumpit, 5467 .flags = GENL_ADMIN_PERM, 5468 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5469 DEVLINK_NL_FLAG_NO_LOCK, 5470 }, 5471 { 5472 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR, 5473 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5474 .doit = devlink_nl_cmd_health_reporter_dump_clear_doit, 5475 .flags = GENL_ADMIN_PERM, 5476 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5477 DEVLINK_NL_FLAG_NO_LOCK, 5478 }, 5479 { 5480 .cmd = DEVLINK_CMD_FLASH_UPDATE, 5481 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 5482 .doit = devlink_nl_cmd_flash_update, 5483 .flags = GENL_ADMIN_PERM, 5484 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5485 }, 5486}; 5487 5488static struct genl_family devlink_nl_family __ro_after_init = { 5489 .name = DEVLINK_GENL_NAME, 5490 .version = DEVLINK_GENL_VERSION, 5491 .maxattr = DEVLINK_ATTR_MAX, 5492 .policy = devlink_nl_policy, 5493 .netnsok = true, 5494 .pre_doit = devlink_nl_pre_doit, 5495 .post_doit = devlink_nl_post_doit, 5496 .module = THIS_MODULE, 5497 .ops = devlink_nl_ops, 5498 .n_ops = ARRAY_SIZE(devlink_nl_ops), 5499 .mcgrps = devlink_nl_mcgrps, 5500 .n_mcgrps = ARRAY_SIZE(devlink_nl_mcgrps), 5501}; 5502 5503/** 5504 * devlink_alloc - Allocate new devlink instance resources 5505 * 5506 * @ops: ops 5507 * @priv_size: size of user private data 5508 * 5509 * Allocate new devlink instance resources, including devlink index 5510 * and name. 5511 */ 5512struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size) 5513{ 5514 struct devlink *devlink; 5515 5516 if (WARN_ON(!ops)) 5517 return NULL; 5518 5519 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL); 5520 if (!devlink) 5521 return NULL; 5522 devlink->ops = ops; 5523 devlink_net_set(devlink, &init_net); 5524 INIT_LIST_HEAD(&devlink->port_list); 5525 INIT_LIST_HEAD(&devlink->sb_list); 5526 INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list); 5527 INIT_LIST_HEAD(&devlink->resource_list); 5528 INIT_LIST_HEAD(&devlink->param_list); 5529 INIT_LIST_HEAD(&devlink->region_list); 5530 INIT_LIST_HEAD(&devlink->reporter_list); 5531 mutex_init(&devlink->lock); 5532 mutex_init(&devlink->reporters_lock); 5533 return devlink; 5534} 5535EXPORT_SYMBOL_GPL(devlink_alloc); 5536 5537/** 5538 * devlink_register - Register devlink instance 5539 * 5540 * @devlink: devlink 5541 * @dev: parent device 5542 */ 5543int devlink_register(struct devlink *devlink, struct device *dev) 5544{ 5545 mutex_lock(&devlink_mutex); 5546 devlink->dev = dev; 5547 list_add_tail(&devlink->list, &devlink_list); 5548 devlink_notify(devlink, DEVLINK_CMD_NEW); 5549 mutex_unlock(&devlink_mutex); 5550 return 0; 5551} 5552EXPORT_SYMBOL_GPL(devlink_register); 5553 5554/** 5555 * devlink_unregister - Unregister devlink instance 5556 * 5557 * @devlink: devlink 5558 */ 5559void devlink_unregister(struct devlink *devlink) 5560{ 5561 mutex_lock(&devlink_mutex); 5562 devlink_notify(devlink, DEVLINK_CMD_DEL); 5563 list_del(&devlink->list); 5564 mutex_unlock(&devlink_mutex); 5565} 5566EXPORT_SYMBOL_GPL(devlink_unregister); 5567 5568/** 5569 * devlink_free - Free devlink instance resources 5570 * 5571 * @devlink: devlink 5572 */ 5573void devlink_free(struct devlink *devlink) 5574{ 5575 mutex_destroy(&devlink->reporters_lock); 5576 mutex_destroy(&devlink->lock); 5577 WARN_ON(!list_empty(&devlink->reporter_list)); 5578 WARN_ON(!list_empty(&devlink->region_list)); 5579 WARN_ON(!list_empty(&devlink->param_list)); 5580 WARN_ON(!list_empty(&devlink->resource_list)); 5581 WARN_ON(!list_empty(&devlink->dpipe_table_list)); 5582 WARN_ON(!list_empty(&devlink->sb_list)); 5583 WARN_ON(!list_empty(&devlink->port_list)); 5584 5585 kfree(devlink); 5586} 5587EXPORT_SYMBOL_GPL(devlink_free); 5588 5589static void devlink_port_type_warn(struct work_struct *work) 5590{ 5591 WARN(true, "Type was not set for devlink port."); 5592} 5593 5594static bool devlink_port_type_should_warn(struct devlink_port *devlink_port) 5595{ 5596 /* Ignore CPU and DSA flavours. */ 5597 return devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_CPU && 5598 devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_DSA; 5599} 5600 5601#define DEVLINK_PORT_TYPE_WARN_TIMEOUT (HZ * 30) 5602 5603static void devlink_port_type_warn_schedule(struct devlink_port *devlink_port) 5604{ 5605 if (!devlink_port_type_should_warn(devlink_port)) 5606 return; 5607 /* Schedule a work to WARN in case driver does not set port 5608 * type within timeout. 5609 */ 5610 schedule_delayed_work(&devlink_port->type_warn_dw, 5611 DEVLINK_PORT_TYPE_WARN_TIMEOUT); 5612} 5613 5614static void devlink_port_type_warn_cancel(struct devlink_port *devlink_port) 5615{ 5616 if (!devlink_port_type_should_warn(devlink_port)) 5617 return; 5618 cancel_delayed_work_sync(&devlink_port->type_warn_dw); 5619} 5620 5621/** 5622 * devlink_port_register - Register devlink port 5623 * 5624 * @devlink: devlink 5625 * @devlink_port: devlink port 5626 * @port_index: driver-specific numerical identifier of the port 5627 * 5628 * Register devlink port with provided port index. User can use 5629 * any indexing, even hw-related one. devlink_port structure 5630 * is convenient to be embedded inside user driver private structure. 5631 * Note that the caller should take care of zeroing the devlink_port 5632 * structure. 5633 */ 5634int devlink_port_register(struct devlink *devlink, 5635 struct devlink_port *devlink_port, 5636 unsigned int port_index) 5637{ 5638 mutex_lock(&devlink->lock); 5639 if (devlink_port_index_exists(devlink, port_index)) { 5640 mutex_unlock(&devlink->lock); 5641 return -EEXIST; 5642 } 5643 devlink_port->devlink = devlink; 5644 devlink_port->index = port_index; 5645 devlink_port->registered = true; 5646 spin_lock_init(&devlink_port->type_lock); 5647 list_add_tail(&devlink_port->list, &devlink->port_list); 5648 INIT_LIST_HEAD(&devlink_port->param_list); 5649 mutex_unlock(&devlink->lock); 5650 INIT_DELAYED_WORK(&devlink_port->type_warn_dw, &devlink_port_type_warn); 5651 devlink_port_type_warn_schedule(devlink_port); 5652 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 5653 return 0; 5654} 5655EXPORT_SYMBOL_GPL(devlink_port_register); 5656 5657/** 5658 * devlink_port_unregister - Unregister devlink port 5659 * 5660 * @devlink_port: devlink port 5661 */ 5662void devlink_port_unregister(struct devlink_port *devlink_port) 5663{ 5664 struct devlink *devlink = devlink_port->devlink; 5665 5666 devlink_port_type_warn_cancel(devlink_port); 5667 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL); 5668 mutex_lock(&devlink->lock); 5669 list_del(&devlink_port->list); 5670 mutex_unlock(&devlink->lock); 5671} 5672EXPORT_SYMBOL_GPL(devlink_port_unregister); 5673 5674static void __devlink_port_type_set(struct devlink_port *devlink_port, 5675 enum devlink_port_type type, 5676 void *type_dev) 5677{ 5678 if (WARN_ON(!devlink_port->registered)) 5679 return; 5680 devlink_port_type_warn_cancel(devlink_port); 5681 spin_lock(&devlink_port->type_lock); 5682 devlink_port->type = type; 5683 devlink_port->type_dev = type_dev; 5684 spin_unlock(&devlink_port->type_lock); 5685 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 5686} 5687 5688/** 5689 * devlink_port_type_eth_set - Set port type to Ethernet 5690 * 5691 * @devlink_port: devlink port 5692 * @netdev: related netdevice 5693 */ 5694void devlink_port_type_eth_set(struct devlink_port *devlink_port, 5695 struct net_device *netdev) 5696{ 5697 const struct net_device_ops *ops = netdev->netdev_ops; 5698 5699 /* If driver registers devlink port, it should set devlink port 5700 * attributes accordingly so the compat functions are called 5701 * and the original ops are not used. 5702 */ 5703 if (ops->ndo_get_phys_port_name) { 5704 /* Some drivers use the same set of ndos for netdevs 5705 * that have devlink_port registered and also for 5706 * those who don't. Make sure that ndo_get_phys_port_name 5707 * returns -EOPNOTSUPP here in case it is defined. 5708 * Warn if not. 5709 */ 5710 char name[IFNAMSIZ]; 5711 int err; 5712 5713 err = ops->ndo_get_phys_port_name(netdev, name, sizeof(name)); 5714 WARN_ON(err != -EOPNOTSUPP); 5715 } 5716 if (ops->ndo_get_port_parent_id) { 5717 /* Some drivers use the same set of ndos for netdevs 5718 * that have devlink_port registered and also for 5719 * those who don't. Make sure that ndo_get_port_parent_id 5720 * returns -EOPNOTSUPP here in case it is defined. 5721 * Warn if not. 5722 */ 5723 struct netdev_phys_item_id ppid; 5724 int err; 5725 5726 err = ops->ndo_get_port_parent_id(netdev, &ppid); 5727 WARN_ON(err != -EOPNOTSUPP); 5728 } 5729 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_ETH, netdev); 5730} 5731EXPORT_SYMBOL_GPL(devlink_port_type_eth_set); 5732 5733/** 5734 * devlink_port_type_ib_set - Set port type to InfiniBand 5735 * 5736 * @devlink_port: devlink port 5737 * @ibdev: related IB device 5738 */ 5739void devlink_port_type_ib_set(struct devlink_port *devlink_port, 5740 struct ib_device *ibdev) 5741{ 5742 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_IB, ibdev); 5743} 5744EXPORT_SYMBOL_GPL(devlink_port_type_ib_set); 5745 5746/** 5747 * devlink_port_type_clear - Clear port type 5748 * 5749 * @devlink_port: devlink port 5750 */ 5751void devlink_port_type_clear(struct devlink_port *devlink_port) 5752{ 5753 __devlink_port_type_set(devlink_port, DEVLINK_PORT_TYPE_NOTSET, NULL); 5754 devlink_port_type_warn_schedule(devlink_port); 5755} 5756EXPORT_SYMBOL_GPL(devlink_port_type_clear); 5757 5758static int __devlink_port_attrs_set(struct devlink_port *devlink_port, 5759 enum devlink_port_flavour flavour, 5760 const unsigned char *switch_id, 5761 unsigned char switch_id_len) 5762{ 5763 struct devlink_port_attrs *attrs = &devlink_port->attrs; 5764 5765 if (WARN_ON(devlink_port->registered)) 5766 return -EEXIST; 5767 attrs->set = true; 5768 attrs->flavour = flavour; 5769 if (switch_id) { 5770 attrs->switch_port = true; 5771 if (WARN_ON(switch_id_len > MAX_PHYS_ITEM_ID_LEN)) 5772 switch_id_len = MAX_PHYS_ITEM_ID_LEN; 5773 memcpy(attrs->switch_id.id, switch_id, switch_id_len); 5774 attrs->switch_id.id_len = switch_id_len; 5775 } else { 5776 attrs->switch_port = false; 5777 } 5778 return 0; 5779} 5780 5781/** 5782 * devlink_port_attrs_set - Set port attributes 5783 * 5784 * @devlink_port: devlink port 5785 * @flavour: flavour of the port 5786 * @port_number: number of the port that is facing user, for example 5787 * the front panel port number 5788 * @split: indicates if this is split port 5789 * @split_subport_number: if the port is split, this is the number 5790 * of subport. 5791 * @switch_id: if the port is part of switch, this is buffer with ID, 5792 * otwerwise this is NULL 5793 * @switch_id_len: length of the switch_id buffer 5794 */ 5795void devlink_port_attrs_set(struct devlink_port *devlink_port, 5796 enum devlink_port_flavour flavour, 5797 u32 port_number, bool split, 5798 u32 split_subport_number, 5799 const unsigned char *switch_id, 5800 unsigned char switch_id_len) 5801{ 5802 struct devlink_port_attrs *attrs = &devlink_port->attrs; 5803 int ret; 5804 5805 ret = __devlink_port_attrs_set(devlink_port, flavour, 5806 switch_id, switch_id_len); 5807 if (ret) 5808 return; 5809 attrs->split = split; 5810 attrs->phys.port_number = port_number; 5811 attrs->phys.split_subport_number = split_subport_number; 5812} 5813EXPORT_SYMBOL_GPL(devlink_port_attrs_set); 5814 5815/** 5816 * devlink_port_attrs_pci_pf_set - Set PCI PF port attributes 5817 * 5818 * @devlink_port: devlink port 5819 * @pf: associated PF for the devlink port instance 5820 * @switch_id: if the port is part of switch, this is buffer with ID, 5821 * otherwise this is NULL 5822 * @switch_id_len: length of the switch_id buffer 5823 */ 5824void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, 5825 const unsigned char *switch_id, 5826 unsigned char switch_id_len, u16 pf) 5827{ 5828 struct devlink_port_attrs *attrs = &devlink_port->attrs; 5829 int ret; 5830 5831 ret = __devlink_port_attrs_set(devlink_port, 5832 DEVLINK_PORT_FLAVOUR_PCI_PF, 5833 switch_id, switch_id_len); 5834 if (ret) 5835 return; 5836 5837 attrs->pci_pf.pf = pf; 5838} 5839EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_pf_set); 5840 5841/** 5842 * devlink_port_attrs_pci_vf_set - Set PCI VF port attributes 5843 * 5844 * @devlink_port: devlink port 5845 * @pf: associated PF for the devlink port instance 5846 * @vf: associated VF of a PF for the devlink port instance 5847 * @switch_id: if the port is part of switch, this is buffer with ID, 5848 * otherwise this is NULL 5849 * @switch_id_len: length of the switch_id buffer 5850 */ 5851void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, 5852 const unsigned char *switch_id, 5853 unsigned char switch_id_len, 5854 u16 pf, u16 vf) 5855{ 5856 struct devlink_port_attrs *attrs = &devlink_port->attrs; 5857 int ret; 5858 5859 ret = __devlink_port_attrs_set(devlink_port, 5860 DEVLINK_PORT_FLAVOUR_PCI_VF, 5861 switch_id, switch_id_len); 5862 if (ret) 5863 return; 5864 attrs->pci_vf.pf = pf; 5865 attrs->pci_vf.vf = vf; 5866} 5867EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_vf_set); 5868 5869static int __devlink_port_phys_port_name_get(struct devlink_port *devlink_port, 5870 char *name, size_t len) 5871{ 5872 struct devlink_port_attrs *attrs = &devlink_port->attrs; 5873 int n = 0; 5874 5875 if (!attrs->set) 5876 return -EOPNOTSUPP; 5877 5878 switch (attrs->flavour) { 5879 case DEVLINK_PORT_FLAVOUR_PHYSICAL: 5880 if (!attrs->split) 5881 n = snprintf(name, len, "p%u", attrs->phys.port_number); 5882 else 5883 n = snprintf(name, len, "p%us%u", 5884 attrs->phys.port_number, 5885 attrs->phys.split_subport_number); 5886 break; 5887 case DEVLINK_PORT_FLAVOUR_CPU: 5888 case DEVLINK_PORT_FLAVOUR_DSA: 5889 /* As CPU and DSA ports do not have a netdevice associated 5890 * case should not ever happen. 5891 */ 5892 WARN_ON(1); 5893 return -EINVAL; 5894 case DEVLINK_PORT_FLAVOUR_PCI_PF: 5895 n = snprintf(name, len, "pf%u", attrs->pci_pf.pf); 5896 break; 5897 case DEVLINK_PORT_FLAVOUR_PCI_VF: 5898 n = snprintf(name, len, "pf%uvf%u", 5899 attrs->pci_vf.pf, attrs->pci_vf.vf); 5900 break; 5901 } 5902 5903 if (n >= len) 5904 return -EINVAL; 5905 5906 return 0; 5907} 5908 5909int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, 5910 u32 size, u16 ingress_pools_count, 5911 u16 egress_pools_count, u16 ingress_tc_count, 5912 u16 egress_tc_count) 5913{ 5914 struct devlink_sb *devlink_sb; 5915 int err = 0; 5916 5917 mutex_lock(&devlink->lock); 5918 if (devlink_sb_index_exists(devlink, sb_index)) { 5919 err = -EEXIST; 5920 goto unlock; 5921 } 5922 5923 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL); 5924 if (!devlink_sb) { 5925 err = -ENOMEM; 5926 goto unlock; 5927 } 5928 devlink_sb->index = sb_index; 5929 devlink_sb->size = size; 5930 devlink_sb->ingress_pools_count = ingress_pools_count; 5931 devlink_sb->egress_pools_count = egress_pools_count; 5932 devlink_sb->ingress_tc_count = ingress_tc_count; 5933 devlink_sb->egress_tc_count = egress_tc_count; 5934 list_add_tail(&devlink_sb->list, &devlink->sb_list); 5935unlock: 5936 mutex_unlock(&devlink->lock); 5937 return err; 5938} 5939EXPORT_SYMBOL_GPL(devlink_sb_register); 5940 5941void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index) 5942{ 5943 struct devlink_sb *devlink_sb; 5944 5945 mutex_lock(&devlink->lock); 5946 devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 5947 WARN_ON(!devlink_sb); 5948 list_del(&devlink_sb->list); 5949 mutex_unlock(&devlink->lock); 5950 kfree(devlink_sb); 5951} 5952EXPORT_SYMBOL_GPL(devlink_sb_unregister); 5953 5954/** 5955 * devlink_dpipe_headers_register - register dpipe headers 5956 * 5957 * @devlink: devlink 5958 * @dpipe_headers: dpipe header array 5959 * 5960 * Register the headers supported by hardware. 5961 */ 5962int devlink_dpipe_headers_register(struct devlink *devlink, 5963 struct devlink_dpipe_headers *dpipe_headers) 5964{ 5965 mutex_lock(&devlink->lock); 5966 devlink->dpipe_headers = dpipe_headers; 5967 mutex_unlock(&devlink->lock); 5968 return 0; 5969} 5970EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register); 5971 5972/** 5973 * devlink_dpipe_headers_unregister - unregister dpipe headers 5974 * 5975 * @devlink: devlink 5976 * 5977 * Unregister the headers supported by hardware. 5978 */ 5979void devlink_dpipe_headers_unregister(struct devlink *devlink) 5980{ 5981 mutex_lock(&devlink->lock); 5982 devlink->dpipe_headers = NULL; 5983 mutex_unlock(&devlink->lock); 5984} 5985EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister); 5986 5987/** 5988 * devlink_dpipe_table_counter_enabled - check if counter allocation 5989 * required 5990 * @devlink: devlink 5991 * @table_name: tables name 5992 * 5993 * Used by driver to check if counter allocation is required. 5994 * After counter allocation is turned on the table entries 5995 * are updated to include counter statistics. 5996 * 5997 * After that point on the driver must respect the counter 5998 * state so that each entry added to the table is added 5999 * with a counter. 6000 */ 6001bool devlink_dpipe_table_counter_enabled(struct devlink *devlink, 6002 const char *table_name) 6003{ 6004 struct devlink_dpipe_table *table; 6005 bool enabled; 6006 6007 rcu_read_lock(); 6008 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 6009 table_name); 6010 enabled = false; 6011 if (table) 6012 enabled = table->counters_enabled; 6013 rcu_read_unlock(); 6014 return enabled; 6015} 6016EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled); 6017 6018/** 6019 * devlink_dpipe_table_register - register dpipe table 6020 * 6021 * @devlink: devlink 6022 * @table_name: table name 6023 * @table_ops: table ops 6024 * @priv: priv 6025 * @counter_control_extern: external control for counters 6026 */ 6027int devlink_dpipe_table_register(struct devlink *devlink, 6028 const char *table_name, 6029 struct devlink_dpipe_table_ops *table_ops, 6030 void *priv, bool counter_control_extern) 6031{ 6032 struct devlink_dpipe_table *table; 6033 6034 if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name)) 6035 return -EEXIST; 6036 6037 if (WARN_ON(!table_ops->size_get)) 6038 return -EINVAL; 6039 6040 table = kzalloc(sizeof(*table), GFP_KERNEL); 6041 if (!table) 6042 return -ENOMEM; 6043 6044 table->name = table_name; 6045 table->table_ops = table_ops; 6046 table->priv = priv; 6047 table->counter_control_extern = counter_control_extern; 6048 6049 mutex_lock(&devlink->lock); 6050 list_add_tail_rcu(&table->list, &devlink->dpipe_table_list); 6051 mutex_unlock(&devlink->lock); 6052 return 0; 6053} 6054EXPORT_SYMBOL_GPL(devlink_dpipe_table_register); 6055 6056/** 6057 * devlink_dpipe_table_unregister - unregister dpipe table 6058 * 6059 * @devlink: devlink 6060 * @table_name: table name 6061 */ 6062void devlink_dpipe_table_unregister(struct devlink *devlink, 6063 const char *table_name) 6064{ 6065 struct devlink_dpipe_table *table; 6066 6067 mutex_lock(&devlink->lock); 6068 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 6069 table_name); 6070 if (!table) 6071 goto unlock; 6072 list_del_rcu(&table->list); 6073 mutex_unlock(&devlink->lock); 6074 kfree_rcu(table, rcu); 6075 return; 6076unlock: 6077 mutex_unlock(&devlink->lock); 6078} 6079EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister); 6080 6081/** 6082 * devlink_resource_register - devlink resource register 6083 * 6084 * @devlink: devlink 6085 * @resource_name: resource's name 6086 * @resource_size: resource's size 6087 * @resource_id: resource's id 6088 * @parent_resource_id: resource's parent id 6089 * @size_params: size parameters 6090 */ 6091int devlink_resource_register(struct devlink *devlink, 6092 const char *resource_name, 6093 u64 resource_size, 6094 u64 resource_id, 6095 u64 parent_resource_id, 6096 const struct devlink_resource_size_params *size_params) 6097{ 6098 struct devlink_resource *resource; 6099 struct list_head *resource_list; 6100 bool top_hierarchy; 6101 int err = 0; 6102 6103 top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP; 6104 6105 mutex_lock(&devlink->lock); 6106 resource = devlink_resource_find(devlink, NULL, resource_id); 6107 if (resource) { 6108 err = -EINVAL; 6109 goto out; 6110 } 6111 6112 resource = kzalloc(sizeof(*resource), GFP_KERNEL); 6113 if (!resource) { 6114 err = -ENOMEM; 6115 goto out; 6116 } 6117 6118 if (top_hierarchy) { 6119 resource_list = &devlink->resource_list; 6120 } else { 6121 struct devlink_resource *parent_resource; 6122 6123 parent_resource = devlink_resource_find(devlink, NULL, 6124 parent_resource_id); 6125 if (parent_resource) { 6126 resource_list = &parent_resource->resource_list; 6127 resource->parent = parent_resource; 6128 } else { 6129 kfree(resource); 6130 err = -EINVAL; 6131 goto out; 6132 } 6133 } 6134 6135 resource->name = resource_name; 6136 resource->size = resource_size; 6137 resource->size_new = resource_size; 6138 resource->id = resource_id; 6139 resource->size_valid = true; 6140 memcpy(&resource->size_params, size_params, 6141 sizeof(resource->size_params)); 6142 INIT_LIST_HEAD(&resource->resource_list); 6143 list_add_tail(&resource->list, resource_list); 6144out: 6145 mutex_unlock(&devlink->lock); 6146 return err; 6147} 6148EXPORT_SYMBOL_GPL(devlink_resource_register); 6149 6150/** 6151 * devlink_resources_unregister - free all resources 6152 * 6153 * @devlink: devlink 6154 * @resource: resource 6155 */ 6156void devlink_resources_unregister(struct devlink *devlink, 6157 struct devlink_resource *resource) 6158{ 6159 struct devlink_resource *tmp, *child_resource; 6160 struct list_head *resource_list; 6161 6162 if (resource) 6163 resource_list = &resource->resource_list; 6164 else 6165 resource_list = &devlink->resource_list; 6166 6167 if (!resource) 6168 mutex_lock(&devlink->lock); 6169 6170 list_for_each_entry_safe(child_resource, tmp, resource_list, list) { 6171 devlink_resources_unregister(devlink, child_resource); 6172 list_del(&child_resource->list); 6173 kfree(child_resource); 6174 } 6175 6176 if (!resource) 6177 mutex_unlock(&devlink->lock); 6178} 6179EXPORT_SYMBOL_GPL(devlink_resources_unregister); 6180 6181/** 6182 * devlink_resource_size_get - get and update size 6183 * 6184 * @devlink: devlink 6185 * @resource_id: the requested resource id 6186 * @p_resource_size: ptr to update 6187 */ 6188int devlink_resource_size_get(struct devlink *devlink, 6189 u64 resource_id, 6190 u64 *p_resource_size) 6191{ 6192 struct devlink_resource *resource; 6193 int err = 0; 6194 6195 mutex_lock(&devlink->lock); 6196 resource = devlink_resource_find(devlink, NULL, resource_id); 6197 if (!resource) { 6198 err = -EINVAL; 6199 goto out; 6200 } 6201 *p_resource_size = resource->size_new; 6202 resource->size = resource->size_new; 6203out: 6204 mutex_unlock(&devlink->lock); 6205 return err; 6206} 6207EXPORT_SYMBOL_GPL(devlink_resource_size_get); 6208 6209/** 6210 * devlink_dpipe_table_resource_set - set the resource id 6211 * 6212 * @devlink: devlink 6213 * @table_name: table name 6214 * @resource_id: resource id 6215 * @resource_units: number of resource's units consumed per table's entry 6216 */ 6217int devlink_dpipe_table_resource_set(struct devlink *devlink, 6218 const char *table_name, u64 resource_id, 6219 u64 resource_units) 6220{ 6221 struct devlink_dpipe_table *table; 6222 int err = 0; 6223 6224 mutex_lock(&devlink->lock); 6225 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 6226 table_name); 6227 if (!table) { 6228 err = -EINVAL; 6229 goto out; 6230 } 6231 table->resource_id = resource_id; 6232 table->resource_units = resource_units; 6233 table->resource_valid = true; 6234out: 6235 mutex_unlock(&devlink->lock); 6236 return err; 6237} 6238EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set); 6239 6240/** 6241 * devlink_resource_occ_get_register - register occupancy getter 6242 * 6243 * @devlink: devlink 6244 * @resource_id: resource id 6245 * @occ_get: occupancy getter callback 6246 * @occ_get_priv: occupancy getter callback priv 6247 */ 6248void devlink_resource_occ_get_register(struct devlink *devlink, 6249 u64 resource_id, 6250 devlink_resource_occ_get_t *occ_get, 6251 void *occ_get_priv) 6252{ 6253 struct devlink_resource *resource; 6254 6255 mutex_lock(&devlink->lock); 6256 resource = devlink_resource_find(devlink, NULL, resource_id); 6257 if (WARN_ON(!resource)) 6258 goto out; 6259 WARN_ON(resource->occ_get); 6260 6261 resource->occ_get = occ_get; 6262 resource->occ_get_priv = occ_get_priv; 6263out: 6264 mutex_unlock(&devlink->lock); 6265} 6266EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register); 6267 6268/** 6269 * devlink_resource_occ_get_unregister - unregister occupancy getter 6270 * 6271 * @devlink: devlink 6272 * @resource_id: resource id 6273 */ 6274void devlink_resource_occ_get_unregister(struct devlink *devlink, 6275 u64 resource_id) 6276{ 6277 struct devlink_resource *resource; 6278 6279 mutex_lock(&devlink->lock); 6280 resource = devlink_resource_find(devlink, NULL, resource_id); 6281 if (WARN_ON(!resource)) 6282 goto out; 6283 WARN_ON(!resource->occ_get); 6284 6285 resource->occ_get = NULL; 6286 resource->occ_get_priv = NULL; 6287out: 6288 mutex_unlock(&devlink->lock); 6289} 6290EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister); 6291 6292static int devlink_param_verify(const struct devlink_param *param) 6293{ 6294 if (!param || !param->name || !param->supported_cmodes) 6295 return -EINVAL; 6296 if (param->generic) 6297 return devlink_param_generic_verify(param); 6298 else 6299 return devlink_param_driver_verify(param); 6300} 6301 6302static int __devlink_params_register(struct devlink *devlink, 6303 unsigned int port_index, 6304 struct list_head *param_list, 6305 const struct devlink_param *params, 6306 size_t params_count, 6307 enum devlink_command reg_cmd, 6308 enum devlink_command unreg_cmd) 6309{ 6310 const struct devlink_param *param = params; 6311 int i; 6312 int err; 6313 6314 mutex_lock(&devlink->lock); 6315 for (i = 0; i < params_count; i++, param++) { 6316 err = devlink_param_verify(param); 6317 if (err) 6318 goto rollback; 6319 6320 err = devlink_param_register_one(devlink, port_index, 6321 param_list, param, reg_cmd); 6322 if (err) 6323 goto rollback; 6324 } 6325 6326 mutex_unlock(&devlink->lock); 6327 return 0; 6328 6329rollback: 6330 if (!i) 6331 goto unlock; 6332 for (param--; i > 0; i--, param--) 6333 devlink_param_unregister_one(devlink, port_index, param_list, 6334 param, unreg_cmd); 6335unlock: 6336 mutex_unlock(&devlink->lock); 6337 return err; 6338} 6339 6340static void __devlink_params_unregister(struct devlink *devlink, 6341 unsigned int port_index, 6342 struct list_head *param_list, 6343 const struct devlink_param *params, 6344 size_t params_count, 6345 enum devlink_command cmd) 6346{ 6347 const struct devlink_param *param = params; 6348 int i; 6349 6350 mutex_lock(&devlink->lock); 6351 for (i = 0; i < params_count; i++, param++) 6352 devlink_param_unregister_one(devlink, 0, param_list, param, 6353 cmd); 6354 mutex_unlock(&devlink->lock); 6355} 6356 6357/** 6358 * devlink_params_register - register configuration parameters 6359 * 6360 * @devlink: devlink 6361 * @params: configuration parameters array 6362 * @params_count: number of parameters provided 6363 * 6364 * Register the configuration parameters supported by the driver. 6365 */ 6366int devlink_params_register(struct devlink *devlink, 6367 const struct devlink_param *params, 6368 size_t params_count) 6369{ 6370 return __devlink_params_register(devlink, 0, &devlink->param_list, 6371 params, params_count, 6372 DEVLINK_CMD_PARAM_NEW, 6373 DEVLINK_CMD_PARAM_DEL); 6374} 6375EXPORT_SYMBOL_GPL(devlink_params_register); 6376 6377/** 6378 * devlink_params_unregister - unregister configuration parameters 6379 * @devlink: devlink 6380 * @params: configuration parameters to unregister 6381 * @params_count: number of parameters provided 6382 */ 6383void devlink_params_unregister(struct devlink *devlink, 6384 const struct devlink_param *params, 6385 size_t params_count) 6386{ 6387 return __devlink_params_unregister(devlink, 0, &devlink->param_list, 6388 params, params_count, 6389 DEVLINK_CMD_PARAM_DEL); 6390} 6391EXPORT_SYMBOL_GPL(devlink_params_unregister); 6392 6393/** 6394 * devlink_params_publish - publish configuration parameters 6395 * 6396 * @devlink: devlink 6397 * 6398 * Publish previously registered configuration parameters. 6399 */ 6400void devlink_params_publish(struct devlink *devlink) 6401{ 6402 struct devlink_param_item *param_item; 6403 6404 list_for_each_entry(param_item, &devlink->param_list, list) { 6405 if (param_item->published) 6406 continue; 6407 param_item->published = true; 6408 devlink_param_notify(devlink, 0, param_item, 6409 DEVLINK_CMD_PARAM_NEW); 6410 } 6411} 6412EXPORT_SYMBOL_GPL(devlink_params_publish); 6413 6414/** 6415 * devlink_params_unpublish - unpublish configuration parameters 6416 * 6417 * @devlink: devlink 6418 * 6419 * Unpublish previously registered configuration parameters. 6420 */ 6421void devlink_params_unpublish(struct devlink *devlink) 6422{ 6423 struct devlink_param_item *param_item; 6424 6425 list_for_each_entry(param_item, &devlink->param_list, list) { 6426 if (!param_item->published) 6427 continue; 6428 param_item->published = false; 6429 devlink_param_notify(devlink, 0, param_item, 6430 DEVLINK_CMD_PARAM_DEL); 6431 } 6432} 6433EXPORT_SYMBOL_GPL(devlink_params_unpublish); 6434 6435/** 6436 * devlink_port_params_register - register port configuration parameters 6437 * 6438 * @devlink_port: devlink port 6439 * @params: configuration parameters array 6440 * @params_count: number of parameters provided 6441 * 6442 * Register the configuration parameters supported by the port. 6443 */ 6444int devlink_port_params_register(struct devlink_port *devlink_port, 6445 const struct devlink_param *params, 6446 size_t params_count) 6447{ 6448 return __devlink_params_register(devlink_port->devlink, 6449 devlink_port->index, 6450 &devlink_port->param_list, params, 6451 params_count, 6452 DEVLINK_CMD_PORT_PARAM_NEW, 6453 DEVLINK_CMD_PORT_PARAM_DEL); 6454} 6455EXPORT_SYMBOL_GPL(devlink_port_params_register); 6456 6457/** 6458 * devlink_port_params_unregister - unregister port configuration 6459 * parameters 6460 * 6461 * @devlink_port: devlink port 6462 * @params: configuration parameters array 6463 * @params_count: number of parameters provided 6464 */ 6465void devlink_port_params_unregister(struct devlink_port *devlink_port, 6466 const struct devlink_param *params, 6467 size_t params_count) 6468{ 6469 return __devlink_params_unregister(devlink_port->devlink, 6470 devlink_port->index, 6471 &devlink_port->param_list, 6472 params, params_count, 6473 DEVLINK_CMD_PORT_PARAM_DEL); 6474} 6475EXPORT_SYMBOL_GPL(devlink_port_params_unregister); 6476 6477static int 6478__devlink_param_driverinit_value_get(struct list_head *param_list, u32 param_id, 6479 union devlink_param_value *init_val) 6480{ 6481 struct devlink_param_item *param_item; 6482 6483 param_item = devlink_param_find_by_id(param_list, param_id); 6484 if (!param_item) 6485 return -EINVAL; 6486 6487 if (!param_item->driverinit_value_valid || 6488 !devlink_param_cmode_is_supported(param_item->param, 6489 DEVLINK_PARAM_CMODE_DRIVERINIT)) 6490 return -EOPNOTSUPP; 6491 6492 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING) 6493 strcpy(init_val->vstr, param_item->driverinit_value.vstr); 6494 else 6495 *init_val = param_item->driverinit_value; 6496 6497 return 0; 6498} 6499 6500static int 6501__devlink_param_driverinit_value_set(struct devlink *devlink, 6502 unsigned int port_index, 6503 struct list_head *param_list, u32 param_id, 6504 union devlink_param_value init_val, 6505 enum devlink_command cmd) 6506{ 6507 struct devlink_param_item *param_item; 6508 6509 param_item = devlink_param_find_by_id(param_list, param_id); 6510 if (!param_item) 6511 return -EINVAL; 6512 6513 if (!devlink_param_cmode_is_supported(param_item->param, 6514 DEVLINK_PARAM_CMODE_DRIVERINIT)) 6515 return -EOPNOTSUPP; 6516 6517 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING) 6518 strcpy(param_item->driverinit_value.vstr, init_val.vstr); 6519 else 6520 param_item->driverinit_value = init_val; 6521 param_item->driverinit_value_valid = true; 6522 6523 devlink_param_notify(devlink, port_index, param_item, cmd); 6524 return 0; 6525} 6526 6527/** 6528 * devlink_param_driverinit_value_get - get configuration parameter 6529 * value for driver initializing 6530 * 6531 * @devlink: devlink 6532 * @param_id: parameter ID 6533 * @init_val: value of parameter in driverinit configuration mode 6534 * 6535 * This function should be used by the driver to get driverinit 6536 * configuration for initialization after reload command. 6537 */ 6538int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id, 6539 union devlink_param_value *init_val) 6540{ 6541 if (!devlink->ops->reload) 6542 return -EOPNOTSUPP; 6543 6544 return __devlink_param_driverinit_value_get(&devlink->param_list, 6545 param_id, init_val); 6546} 6547EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_get); 6548 6549/** 6550 * devlink_param_driverinit_value_set - set value of configuration 6551 * parameter for driverinit 6552 * configuration mode 6553 * 6554 * @devlink: devlink 6555 * @param_id: parameter ID 6556 * @init_val: value of parameter to set for driverinit configuration mode 6557 * 6558 * This function should be used by the driver to set driverinit 6559 * configuration mode default value. 6560 */ 6561int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id, 6562 union devlink_param_value init_val) 6563{ 6564 return __devlink_param_driverinit_value_set(devlink, 0, 6565 &devlink->param_list, 6566 param_id, init_val, 6567 DEVLINK_CMD_PARAM_NEW); 6568} 6569EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_set); 6570 6571/** 6572 * devlink_port_param_driverinit_value_get - get configuration parameter 6573 * value for driver initializing 6574 * 6575 * @devlink_port: devlink_port 6576 * @param_id: parameter ID 6577 * @init_val: value of parameter in driverinit configuration mode 6578 * 6579 * This function should be used by the driver to get driverinit 6580 * configuration for initialization after reload command. 6581 */ 6582int devlink_port_param_driverinit_value_get(struct devlink_port *devlink_port, 6583 u32 param_id, 6584 union devlink_param_value *init_val) 6585{ 6586 struct devlink *devlink = devlink_port->devlink; 6587 6588 if (!devlink->ops->reload) 6589 return -EOPNOTSUPP; 6590 6591 return __devlink_param_driverinit_value_get(&devlink_port->param_list, 6592 param_id, init_val); 6593} 6594EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_get); 6595 6596/** 6597 * devlink_port_param_driverinit_value_set - set value of configuration 6598 * parameter for driverinit 6599 * configuration mode 6600 * 6601 * @devlink_port: devlink_port 6602 * @param_id: parameter ID 6603 * @init_val: value of parameter to set for driverinit configuration mode 6604 * 6605 * This function should be used by the driver to set driverinit 6606 * configuration mode default value. 6607 */ 6608int devlink_port_param_driverinit_value_set(struct devlink_port *devlink_port, 6609 u32 param_id, 6610 union devlink_param_value init_val) 6611{ 6612 return __devlink_param_driverinit_value_set(devlink_port->devlink, 6613 devlink_port->index, 6614 &devlink_port->param_list, 6615 param_id, init_val, 6616 DEVLINK_CMD_PORT_PARAM_NEW); 6617} 6618EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_set); 6619 6620/** 6621 * devlink_param_value_changed - notify devlink on a parameter's value 6622 * change. Should be called by the driver 6623 * right after the change. 6624 * 6625 * @devlink: devlink 6626 * @param_id: parameter ID 6627 * 6628 * This function should be used by the driver to notify devlink on value 6629 * change, excluding driverinit configuration mode. 6630 * For driverinit configuration mode driver should use the function 6631 */ 6632void devlink_param_value_changed(struct devlink *devlink, u32 param_id) 6633{ 6634 struct devlink_param_item *param_item; 6635 6636 param_item = devlink_param_find_by_id(&devlink->param_list, param_id); 6637 WARN_ON(!param_item); 6638 6639 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW); 6640} 6641EXPORT_SYMBOL_GPL(devlink_param_value_changed); 6642 6643/** 6644 * devlink_port_param_value_changed - notify devlink on a parameter's value 6645 * change. Should be called by the driver 6646 * right after the change. 6647 * 6648 * @devlink_port: devlink_port 6649 * @param_id: parameter ID 6650 * 6651 * This function should be used by the driver to notify devlink on value 6652 * change, excluding driverinit configuration mode. 6653 * For driverinit configuration mode driver should use the function 6654 * devlink_port_param_driverinit_value_set() instead. 6655 */ 6656void devlink_port_param_value_changed(struct devlink_port *devlink_port, 6657 u32 param_id) 6658{ 6659 struct devlink_param_item *param_item; 6660 6661 param_item = devlink_param_find_by_id(&devlink_port->param_list, 6662 param_id); 6663 WARN_ON(!param_item); 6664 6665 devlink_param_notify(devlink_port->devlink, devlink_port->index, 6666 param_item, DEVLINK_CMD_PORT_PARAM_NEW); 6667} 6668EXPORT_SYMBOL_GPL(devlink_port_param_value_changed); 6669 6670/** 6671 * devlink_param_value_str_fill - Safely fill-up the string preventing 6672 * from overflow of the preallocated buffer 6673 * 6674 * @dst_val: destination devlink_param_value 6675 * @src: source buffer 6676 */ 6677void devlink_param_value_str_fill(union devlink_param_value *dst_val, 6678 const char *src) 6679{ 6680 size_t len; 6681 6682 len = strlcpy(dst_val->vstr, src, __DEVLINK_PARAM_MAX_STRING_VALUE); 6683 WARN_ON(len >= __DEVLINK_PARAM_MAX_STRING_VALUE); 6684} 6685EXPORT_SYMBOL_GPL(devlink_param_value_str_fill); 6686 6687/** 6688 * devlink_region_create - create a new address region 6689 * 6690 * @devlink: devlink 6691 * @region_name: region name 6692 * @region_max_snapshots: Maximum supported number of snapshots for region 6693 * @region_size: size of region 6694 */ 6695struct devlink_region *devlink_region_create(struct devlink *devlink, 6696 const char *region_name, 6697 u32 region_max_snapshots, 6698 u64 region_size) 6699{ 6700 struct devlink_region *region; 6701 int err = 0; 6702 6703 mutex_lock(&devlink->lock); 6704 6705 if (devlink_region_get_by_name(devlink, region_name)) { 6706 err = -EEXIST; 6707 goto unlock; 6708 } 6709 6710 region = kzalloc(sizeof(*region), GFP_KERNEL); 6711 if (!region) { 6712 err = -ENOMEM; 6713 goto unlock; 6714 } 6715 6716 region->devlink = devlink; 6717 region->max_snapshots = region_max_snapshots; 6718 region->name = region_name; 6719 region->size = region_size; 6720 INIT_LIST_HEAD(&region->snapshot_list); 6721 list_add_tail(&region->list, &devlink->region_list); 6722 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW); 6723 6724 mutex_unlock(&devlink->lock); 6725 return region; 6726 6727unlock: 6728 mutex_unlock(&devlink->lock); 6729 return ERR_PTR(err); 6730} 6731EXPORT_SYMBOL_GPL(devlink_region_create); 6732 6733/** 6734 * devlink_region_destroy - destroy address region 6735 * 6736 * @region: devlink region to destroy 6737 */ 6738void devlink_region_destroy(struct devlink_region *region) 6739{ 6740 struct devlink *devlink = region->devlink; 6741 struct devlink_snapshot *snapshot, *ts; 6742 6743 mutex_lock(&devlink->lock); 6744 6745 /* Free all snapshots of region */ 6746 list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list) 6747 devlink_region_snapshot_del(snapshot); 6748 6749 list_del(&region->list); 6750 6751 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL); 6752 mutex_unlock(&devlink->lock); 6753 kfree(region); 6754} 6755EXPORT_SYMBOL_GPL(devlink_region_destroy); 6756 6757/** 6758 * devlink_region_shapshot_id_get - get snapshot ID 6759 * 6760 * This callback should be called when adding a new snapshot, 6761 * Driver should use the same id for multiple snapshots taken 6762 * on multiple regions at the same time/by the same trigger. 6763 * 6764 * @devlink: devlink 6765 */ 6766u32 devlink_region_shapshot_id_get(struct devlink *devlink) 6767{ 6768 u32 id; 6769 6770 mutex_lock(&devlink->lock); 6771 id = ++devlink->snapshot_id; 6772 mutex_unlock(&devlink->lock); 6773 6774 return id; 6775} 6776EXPORT_SYMBOL_GPL(devlink_region_shapshot_id_get); 6777 6778/** 6779 * devlink_region_snapshot_create - create a new snapshot 6780 * This will add a new snapshot of a region. The snapshot 6781 * will be stored on the region struct and can be accessed 6782 * from devlink. This is useful for future analyses of snapshots. 6783 * Multiple snapshots can be created on a region. 6784 * The @snapshot_id should be obtained using the getter function. 6785 * 6786 * @region: devlink region of the snapshot 6787 * @data_len: size of snapshot data 6788 * @data: snapshot data 6789 * @snapshot_id: snapshot id to be created 6790 * @data_destructor: pointer to destructor function to free data 6791 */ 6792int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len, 6793 u8 *data, u32 snapshot_id, 6794 devlink_snapshot_data_dest_t *data_destructor) 6795{ 6796 struct devlink *devlink = region->devlink; 6797 struct devlink_snapshot *snapshot; 6798 int err; 6799 6800 mutex_lock(&devlink->lock); 6801 6802 /* check if region can hold one more snapshot */ 6803 if (region->cur_snapshots == region->max_snapshots) { 6804 err = -ENOMEM; 6805 goto unlock; 6806 } 6807 6808 if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { 6809 err = -EEXIST; 6810 goto unlock; 6811 } 6812 6813 snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL); 6814 if (!snapshot) { 6815 err = -ENOMEM; 6816 goto unlock; 6817 } 6818 6819 snapshot->id = snapshot_id; 6820 snapshot->region = region; 6821 snapshot->data = data; 6822 snapshot->data_len = data_len; 6823 snapshot->data_destructor = data_destructor; 6824 6825 list_add_tail(&snapshot->list, &region->snapshot_list); 6826 6827 region->cur_snapshots++; 6828 6829 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW); 6830 mutex_unlock(&devlink->lock); 6831 return 0; 6832 6833unlock: 6834 mutex_unlock(&devlink->lock); 6835 return err; 6836} 6837EXPORT_SYMBOL_GPL(devlink_region_snapshot_create); 6838 6839static void __devlink_compat_running_version(struct devlink *devlink, 6840 char *buf, size_t len) 6841{ 6842 const struct nlattr *nlattr; 6843 struct devlink_info_req req; 6844 struct sk_buff *msg; 6845 int rem, err; 6846 6847 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 6848 if (!msg) 6849 return; 6850 6851 req.msg = msg; 6852 err = devlink->ops->info_get(devlink, &req, NULL); 6853 if (err) 6854 goto free_msg; 6855 6856 nla_for_each_attr(nlattr, (void *)msg->data, msg->len, rem) { 6857 const struct nlattr *kv; 6858 int rem_kv; 6859 6860 if (nla_type(nlattr) != DEVLINK_ATTR_INFO_VERSION_RUNNING) 6861 continue; 6862 6863 nla_for_each_nested(kv, nlattr, rem_kv) { 6864 if (nla_type(kv) != DEVLINK_ATTR_INFO_VERSION_VALUE) 6865 continue; 6866 6867 strlcat(buf, nla_data(kv), len); 6868 strlcat(buf, " ", len); 6869 } 6870 } 6871free_msg: 6872 nlmsg_free(msg); 6873} 6874 6875void devlink_compat_running_version(struct net_device *dev, 6876 char *buf, size_t len) 6877{ 6878 struct devlink *devlink; 6879 6880 dev_hold(dev); 6881 rtnl_unlock(); 6882 6883 devlink = netdev_to_devlink(dev); 6884 if (!devlink || !devlink->ops->info_get) 6885 goto out; 6886 6887 mutex_lock(&devlink->lock); 6888 __devlink_compat_running_version(devlink, buf, len); 6889 mutex_unlock(&devlink->lock); 6890 6891out: 6892 rtnl_lock(); 6893 dev_put(dev); 6894} 6895 6896int devlink_compat_flash_update(struct net_device *dev, const char *file_name) 6897{ 6898 struct devlink *devlink; 6899 int ret; 6900 6901 dev_hold(dev); 6902 rtnl_unlock(); 6903 6904 devlink = netdev_to_devlink(dev); 6905 if (!devlink || !devlink->ops->flash_update) { 6906 ret = -EOPNOTSUPP; 6907 goto out; 6908 } 6909 6910 mutex_lock(&devlink->lock); 6911 ret = devlink->ops->flash_update(devlink, file_name, NULL, NULL); 6912 mutex_unlock(&devlink->lock); 6913 6914out: 6915 rtnl_lock(); 6916 dev_put(dev); 6917 6918 return ret; 6919} 6920 6921int devlink_compat_phys_port_name_get(struct net_device *dev, 6922 char *name, size_t len) 6923{ 6924 struct devlink_port *devlink_port; 6925 6926 /* RTNL mutex is held here which ensures that devlink_port 6927 * instance cannot disappear in the middle. No need to take 6928 * any devlink lock as only permanent values are accessed. 6929 */ 6930 ASSERT_RTNL(); 6931 6932 devlink_port = netdev_to_devlink_port(dev); 6933 if (!devlink_port) 6934 return -EOPNOTSUPP; 6935 6936 return __devlink_port_phys_port_name_get(devlink_port, name, len); 6937} 6938 6939int devlink_compat_switch_id_get(struct net_device *dev, 6940 struct netdev_phys_item_id *ppid) 6941{ 6942 struct devlink_port *devlink_port; 6943 6944 /* RTNL mutex is held here which ensures that devlink_port 6945 * instance cannot disappear in the middle. No need to take 6946 * any devlink lock as only permanent values are accessed. 6947 */ 6948 ASSERT_RTNL(); 6949 devlink_port = netdev_to_devlink_port(dev); 6950 if (!devlink_port || !devlink_port->attrs.switch_port) 6951 return -EOPNOTSUPP; 6952 6953 memcpy(ppid, &devlink_port->attrs.switch_id, sizeof(*ppid)); 6954 6955 return 0; 6956} 6957 6958static int __init devlink_init(void) 6959{ 6960 return genl_register_family(&devlink_nl_family); 6961} 6962 6963subsys_initcall(devlink_init);