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