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