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