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