at v5.1 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 if (!devlink->ops->info_get) { 3901 idx++; 3902 continue; 3903 } 3904 3905 mutex_lock(&devlink->lock); 3906 err = devlink_nl_info_fill(msg, devlink, DEVLINK_CMD_INFO_GET, 3907 NETLINK_CB(cb->skb).portid, 3908 cb->nlh->nlmsg_seq, NLM_F_MULTI, 3909 cb->extack); 3910 mutex_unlock(&devlink->lock); 3911 if (err) 3912 break; 3913 idx++; 3914 } 3915 mutex_unlock(&devlink_mutex); 3916 3917 cb->args[0] = idx; 3918 return msg->len; 3919} 3920 3921struct devlink_fmsg_item { 3922 struct list_head list; 3923 int attrtype; 3924 u8 nla_type; 3925 u16 len; 3926 int value[0]; 3927}; 3928 3929struct devlink_fmsg { 3930 struct list_head item_list; 3931}; 3932 3933static struct devlink_fmsg *devlink_fmsg_alloc(void) 3934{ 3935 struct devlink_fmsg *fmsg; 3936 3937 fmsg = kzalloc(sizeof(*fmsg), GFP_KERNEL); 3938 if (!fmsg) 3939 return NULL; 3940 3941 INIT_LIST_HEAD(&fmsg->item_list); 3942 3943 return fmsg; 3944} 3945 3946static void devlink_fmsg_free(struct devlink_fmsg *fmsg) 3947{ 3948 struct devlink_fmsg_item *item, *tmp; 3949 3950 list_for_each_entry_safe(item, tmp, &fmsg->item_list, list) { 3951 list_del(&item->list); 3952 kfree(item); 3953 } 3954 kfree(fmsg); 3955} 3956 3957static int devlink_fmsg_nest_common(struct devlink_fmsg *fmsg, 3958 int attrtype) 3959{ 3960 struct devlink_fmsg_item *item; 3961 3962 item = kzalloc(sizeof(*item), GFP_KERNEL); 3963 if (!item) 3964 return -ENOMEM; 3965 3966 item->attrtype = attrtype; 3967 list_add_tail(&item->list, &fmsg->item_list); 3968 3969 return 0; 3970} 3971 3972int devlink_fmsg_obj_nest_start(struct devlink_fmsg *fmsg) 3973{ 3974 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_OBJ_NEST_START); 3975} 3976EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_start); 3977 3978static int devlink_fmsg_nest_end(struct devlink_fmsg *fmsg) 3979{ 3980 return devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_NEST_END); 3981} 3982 3983int devlink_fmsg_obj_nest_end(struct devlink_fmsg *fmsg) 3984{ 3985 return devlink_fmsg_nest_end(fmsg); 3986} 3987EXPORT_SYMBOL_GPL(devlink_fmsg_obj_nest_end); 3988 3989#define DEVLINK_FMSG_MAX_SIZE (GENLMSG_DEFAULT_SIZE - GENL_HDRLEN - NLA_HDRLEN) 3990 3991static int devlink_fmsg_put_name(struct devlink_fmsg *fmsg, const char *name) 3992{ 3993 struct devlink_fmsg_item *item; 3994 3995 if (strlen(name) + 1 > DEVLINK_FMSG_MAX_SIZE) 3996 return -EMSGSIZE; 3997 3998 item = kzalloc(sizeof(*item) + strlen(name) + 1, GFP_KERNEL); 3999 if (!item) 4000 return -ENOMEM; 4001 4002 item->nla_type = NLA_NUL_STRING; 4003 item->len = strlen(name) + 1; 4004 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_NAME; 4005 memcpy(&item->value, name, item->len); 4006 list_add_tail(&item->list, &fmsg->item_list); 4007 4008 return 0; 4009} 4010 4011int devlink_fmsg_pair_nest_start(struct devlink_fmsg *fmsg, const char *name) 4012{ 4013 int err; 4014 4015 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_PAIR_NEST_START); 4016 if (err) 4017 return err; 4018 4019 err = devlink_fmsg_put_name(fmsg, name); 4020 if (err) 4021 return err; 4022 4023 return 0; 4024} 4025EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_start); 4026 4027int devlink_fmsg_pair_nest_end(struct devlink_fmsg *fmsg) 4028{ 4029 return devlink_fmsg_nest_end(fmsg); 4030} 4031EXPORT_SYMBOL_GPL(devlink_fmsg_pair_nest_end); 4032 4033int devlink_fmsg_arr_pair_nest_start(struct devlink_fmsg *fmsg, 4034 const char *name) 4035{ 4036 int err; 4037 4038 err = devlink_fmsg_pair_nest_start(fmsg, name); 4039 if (err) 4040 return err; 4041 4042 err = devlink_fmsg_nest_common(fmsg, DEVLINK_ATTR_FMSG_ARR_NEST_START); 4043 if (err) 4044 return err; 4045 4046 return 0; 4047} 4048EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_start); 4049 4050int devlink_fmsg_arr_pair_nest_end(struct devlink_fmsg *fmsg) 4051{ 4052 int err; 4053 4054 err = devlink_fmsg_nest_end(fmsg); 4055 if (err) 4056 return err; 4057 4058 err = devlink_fmsg_nest_end(fmsg); 4059 if (err) 4060 return err; 4061 4062 return 0; 4063} 4064EXPORT_SYMBOL_GPL(devlink_fmsg_arr_pair_nest_end); 4065 4066static int devlink_fmsg_put_value(struct devlink_fmsg *fmsg, 4067 const void *value, u16 value_len, 4068 u8 value_nla_type) 4069{ 4070 struct devlink_fmsg_item *item; 4071 4072 if (value_len > DEVLINK_FMSG_MAX_SIZE) 4073 return -EMSGSIZE; 4074 4075 item = kzalloc(sizeof(*item) + value_len, GFP_KERNEL); 4076 if (!item) 4077 return -ENOMEM; 4078 4079 item->nla_type = value_nla_type; 4080 item->len = value_len; 4081 item->attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA; 4082 memcpy(&item->value, value, item->len); 4083 list_add_tail(&item->list, &fmsg->item_list); 4084 4085 return 0; 4086} 4087 4088int devlink_fmsg_bool_put(struct devlink_fmsg *fmsg, bool value) 4089{ 4090 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_FLAG); 4091} 4092EXPORT_SYMBOL_GPL(devlink_fmsg_bool_put); 4093 4094int devlink_fmsg_u8_put(struct devlink_fmsg *fmsg, u8 value) 4095{ 4096 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U8); 4097} 4098EXPORT_SYMBOL_GPL(devlink_fmsg_u8_put); 4099 4100int devlink_fmsg_u32_put(struct devlink_fmsg *fmsg, u32 value) 4101{ 4102 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U32); 4103} 4104EXPORT_SYMBOL_GPL(devlink_fmsg_u32_put); 4105 4106int devlink_fmsg_u64_put(struct devlink_fmsg *fmsg, u64 value) 4107{ 4108 return devlink_fmsg_put_value(fmsg, &value, sizeof(value), NLA_U64); 4109} 4110EXPORT_SYMBOL_GPL(devlink_fmsg_u64_put); 4111 4112int devlink_fmsg_string_put(struct devlink_fmsg *fmsg, const char *value) 4113{ 4114 return devlink_fmsg_put_value(fmsg, value, strlen(value) + 1, 4115 NLA_NUL_STRING); 4116} 4117EXPORT_SYMBOL_GPL(devlink_fmsg_string_put); 4118 4119int devlink_fmsg_binary_put(struct devlink_fmsg *fmsg, const void *value, 4120 u16 value_len) 4121{ 4122 return devlink_fmsg_put_value(fmsg, value, value_len, NLA_BINARY); 4123} 4124EXPORT_SYMBOL_GPL(devlink_fmsg_binary_put); 4125 4126int devlink_fmsg_bool_pair_put(struct devlink_fmsg *fmsg, const char *name, 4127 bool value) 4128{ 4129 int err; 4130 4131 err = devlink_fmsg_pair_nest_start(fmsg, name); 4132 if (err) 4133 return err; 4134 4135 err = devlink_fmsg_bool_put(fmsg, value); 4136 if (err) 4137 return err; 4138 4139 err = devlink_fmsg_pair_nest_end(fmsg); 4140 if (err) 4141 return err; 4142 4143 return 0; 4144} 4145EXPORT_SYMBOL_GPL(devlink_fmsg_bool_pair_put); 4146 4147int devlink_fmsg_u8_pair_put(struct devlink_fmsg *fmsg, const char *name, 4148 u8 value) 4149{ 4150 int err; 4151 4152 err = devlink_fmsg_pair_nest_start(fmsg, name); 4153 if (err) 4154 return err; 4155 4156 err = devlink_fmsg_u8_put(fmsg, value); 4157 if (err) 4158 return err; 4159 4160 err = devlink_fmsg_pair_nest_end(fmsg); 4161 if (err) 4162 return err; 4163 4164 return 0; 4165} 4166EXPORT_SYMBOL_GPL(devlink_fmsg_u8_pair_put); 4167 4168int devlink_fmsg_u32_pair_put(struct devlink_fmsg *fmsg, const char *name, 4169 u32 value) 4170{ 4171 int err; 4172 4173 err = devlink_fmsg_pair_nest_start(fmsg, name); 4174 if (err) 4175 return err; 4176 4177 err = devlink_fmsg_u32_put(fmsg, value); 4178 if (err) 4179 return err; 4180 4181 err = devlink_fmsg_pair_nest_end(fmsg); 4182 if (err) 4183 return err; 4184 4185 return 0; 4186} 4187EXPORT_SYMBOL_GPL(devlink_fmsg_u32_pair_put); 4188 4189int devlink_fmsg_u64_pair_put(struct devlink_fmsg *fmsg, const char *name, 4190 u64 value) 4191{ 4192 int err; 4193 4194 err = devlink_fmsg_pair_nest_start(fmsg, name); 4195 if (err) 4196 return err; 4197 4198 err = devlink_fmsg_u64_put(fmsg, value); 4199 if (err) 4200 return err; 4201 4202 err = devlink_fmsg_pair_nest_end(fmsg); 4203 if (err) 4204 return err; 4205 4206 return 0; 4207} 4208EXPORT_SYMBOL_GPL(devlink_fmsg_u64_pair_put); 4209 4210int devlink_fmsg_string_pair_put(struct devlink_fmsg *fmsg, const char *name, 4211 const char *value) 4212{ 4213 int err; 4214 4215 err = devlink_fmsg_pair_nest_start(fmsg, name); 4216 if (err) 4217 return err; 4218 4219 err = devlink_fmsg_string_put(fmsg, value); 4220 if (err) 4221 return err; 4222 4223 err = devlink_fmsg_pair_nest_end(fmsg); 4224 if (err) 4225 return err; 4226 4227 return 0; 4228} 4229EXPORT_SYMBOL_GPL(devlink_fmsg_string_pair_put); 4230 4231int devlink_fmsg_binary_pair_put(struct devlink_fmsg *fmsg, const char *name, 4232 const void *value, u16 value_len) 4233{ 4234 int err; 4235 4236 err = devlink_fmsg_pair_nest_start(fmsg, name); 4237 if (err) 4238 return err; 4239 4240 err = devlink_fmsg_binary_put(fmsg, value, value_len); 4241 if (err) 4242 return err; 4243 4244 err = devlink_fmsg_pair_nest_end(fmsg); 4245 if (err) 4246 return err; 4247 4248 return 0; 4249} 4250EXPORT_SYMBOL_GPL(devlink_fmsg_binary_pair_put); 4251 4252static int 4253devlink_fmsg_item_fill_type(struct devlink_fmsg_item *msg, struct sk_buff *skb) 4254{ 4255 switch (msg->nla_type) { 4256 case NLA_FLAG: 4257 case NLA_U8: 4258 case NLA_U32: 4259 case NLA_U64: 4260 case NLA_NUL_STRING: 4261 case NLA_BINARY: 4262 return nla_put_u8(skb, DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE, 4263 msg->nla_type); 4264 default: 4265 return -EINVAL; 4266 } 4267} 4268 4269static int 4270devlink_fmsg_item_fill_data(struct devlink_fmsg_item *msg, struct sk_buff *skb) 4271{ 4272 int attrtype = DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA; 4273 u8 tmp; 4274 4275 switch (msg->nla_type) { 4276 case NLA_FLAG: 4277 /* Always provide flag data, regardless of its value */ 4278 tmp = *(bool *) msg->value; 4279 4280 return nla_put_u8(skb, attrtype, tmp); 4281 case NLA_U8: 4282 return nla_put_u8(skb, attrtype, *(u8 *) msg->value); 4283 case NLA_U32: 4284 return nla_put_u32(skb, attrtype, *(u32 *) msg->value); 4285 case NLA_U64: 4286 return nla_put_u64_64bit(skb, attrtype, *(u64 *) msg->value, 4287 DEVLINK_ATTR_PAD); 4288 case NLA_NUL_STRING: 4289 return nla_put_string(skb, attrtype, (char *) &msg->value); 4290 case NLA_BINARY: 4291 return nla_put(skb, attrtype, msg->len, (void *) &msg->value); 4292 default: 4293 return -EINVAL; 4294 } 4295} 4296 4297static int 4298devlink_fmsg_prepare_skb(struct devlink_fmsg *fmsg, struct sk_buff *skb, 4299 int *start) 4300{ 4301 struct devlink_fmsg_item *item; 4302 struct nlattr *fmsg_nlattr; 4303 int i = 0; 4304 int err; 4305 4306 fmsg_nlattr = nla_nest_start(skb, DEVLINK_ATTR_FMSG); 4307 if (!fmsg_nlattr) 4308 return -EMSGSIZE; 4309 4310 list_for_each_entry(item, &fmsg->item_list, list) { 4311 if (i < *start) { 4312 i++; 4313 continue; 4314 } 4315 4316 switch (item->attrtype) { 4317 case DEVLINK_ATTR_FMSG_OBJ_NEST_START: 4318 case DEVLINK_ATTR_FMSG_PAIR_NEST_START: 4319 case DEVLINK_ATTR_FMSG_ARR_NEST_START: 4320 case DEVLINK_ATTR_FMSG_NEST_END: 4321 err = nla_put_flag(skb, item->attrtype); 4322 break; 4323 case DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA: 4324 err = devlink_fmsg_item_fill_type(item, skb); 4325 if (err) 4326 break; 4327 err = devlink_fmsg_item_fill_data(item, skb); 4328 break; 4329 case DEVLINK_ATTR_FMSG_OBJ_NAME: 4330 err = nla_put_string(skb, item->attrtype, 4331 (char *) &item->value); 4332 break; 4333 default: 4334 err = -EINVAL; 4335 break; 4336 } 4337 if (!err) 4338 *start = ++i; 4339 else 4340 break; 4341 } 4342 4343 nla_nest_end(skb, fmsg_nlattr); 4344 return err; 4345} 4346 4347static int devlink_fmsg_snd(struct devlink_fmsg *fmsg, 4348 struct genl_info *info, 4349 enum devlink_command cmd, int flags) 4350{ 4351 struct nlmsghdr *nlh; 4352 struct sk_buff *skb; 4353 bool last = false; 4354 int index = 0; 4355 void *hdr; 4356 int err; 4357 4358 while (!last) { 4359 int tmp_index = index; 4360 4361 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 4362 if (!skb) 4363 return -ENOMEM; 4364 4365 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 4366 &devlink_nl_family, flags | NLM_F_MULTI, cmd); 4367 if (!hdr) { 4368 err = -EMSGSIZE; 4369 goto nla_put_failure; 4370 } 4371 4372 err = devlink_fmsg_prepare_skb(fmsg, skb, &index); 4373 if (!err) 4374 last = true; 4375 else if (err != -EMSGSIZE || tmp_index == index) 4376 goto nla_put_failure; 4377 4378 genlmsg_end(skb, hdr); 4379 err = genlmsg_reply(skb, info); 4380 if (err) 4381 return err; 4382 } 4383 4384 skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 4385 if (!skb) 4386 return -ENOMEM; 4387 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 4388 NLMSG_DONE, 0, flags | NLM_F_MULTI); 4389 if (!nlh) { 4390 err = -EMSGSIZE; 4391 goto nla_put_failure; 4392 } 4393 4394 return genlmsg_reply(skb, info); 4395 4396nla_put_failure: 4397 nlmsg_free(skb); 4398 return err; 4399} 4400 4401struct devlink_health_reporter { 4402 struct list_head list; 4403 void *priv; 4404 const struct devlink_health_reporter_ops *ops; 4405 struct devlink *devlink; 4406 struct devlink_fmsg *dump_fmsg; 4407 struct mutex dump_lock; /* lock parallel read/write from dump buffers */ 4408 u64 graceful_period; 4409 bool auto_recover; 4410 u8 health_state; 4411 u64 dump_ts; 4412 u64 error_count; 4413 u64 recovery_count; 4414 u64 last_recovery_ts; 4415}; 4416 4417void * 4418devlink_health_reporter_priv(struct devlink_health_reporter *reporter) 4419{ 4420 return reporter->priv; 4421} 4422EXPORT_SYMBOL_GPL(devlink_health_reporter_priv); 4423 4424static struct devlink_health_reporter * 4425devlink_health_reporter_find_by_name(struct devlink *devlink, 4426 const char *reporter_name) 4427{ 4428 struct devlink_health_reporter *reporter; 4429 4430 list_for_each_entry(reporter, &devlink->reporter_list, list) 4431 if (!strcmp(reporter->ops->name, reporter_name)) 4432 return reporter; 4433 return NULL; 4434} 4435 4436/** 4437 * devlink_health_reporter_create - create devlink health reporter 4438 * 4439 * @devlink: devlink 4440 * @ops: ops 4441 * @graceful_period: to avoid recovery loops, in msecs 4442 * @auto_recover: auto recover when error occurs 4443 * @priv: priv 4444 */ 4445struct devlink_health_reporter * 4446devlink_health_reporter_create(struct devlink *devlink, 4447 const struct devlink_health_reporter_ops *ops, 4448 u64 graceful_period, bool auto_recover, 4449 void *priv) 4450{ 4451 struct devlink_health_reporter *reporter; 4452 4453 mutex_lock(&devlink->lock); 4454 if (devlink_health_reporter_find_by_name(devlink, ops->name)) { 4455 reporter = ERR_PTR(-EEXIST); 4456 goto unlock; 4457 } 4458 4459 if (WARN_ON(auto_recover && !ops->recover) || 4460 WARN_ON(graceful_period && !ops->recover)) { 4461 reporter = ERR_PTR(-EINVAL); 4462 goto unlock; 4463 } 4464 4465 reporter = kzalloc(sizeof(*reporter), GFP_KERNEL); 4466 if (!reporter) { 4467 reporter = ERR_PTR(-ENOMEM); 4468 goto unlock; 4469 } 4470 4471 reporter->priv = priv; 4472 reporter->ops = ops; 4473 reporter->devlink = devlink; 4474 reporter->graceful_period = graceful_period; 4475 reporter->auto_recover = auto_recover; 4476 mutex_init(&reporter->dump_lock); 4477 list_add_tail(&reporter->list, &devlink->reporter_list); 4478unlock: 4479 mutex_unlock(&devlink->lock); 4480 return reporter; 4481} 4482EXPORT_SYMBOL_GPL(devlink_health_reporter_create); 4483 4484/** 4485 * devlink_health_reporter_destroy - destroy devlink health reporter 4486 * 4487 * @reporter: devlink health reporter to destroy 4488 */ 4489void 4490devlink_health_reporter_destroy(struct devlink_health_reporter *reporter) 4491{ 4492 mutex_lock(&reporter->devlink->lock); 4493 list_del(&reporter->list); 4494 mutex_unlock(&reporter->devlink->lock); 4495 if (reporter->dump_fmsg) 4496 devlink_fmsg_free(reporter->dump_fmsg); 4497 kfree(reporter); 4498} 4499EXPORT_SYMBOL_GPL(devlink_health_reporter_destroy); 4500 4501void 4502devlink_health_reporter_state_update(struct devlink_health_reporter *reporter, 4503 enum devlink_health_reporter_state state) 4504{ 4505 if (WARN_ON(state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY && 4506 state != DEVLINK_HEALTH_REPORTER_STATE_ERROR)) 4507 return; 4508 4509 if (reporter->health_state == state) 4510 return; 4511 4512 reporter->health_state = state; 4513 trace_devlink_health_reporter_state_update(reporter->devlink, 4514 reporter->ops->name, state); 4515} 4516EXPORT_SYMBOL_GPL(devlink_health_reporter_state_update); 4517 4518static int 4519devlink_health_reporter_recover(struct devlink_health_reporter *reporter, 4520 void *priv_ctx) 4521{ 4522 int err; 4523 4524 if (!reporter->ops->recover) 4525 return -EOPNOTSUPP; 4526 4527 err = reporter->ops->recover(reporter, priv_ctx); 4528 if (err) 4529 return err; 4530 4531 reporter->recovery_count++; 4532 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_HEALTHY; 4533 reporter->last_recovery_ts = jiffies; 4534 4535 return 0; 4536} 4537 4538static void 4539devlink_health_dump_clear(struct devlink_health_reporter *reporter) 4540{ 4541 if (!reporter->dump_fmsg) 4542 return; 4543 devlink_fmsg_free(reporter->dump_fmsg); 4544 reporter->dump_fmsg = NULL; 4545} 4546 4547static int devlink_health_do_dump(struct devlink_health_reporter *reporter, 4548 void *priv_ctx) 4549{ 4550 int err; 4551 4552 if (!reporter->ops->dump) 4553 return 0; 4554 4555 if (reporter->dump_fmsg) 4556 return 0; 4557 4558 reporter->dump_fmsg = devlink_fmsg_alloc(); 4559 if (!reporter->dump_fmsg) { 4560 err = -ENOMEM; 4561 return err; 4562 } 4563 4564 err = devlink_fmsg_obj_nest_start(reporter->dump_fmsg); 4565 if (err) 4566 goto dump_err; 4567 4568 err = reporter->ops->dump(reporter, reporter->dump_fmsg, 4569 priv_ctx); 4570 if (err) 4571 goto dump_err; 4572 4573 err = devlink_fmsg_obj_nest_end(reporter->dump_fmsg); 4574 if (err) 4575 goto dump_err; 4576 4577 reporter->dump_ts = jiffies; 4578 4579 return 0; 4580 4581dump_err: 4582 devlink_health_dump_clear(reporter); 4583 return err; 4584} 4585 4586int devlink_health_report(struct devlink_health_reporter *reporter, 4587 const char *msg, void *priv_ctx) 4588{ 4589 enum devlink_health_reporter_state prev_health_state; 4590 struct devlink *devlink = reporter->devlink; 4591 4592 /* write a log message of the current error */ 4593 WARN_ON(!msg); 4594 trace_devlink_health_report(devlink, reporter->ops->name, msg); 4595 reporter->error_count++; 4596 prev_health_state = reporter->health_state; 4597 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR; 4598 4599 /* abort if the previous error wasn't recovered */ 4600 if (reporter->auto_recover && 4601 (prev_health_state != DEVLINK_HEALTH_REPORTER_STATE_HEALTHY || 4602 jiffies - reporter->last_recovery_ts < 4603 msecs_to_jiffies(reporter->graceful_period))) { 4604 trace_devlink_health_recover_aborted(devlink, 4605 reporter->ops->name, 4606 reporter->health_state, 4607 jiffies - 4608 reporter->last_recovery_ts); 4609 return -ECANCELED; 4610 } 4611 4612 reporter->health_state = DEVLINK_HEALTH_REPORTER_STATE_ERROR; 4613 4614 mutex_lock(&reporter->dump_lock); 4615 /* store current dump of current error, for later analysis */ 4616 devlink_health_do_dump(reporter, priv_ctx); 4617 mutex_unlock(&reporter->dump_lock); 4618 4619 if (reporter->auto_recover) 4620 return devlink_health_reporter_recover(reporter, priv_ctx); 4621 4622 return 0; 4623} 4624EXPORT_SYMBOL_GPL(devlink_health_report); 4625 4626static struct devlink_health_reporter * 4627devlink_health_reporter_get_from_info(struct devlink *devlink, 4628 struct genl_info *info) 4629{ 4630 char *reporter_name; 4631 4632 if (!info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]) 4633 return NULL; 4634 4635 reporter_name = 4636 nla_data(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_NAME]); 4637 return devlink_health_reporter_find_by_name(devlink, reporter_name); 4638} 4639 4640static int 4641devlink_nl_health_reporter_fill(struct sk_buff *msg, 4642 struct devlink *devlink, 4643 struct devlink_health_reporter *reporter, 4644 enum devlink_command cmd, u32 portid, 4645 u32 seq, int flags) 4646{ 4647 struct nlattr *reporter_attr; 4648 void *hdr; 4649 4650 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 4651 if (!hdr) 4652 return -EMSGSIZE; 4653 4654 if (devlink_nl_put_handle(msg, devlink)) 4655 goto genlmsg_cancel; 4656 4657 reporter_attr = nla_nest_start(msg, DEVLINK_ATTR_HEALTH_REPORTER); 4658 if (!reporter_attr) 4659 goto genlmsg_cancel; 4660 if (nla_put_string(msg, DEVLINK_ATTR_HEALTH_REPORTER_NAME, 4661 reporter->ops->name)) 4662 goto reporter_nest_cancel; 4663 if (nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_STATE, 4664 reporter->health_state)) 4665 goto reporter_nest_cancel; 4666 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_ERR_COUNT, 4667 reporter->error_count, DEVLINK_ATTR_PAD)) 4668 goto reporter_nest_cancel; 4669 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_RECOVER_COUNT, 4670 reporter->recovery_count, DEVLINK_ATTR_PAD)) 4671 goto reporter_nest_cancel; 4672 if (reporter->ops->recover && 4673 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD, 4674 reporter->graceful_period, 4675 DEVLINK_ATTR_PAD)) 4676 goto reporter_nest_cancel; 4677 if (reporter->ops->recover && 4678 nla_put_u8(msg, DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER, 4679 reporter->auto_recover)) 4680 goto reporter_nest_cancel; 4681 if (reporter->dump_fmsg && 4682 nla_put_u64_64bit(msg, DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS, 4683 jiffies_to_msecs(reporter->dump_ts), 4684 DEVLINK_ATTR_PAD)) 4685 goto reporter_nest_cancel; 4686 4687 nla_nest_end(msg, reporter_attr); 4688 genlmsg_end(msg, hdr); 4689 return 0; 4690 4691reporter_nest_cancel: 4692 nla_nest_end(msg, reporter_attr); 4693genlmsg_cancel: 4694 genlmsg_cancel(msg, hdr); 4695 return -EMSGSIZE; 4696} 4697 4698static int devlink_nl_cmd_health_reporter_get_doit(struct sk_buff *skb, 4699 struct genl_info *info) 4700{ 4701 struct devlink *devlink = info->user_ptr[0]; 4702 struct devlink_health_reporter *reporter; 4703 struct sk_buff *msg; 4704 int err; 4705 4706 reporter = devlink_health_reporter_get_from_info(devlink, info); 4707 if (!reporter) 4708 return -EINVAL; 4709 4710 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 4711 if (!msg) 4712 return -ENOMEM; 4713 4714 err = devlink_nl_health_reporter_fill(msg, devlink, reporter, 4715 DEVLINK_CMD_HEALTH_REPORTER_GET, 4716 info->snd_portid, info->snd_seq, 4717 0); 4718 if (err) { 4719 nlmsg_free(msg); 4720 return err; 4721 } 4722 4723 return genlmsg_reply(msg, info); 4724} 4725 4726static int 4727devlink_nl_cmd_health_reporter_get_dumpit(struct sk_buff *msg, 4728 struct netlink_callback *cb) 4729{ 4730 struct devlink_health_reporter *reporter; 4731 struct devlink *devlink; 4732 int start = cb->args[0]; 4733 int idx = 0; 4734 int err; 4735 4736 mutex_lock(&devlink_mutex); 4737 list_for_each_entry(devlink, &devlink_list, list) { 4738 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 4739 continue; 4740 mutex_lock(&devlink->lock); 4741 list_for_each_entry(reporter, &devlink->reporter_list, 4742 list) { 4743 if (idx < start) { 4744 idx++; 4745 continue; 4746 } 4747 err = devlink_nl_health_reporter_fill(msg, devlink, 4748 reporter, 4749 DEVLINK_CMD_HEALTH_REPORTER_GET, 4750 NETLINK_CB(cb->skb).portid, 4751 cb->nlh->nlmsg_seq, 4752 NLM_F_MULTI); 4753 if (err) { 4754 mutex_unlock(&devlink->lock); 4755 goto out; 4756 } 4757 idx++; 4758 } 4759 mutex_unlock(&devlink->lock); 4760 } 4761out: 4762 mutex_unlock(&devlink_mutex); 4763 4764 cb->args[0] = idx; 4765 return msg->len; 4766} 4767 4768static int 4769devlink_nl_cmd_health_reporter_set_doit(struct sk_buff *skb, 4770 struct genl_info *info) 4771{ 4772 struct devlink *devlink = info->user_ptr[0]; 4773 struct devlink_health_reporter *reporter; 4774 4775 reporter = devlink_health_reporter_get_from_info(devlink, info); 4776 if (!reporter) 4777 return -EINVAL; 4778 4779 if (!reporter->ops->recover && 4780 (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] || 4781 info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER])) 4782 return -EOPNOTSUPP; 4783 4784 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]) 4785 reporter->graceful_period = 4786 nla_get_u64(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD]); 4787 4788 if (info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]) 4789 reporter->auto_recover = 4790 nla_get_u8(info->attrs[DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER]); 4791 4792 return 0; 4793} 4794 4795static int devlink_nl_cmd_health_reporter_recover_doit(struct sk_buff *skb, 4796 struct genl_info *info) 4797{ 4798 struct devlink *devlink = info->user_ptr[0]; 4799 struct devlink_health_reporter *reporter; 4800 4801 reporter = devlink_health_reporter_get_from_info(devlink, info); 4802 if (!reporter) 4803 return -EINVAL; 4804 4805 return devlink_health_reporter_recover(reporter, NULL); 4806} 4807 4808static int devlink_nl_cmd_health_reporter_diagnose_doit(struct sk_buff *skb, 4809 struct genl_info *info) 4810{ 4811 struct devlink *devlink = info->user_ptr[0]; 4812 struct devlink_health_reporter *reporter; 4813 struct devlink_fmsg *fmsg; 4814 int err; 4815 4816 reporter = devlink_health_reporter_get_from_info(devlink, info); 4817 if (!reporter) 4818 return -EINVAL; 4819 4820 if (!reporter->ops->diagnose) 4821 return -EOPNOTSUPP; 4822 4823 fmsg = devlink_fmsg_alloc(); 4824 if (!fmsg) 4825 return -ENOMEM; 4826 4827 err = devlink_fmsg_obj_nest_start(fmsg); 4828 if (err) 4829 goto out; 4830 4831 err = reporter->ops->diagnose(reporter, fmsg); 4832 if (err) 4833 goto out; 4834 4835 err = devlink_fmsg_obj_nest_end(fmsg); 4836 if (err) 4837 goto out; 4838 4839 err = devlink_fmsg_snd(fmsg, info, 4840 DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 0); 4841 4842out: 4843 devlink_fmsg_free(fmsg); 4844 return err; 4845} 4846 4847static int devlink_nl_cmd_health_reporter_dump_get_doit(struct sk_buff *skb, 4848 struct genl_info *info) 4849{ 4850 struct devlink *devlink = info->user_ptr[0]; 4851 struct devlink_health_reporter *reporter; 4852 int err; 4853 4854 reporter = devlink_health_reporter_get_from_info(devlink, info); 4855 if (!reporter) 4856 return -EINVAL; 4857 4858 if (!reporter->ops->dump) 4859 return -EOPNOTSUPP; 4860 4861 mutex_lock(&reporter->dump_lock); 4862 err = devlink_health_do_dump(reporter, NULL); 4863 if (err) 4864 goto out; 4865 4866 err = devlink_fmsg_snd(reporter->dump_fmsg, info, 4867 DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET, 0); 4868 4869out: 4870 mutex_unlock(&reporter->dump_lock); 4871 return err; 4872} 4873 4874static int 4875devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb, 4876 struct genl_info *info) 4877{ 4878 struct devlink *devlink = info->user_ptr[0]; 4879 struct devlink_health_reporter *reporter; 4880 4881 reporter = devlink_health_reporter_get_from_info(devlink, info); 4882 if (!reporter) 4883 return -EINVAL; 4884 4885 if (!reporter->ops->dump) 4886 return -EOPNOTSUPP; 4887 4888 mutex_lock(&reporter->dump_lock); 4889 devlink_health_dump_clear(reporter); 4890 mutex_unlock(&reporter->dump_lock); 4891 return 0; 4892} 4893 4894static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { 4895 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING }, 4896 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING }, 4897 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 }, 4898 [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 }, 4899 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 }, 4900 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 }, 4901 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 }, 4902 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 }, 4903 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 }, 4904 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 }, 4905 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 }, 4906 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 }, 4907 [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 }, 4908 [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 }, 4909 [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 }, 4910 [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING }, 4911 [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 }, 4912 [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64}, 4913 [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64}, 4914 [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING }, 4915 [DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 }, 4916 [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 }, 4917 [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING }, 4918 [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 }, 4919 [DEVLINK_ATTR_HEALTH_REPORTER_NAME] = { .type = NLA_NUL_STRING }, 4920 [DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD] = { .type = NLA_U64 }, 4921 [DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER] = { .type = NLA_U8 }, 4922 [DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME] = { .type = NLA_NUL_STRING }, 4923 [DEVLINK_ATTR_FLASH_UPDATE_COMPONENT] = { .type = NLA_NUL_STRING }, 4924}; 4925 4926static const struct genl_ops devlink_nl_ops[] = { 4927 { 4928 .cmd = DEVLINK_CMD_GET, 4929 .doit = devlink_nl_cmd_get_doit, 4930 .dumpit = devlink_nl_cmd_get_dumpit, 4931 .policy = devlink_nl_policy, 4932 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 4933 /* can be retrieved by unprivileged users */ 4934 }, 4935 { 4936 .cmd = DEVLINK_CMD_PORT_GET, 4937 .doit = devlink_nl_cmd_port_get_doit, 4938 .dumpit = devlink_nl_cmd_port_get_dumpit, 4939 .policy = devlink_nl_policy, 4940 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 4941 /* can be retrieved by unprivileged users */ 4942 }, 4943 { 4944 .cmd = DEVLINK_CMD_PORT_SET, 4945 .doit = devlink_nl_cmd_port_set_doit, 4946 .policy = devlink_nl_policy, 4947 .flags = GENL_ADMIN_PERM, 4948 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 4949 }, 4950 { 4951 .cmd = DEVLINK_CMD_PORT_SPLIT, 4952 .doit = devlink_nl_cmd_port_split_doit, 4953 .policy = devlink_nl_policy, 4954 .flags = GENL_ADMIN_PERM, 4955 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 4956 DEVLINK_NL_FLAG_NO_LOCK, 4957 }, 4958 { 4959 .cmd = DEVLINK_CMD_PORT_UNSPLIT, 4960 .doit = devlink_nl_cmd_port_unsplit_doit, 4961 .policy = devlink_nl_policy, 4962 .flags = GENL_ADMIN_PERM, 4963 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 4964 DEVLINK_NL_FLAG_NO_LOCK, 4965 }, 4966 { 4967 .cmd = DEVLINK_CMD_SB_GET, 4968 .doit = devlink_nl_cmd_sb_get_doit, 4969 .dumpit = devlink_nl_cmd_sb_get_dumpit, 4970 .policy = devlink_nl_policy, 4971 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 4972 DEVLINK_NL_FLAG_NEED_SB, 4973 /* can be retrieved by unprivileged users */ 4974 }, 4975 { 4976 .cmd = DEVLINK_CMD_SB_POOL_GET, 4977 .doit = devlink_nl_cmd_sb_pool_get_doit, 4978 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit, 4979 .policy = devlink_nl_policy, 4980 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 4981 DEVLINK_NL_FLAG_NEED_SB, 4982 /* can be retrieved by unprivileged users */ 4983 }, 4984 { 4985 .cmd = DEVLINK_CMD_SB_POOL_SET, 4986 .doit = devlink_nl_cmd_sb_pool_set_doit, 4987 .policy = devlink_nl_policy, 4988 .flags = GENL_ADMIN_PERM, 4989 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 4990 DEVLINK_NL_FLAG_NEED_SB, 4991 }, 4992 { 4993 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET, 4994 .doit = devlink_nl_cmd_sb_port_pool_get_doit, 4995 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit, 4996 .policy = devlink_nl_policy, 4997 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 4998 DEVLINK_NL_FLAG_NEED_SB, 4999 /* can be retrieved by unprivileged users */ 5000 }, 5001 { 5002 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET, 5003 .doit = devlink_nl_cmd_sb_port_pool_set_doit, 5004 .policy = devlink_nl_policy, 5005 .flags = GENL_ADMIN_PERM, 5006 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 5007 DEVLINK_NL_FLAG_NEED_SB, 5008 }, 5009 { 5010 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET, 5011 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit, 5012 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit, 5013 .policy = devlink_nl_policy, 5014 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 5015 DEVLINK_NL_FLAG_NEED_SB, 5016 /* can be retrieved by unprivileged users */ 5017 }, 5018 { 5019 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET, 5020 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit, 5021 .policy = devlink_nl_policy, 5022 .flags = GENL_ADMIN_PERM, 5023 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 5024 DEVLINK_NL_FLAG_NEED_SB, 5025 }, 5026 { 5027 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT, 5028 .doit = devlink_nl_cmd_sb_occ_snapshot_doit, 5029 .policy = devlink_nl_policy, 5030 .flags = GENL_ADMIN_PERM, 5031 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5032 DEVLINK_NL_FLAG_NEED_SB, 5033 }, 5034 { 5035 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR, 5036 .doit = devlink_nl_cmd_sb_occ_max_clear_doit, 5037 .policy = devlink_nl_policy, 5038 .flags = GENL_ADMIN_PERM, 5039 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5040 DEVLINK_NL_FLAG_NEED_SB, 5041 }, 5042 { 5043 .cmd = DEVLINK_CMD_ESWITCH_GET, 5044 .doit = devlink_nl_cmd_eswitch_get_doit, 5045 .policy = devlink_nl_policy, 5046 .flags = GENL_ADMIN_PERM, 5047 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5048 }, 5049 { 5050 .cmd = DEVLINK_CMD_ESWITCH_SET, 5051 .doit = devlink_nl_cmd_eswitch_set_doit, 5052 .policy = devlink_nl_policy, 5053 .flags = GENL_ADMIN_PERM, 5054 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5055 DEVLINK_NL_FLAG_NO_LOCK, 5056 }, 5057 { 5058 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET, 5059 .doit = devlink_nl_cmd_dpipe_table_get, 5060 .policy = devlink_nl_policy, 5061 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5062 /* can be retrieved by unprivileged users */ 5063 }, 5064 { 5065 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET, 5066 .doit = devlink_nl_cmd_dpipe_entries_get, 5067 .policy = devlink_nl_policy, 5068 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5069 /* can be retrieved by unprivileged users */ 5070 }, 5071 { 5072 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET, 5073 .doit = devlink_nl_cmd_dpipe_headers_get, 5074 .policy = devlink_nl_policy, 5075 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5076 /* can be retrieved by unprivileged users */ 5077 }, 5078 { 5079 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET, 5080 .doit = devlink_nl_cmd_dpipe_table_counters_set, 5081 .policy = devlink_nl_policy, 5082 .flags = GENL_ADMIN_PERM, 5083 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5084 }, 5085 { 5086 .cmd = DEVLINK_CMD_RESOURCE_SET, 5087 .doit = devlink_nl_cmd_resource_set, 5088 .policy = devlink_nl_policy, 5089 .flags = GENL_ADMIN_PERM, 5090 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5091 }, 5092 { 5093 .cmd = DEVLINK_CMD_RESOURCE_DUMP, 5094 .doit = devlink_nl_cmd_resource_dump, 5095 .policy = devlink_nl_policy, 5096 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5097 /* can be retrieved by unprivileged users */ 5098 }, 5099 { 5100 .cmd = DEVLINK_CMD_RELOAD, 5101 .doit = devlink_nl_cmd_reload, 5102 .policy = devlink_nl_policy, 5103 .flags = GENL_ADMIN_PERM, 5104 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5105 DEVLINK_NL_FLAG_NO_LOCK, 5106 }, 5107 { 5108 .cmd = DEVLINK_CMD_PARAM_GET, 5109 .doit = devlink_nl_cmd_param_get_doit, 5110 .dumpit = devlink_nl_cmd_param_get_dumpit, 5111 .policy = devlink_nl_policy, 5112 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5113 /* can be retrieved by unprivileged users */ 5114 }, 5115 { 5116 .cmd = DEVLINK_CMD_PARAM_SET, 5117 .doit = devlink_nl_cmd_param_set_doit, 5118 .policy = devlink_nl_policy, 5119 .flags = GENL_ADMIN_PERM, 5120 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5121 }, 5122 { 5123 .cmd = DEVLINK_CMD_PORT_PARAM_GET, 5124 .doit = devlink_nl_cmd_port_param_get_doit, 5125 .dumpit = devlink_nl_cmd_port_param_get_dumpit, 5126 .policy = devlink_nl_policy, 5127 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 5128 /* can be retrieved by unprivileged users */ 5129 }, 5130 { 5131 .cmd = DEVLINK_CMD_PORT_PARAM_SET, 5132 .doit = devlink_nl_cmd_port_param_set_doit, 5133 .policy = devlink_nl_policy, 5134 .flags = GENL_ADMIN_PERM, 5135 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 5136 }, 5137 { 5138 .cmd = DEVLINK_CMD_REGION_GET, 5139 .doit = devlink_nl_cmd_region_get_doit, 5140 .dumpit = devlink_nl_cmd_region_get_dumpit, 5141 .policy = devlink_nl_policy, 5142 .flags = GENL_ADMIN_PERM, 5143 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5144 }, 5145 { 5146 .cmd = DEVLINK_CMD_REGION_DEL, 5147 .doit = devlink_nl_cmd_region_del, 5148 .policy = devlink_nl_policy, 5149 .flags = GENL_ADMIN_PERM, 5150 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5151 }, 5152 { 5153 .cmd = DEVLINK_CMD_REGION_READ, 5154 .dumpit = devlink_nl_cmd_region_read_dumpit, 5155 .policy = devlink_nl_policy, 5156 .flags = GENL_ADMIN_PERM, 5157 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5158 }, 5159 { 5160 .cmd = DEVLINK_CMD_INFO_GET, 5161 .doit = devlink_nl_cmd_info_get_doit, 5162 .dumpit = devlink_nl_cmd_info_get_dumpit, 5163 .policy = devlink_nl_policy, 5164 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5165 /* can be retrieved by unprivileged users */ 5166 }, 5167 { 5168 .cmd = DEVLINK_CMD_HEALTH_REPORTER_GET, 5169 .doit = devlink_nl_cmd_health_reporter_get_doit, 5170 .dumpit = devlink_nl_cmd_health_reporter_get_dumpit, 5171 .policy = devlink_nl_policy, 5172 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5173 /* can be retrieved by unprivileged users */ 5174 }, 5175 { 5176 .cmd = DEVLINK_CMD_HEALTH_REPORTER_SET, 5177 .doit = devlink_nl_cmd_health_reporter_set_doit, 5178 .policy = devlink_nl_policy, 5179 .flags = GENL_ADMIN_PERM, 5180 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5181 }, 5182 { 5183 .cmd = DEVLINK_CMD_HEALTH_REPORTER_RECOVER, 5184 .doit = devlink_nl_cmd_health_reporter_recover_doit, 5185 .policy = devlink_nl_policy, 5186 .flags = GENL_ADMIN_PERM, 5187 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5188 }, 5189 { 5190 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, 5191 .doit = devlink_nl_cmd_health_reporter_diagnose_doit, 5192 .policy = devlink_nl_policy, 5193 .flags = GENL_ADMIN_PERM, 5194 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5195 }, 5196 { 5197 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET, 5198 .doit = devlink_nl_cmd_health_reporter_dump_get_doit, 5199 .policy = devlink_nl_policy, 5200 .flags = GENL_ADMIN_PERM, 5201 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5202 DEVLINK_NL_FLAG_NO_LOCK, 5203 }, 5204 { 5205 .cmd = DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR, 5206 .doit = devlink_nl_cmd_health_reporter_dump_clear_doit, 5207 .policy = devlink_nl_policy, 5208 .flags = GENL_ADMIN_PERM, 5209 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 5210 DEVLINK_NL_FLAG_NO_LOCK, 5211 }, 5212 { 5213 .cmd = DEVLINK_CMD_FLASH_UPDATE, 5214 .doit = devlink_nl_cmd_flash_update, 5215 .policy = devlink_nl_policy, 5216 .flags = GENL_ADMIN_PERM, 5217 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 5218 }, 5219}; 5220 5221static struct genl_family devlink_nl_family __ro_after_init = { 5222 .name = DEVLINK_GENL_NAME, 5223 .version = DEVLINK_GENL_VERSION, 5224 .maxattr = DEVLINK_ATTR_MAX, 5225 .netnsok = true, 5226 .pre_doit = devlink_nl_pre_doit, 5227 .post_doit = devlink_nl_post_doit, 5228 .module = THIS_MODULE, 5229 .ops = devlink_nl_ops, 5230 .n_ops = ARRAY_SIZE(devlink_nl_ops), 5231 .mcgrps = devlink_nl_mcgrps, 5232 .n_mcgrps = ARRAY_SIZE(devlink_nl_mcgrps), 5233}; 5234 5235/** 5236 * devlink_alloc - Allocate new devlink instance resources 5237 * 5238 * @ops: ops 5239 * @priv_size: size of user private data 5240 * 5241 * Allocate new devlink instance resources, including devlink index 5242 * and name. 5243 */ 5244struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size) 5245{ 5246 struct devlink *devlink; 5247 5248 if (WARN_ON(!ops)) 5249 return NULL; 5250 5251 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL); 5252 if (!devlink) 5253 return NULL; 5254 devlink->ops = ops; 5255 devlink_net_set(devlink, &init_net); 5256 INIT_LIST_HEAD(&devlink->port_list); 5257 INIT_LIST_HEAD(&devlink->sb_list); 5258 INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list); 5259 INIT_LIST_HEAD(&devlink->resource_list); 5260 INIT_LIST_HEAD(&devlink->param_list); 5261 INIT_LIST_HEAD(&devlink->region_list); 5262 INIT_LIST_HEAD(&devlink->reporter_list); 5263 mutex_init(&devlink->lock); 5264 return devlink; 5265} 5266EXPORT_SYMBOL_GPL(devlink_alloc); 5267 5268/** 5269 * devlink_register - Register devlink instance 5270 * 5271 * @devlink: devlink 5272 * @dev: parent device 5273 */ 5274int devlink_register(struct devlink *devlink, struct device *dev) 5275{ 5276 mutex_lock(&devlink_mutex); 5277 devlink->dev = dev; 5278 list_add_tail(&devlink->list, &devlink_list); 5279 devlink_notify(devlink, DEVLINK_CMD_NEW); 5280 mutex_unlock(&devlink_mutex); 5281 return 0; 5282} 5283EXPORT_SYMBOL_GPL(devlink_register); 5284 5285/** 5286 * devlink_unregister - Unregister devlink instance 5287 * 5288 * @devlink: devlink 5289 */ 5290void devlink_unregister(struct devlink *devlink) 5291{ 5292 mutex_lock(&devlink_mutex); 5293 devlink_notify(devlink, DEVLINK_CMD_DEL); 5294 list_del(&devlink->list); 5295 mutex_unlock(&devlink_mutex); 5296} 5297EXPORT_SYMBOL_GPL(devlink_unregister); 5298 5299/** 5300 * devlink_free - Free devlink instance resources 5301 * 5302 * @devlink: devlink 5303 */ 5304void devlink_free(struct devlink *devlink) 5305{ 5306 WARN_ON(!list_empty(&devlink->reporter_list)); 5307 WARN_ON(!list_empty(&devlink->region_list)); 5308 WARN_ON(!list_empty(&devlink->param_list)); 5309 WARN_ON(!list_empty(&devlink->resource_list)); 5310 WARN_ON(!list_empty(&devlink->dpipe_table_list)); 5311 WARN_ON(!list_empty(&devlink->sb_list)); 5312 WARN_ON(!list_empty(&devlink->port_list)); 5313 5314 kfree(devlink); 5315} 5316EXPORT_SYMBOL_GPL(devlink_free); 5317 5318/** 5319 * devlink_port_register - Register devlink port 5320 * 5321 * @devlink: devlink 5322 * @devlink_port: devlink port 5323 * @port_index: driver-specific numerical identifier of the port 5324 * 5325 * Register devlink port with provided port index. User can use 5326 * any indexing, even hw-related one. devlink_port structure 5327 * is convenient to be embedded inside user driver private structure. 5328 * Note that the caller should take care of zeroing the devlink_port 5329 * structure. 5330 */ 5331int devlink_port_register(struct devlink *devlink, 5332 struct devlink_port *devlink_port, 5333 unsigned int port_index) 5334{ 5335 mutex_lock(&devlink->lock); 5336 if (devlink_port_index_exists(devlink, port_index)) { 5337 mutex_unlock(&devlink->lock); 5338 return -EEXIST; 5339 } 5340 devlink_port->devlink = devlink; 5341 devlink_port->index = port_index; 5342 devlink_port->registered = true; 5343 list_add_tail(&devlink_port->list, &devlink->port_list); 5344 INIT_LIST_HEAD(&devlink_port->param_list); 5345 mutex_unlock(&devlink->lock); 5346 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 5347 return 0; 5348} 5349EXPORT_SYMBOL_GPL(devlink_port_register); 5350 5351/** 5352 * devlink_port_unregister - Unregister devlink port 5353 * 5354 * @devlink_port: devlink port 5355 */ 5356void devlink_port_unregister(struct devlink_port *devlink_port) 5357{ 5358 struct devlink *devlink = devlink_port->devlink; 5359 5360 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL); 5361 mutex_lock(&devlink->lock); 5362 list_del(&devlink_port->list); 5363 mutex_unlock(&devlink->lock); 5364} 5365EXPORT_SYMBOL_GPL(devlink_port_unregister); 5366 5367static void __devlink_port_type_set(struct devlink_port *devlink_port, 5368 enum devlink_port_type type, 5369 void *type_dev) 5370{ 5371 devlink_port->type = type; 5372 devlink_port->type_dev = type_dev; 5373 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 5374} 5375 5376/** 5377 * devlink_port_type_eth_set - Set port type to Ethernet 5378 * 5379 * @devlink_port: devlink port 5380 * @netdev: related netdevice 5381 */ 5382void devlink_port_type_eth_set(struct devlink_port *devlink_port, 5383 struct net_device *netdev) 5384{ 5385 return __devlink_port_type_set(devlink_port, 5386 DEVLINK_PORT_TYPE_ETH, netdev); 5387} 5388EXPORT_SYMBOL_GPL(devlink_port_type_eth_set); 5389 5390/** 5391 * devlink_port_type_ib_set - Set port type to InfiniBand 5392 * 5393 * @devlink_port: devlink port 5394 * @ibdev: related IB device 5395 */ 5396void devlink_port_type_ib_set(struct devlink_port *devlink_port, 5397 struct ib_device *ibdev) 5398{ 5399 return __devlink_port_type_set(devlink_port, 5400 DEVLINK_PORT_TYPE_IB, ibdev); 5401} 5402EXPORT_SYMBOL_GPL(devlink_port_type_ib_set); 5403 5404/** 5405 * devlink_port_type_clear - Clear port type 5406 * 5407 * @devlink_port: devlink port 5408 */ 5409void devlink_port_type_clear(struct devlink_port *devlink_port) 5410{ 5411 return __devlink_port_type_set(devlink_port, 5412 DEVLINK_PORT_TYPE_NOTSET, NULL); 5413} 5414EXPORT_SYMBOL_GPL(devlink_port_type_clear); 5415 5416/** 5417 * devlink_port_attrs_set - Set port attributes 5418 * 5419 * @devlink_port: devlink port 5420 * @flavour: flavour of the port 5421 * @port_number: number of the port that is facing user, for example 5422 * the front panel port number 5423 * @split: indicates if this is split port 5424 * @split_subport_number: if the port is split, this is the number 5425 * of subport. 5426 */ 5427void devlink_port_attrs_set(struct devlink_port *devlink_port, 5428 enum devlink_port_flavour flavour, 5429 u32 port_number, bool split, 5430 u32 split_subport_number) 5431{ 5432 struct devlink_port_attrs *attrs = &devlink_port->attrs; 5433 5434 attrs->set = true; 5435 attrs->flavour = flavour; 5436 attrs->port_number = port_number; 5437 attrs->split = split; 5438 attrs->split_subport_number = split_subport_number; 5439 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 5440} 5441EXPORT_SYMBOL_GPL(devlink_port_attrs_set); 5442 5443int devlink_port_get_phys_port_name(struct devlink_port *devlink_port, 5444 char *name, size_t len) 5445{ 5446 struct devlink_port_attrs *attrs = &devlink_port->attrs; 5447 int n = 0; 5448 5449 if (!attrs->set) 5450 return -EOPNOTSUPP; 5451 5452 switch (attrs->flavour) { 5453 case DEVLINK_PORT_FLAVOUR_PHYSICAL: 5454 if (!attrs->split) 5455 n = snprintf(name, len, "p%u", attrs->port_number); 5456 else 5457 n = snprintf(name, len, "p%us%u", attrs->port_number, 5458 attrs->split_subport_number); 5459 break; 5460 case DEVLINK_PORT_FLAVOUR_CPU: 5461 case DEVLINK_PORT_FLAVOUR_DSA: 5462 /* As CPU and DSA ports do not have a netdevice associated 5463 * case should not ever happen. 5464 */ 5465 WARN_ON(1); 5466 return -EINVAL; 5467 } 5468 5469 if (n >= len) 5470 return -EINVAL; 5471 5472 return 0; 5473} 5474EXPORT_SYMBOL_GPL(devlink_port_get_phys_port_name); 5475 5476int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, 5477 u32 size, u16 ingress_pools_count, 5478 u16 egress_pools_count, u16 ingress_tc_count, 5479 u16 egress_tc_count) 5480{ 5481 struct devlink_sb *devlink_sb; 5482 int err = 0; 5483 5484 mutex_lock(&devlink->lock); 5485 if (devlink_sb_index_exists(devlink, sb_index)) { 5486 err = -EEXIST; 5487 goto unlock; 5488 } 5489 5490 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL); 5491 if (!devlink_sb) { 5492 err = -ENOMEM; 5493 goto unlock; 5494 } 5495 devlink_sb->index = sb_index; 5496 devlink_sb->size = size; 5497 devlink_sb->ingress_pools_count = ingress_pools_count; 5498 devlink_sb->egress_pools_count = egress_pools_count; 5499 devlink_sb->ingress_tc_count = ingress_tc_count; 5500 devlink_sb->egress_tc_count = egress_tc_count; 5501 list_add_tail(&devlink_sb->list, &devlink->sb_list); 5502unlock: 5503 mutex_unlock(&devlink->lock); 5504 return err; 5505} 5506EXPORT_SYMBOL_GPL(devlink_sb_register); 5507 5508void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index) 5509{ 5510 struct devlink_sb *devlink_sb; 5511 5512 mutex_lock(&devlink->lock); 5513 devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 5514 WARN_ON(!devlink_sb); 5515 list_del(&devlink_sb->list); 5516 mutex_unlock(&devlink->lock); 5517 kfree(devlink_sb); 5518} 5519EXPORT_SYMBOL_GPL(devlink_sb_unregister); 5520 5521/** 5522 * devlink_dpipe_headers_register - register dpipe headers 5523 * 5524 * @devlink: devlink 5525 * @dpipe_headers: dpipe header array 5526 * 5527 * Register the headers supported by hardware. 5528 */ 5529int devlink_dpipe_headers_register(struct devlink *devlink, 5530 struct devlink_dpipe_headers *dpipe_headers) 5531{ 5532 mutex_lock(&devlink->lock); 5533 devlink->dpipe_headers = dpipe_headers; 5534 mutex_unlock(&devlink->lock); 5535 return 0; 5536} 5537EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register); 5538 5539/** 5540 * devlink_dpipe_headers_unregister - unregister dpipe headers 5541 * 5542 * @devlink: devlink 5543 * 5544 * Unregister the headers supported by hardware. 5545 */ 5546void devlink_dpipe_headers_unregister(struct devlink *devlink) 5547{ 5548 mutex_lock(&devlink->lock); 5549 devlink->dpipe_headers = NULL; 5550 mutex_unlock(&devlink->lock); 5551} 5552EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister); 5553 5554/** 5555 * devlink_dpipe_table_counter_enabled - check if counter allocation 5556 * required 5557 * @devlink: devlink 5558 * @table_name: tables name 5559 * 5560 * Used by driver to check if counter allocation is required. 5561 * After counter allocation is turned on the table entries 5562 * are updated to include counter statistics. 5563 * 5564 * After that point on the driver must respect the counter 5565 * state so that each entry added to the table is added 5566 * with a counter. 5567 */ 5568bool devlink_dpipe_table_counter_enabled(struct devlink *devlink, 5569 const char *table_name) 5570{ 5571 struct devlink_dpipe_table *table; 5572 bool enabled; 5573 5574 rcu_read_lock(); 5575 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 5576 table_name); 5577 enabled = false; 5578 if (table) 5579 enabled = table->counters_enabled; 5580 rcu_read_unlock(); 5581 return enabled; 5582} 5583EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled); 5584 5585/** 5586 * devlink_dpipe_table_register - register dpipe table 5587 * 5588 * @devlink: devlink 5589 * @table_name: table name 5590 * @table_ops: table ops 5591 * @priv: priv 5592 * @counter_control_extern: external control for counters 5593 */ 5594int devlink_dpipe_table_register(struct devlink *devlink, 5595 const char *table_name, 5596 struct devlink_dpipe_table_ops *table_ops, 5597 void *priv, bool counter_control_extern) 5598{ 5599 struct devlink_dpipe_table *table; 5600 5601 if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name)) 5602 return -EEXIST; 5603 5604 if (WARN_ON(!table_ops->size_get)) 5605 return -EINVAL; 5606 5607 table = kzalloc(sizeof(*table), GFP_KERNEL); 5608 if (!table) 5609 return -ENOMEM; 5610 5611 table->name = table_name; 5612 table->table_ops = table_ops; 5613 table->priv = priv; 5614 table->counter_control_extern = counter_control_extern; 5615 5616 mutex_lock(&devlink->lock); 5617 list_add_tail_rcu(&table->list, &devlink->dpipe_table_list); 5618 mutex_unlock(&devlink->lock); 5619 return 0; 5620} 5621EXPORT_SYMBOL_GPL(devlink_dpipe_table_register); 5622 5623/** 5624 * devlink_dpipe_table_unregister - unregister dpipe table 5625 * 5626 * @devlink: devlink 5627 * @table_name: table name 5628 */ 5629void devlink_dpipe_table_unregister(struct devlink *devlink, 5630 const char *table_name) 5631{ 5632 struct devlink_dpipe_table *table; 5633 5634 mutex_lock(&devlink->lock); 5635 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 5636 table_name); 5637 if (!table) 5638 goto unlock; 5639 list_del_rcu(&table->list); 5640 mutex_unlock(&devlink->lock); 5641 kfree_rcu(table, rcu); 5642 return; 5643unlock: 5644 mutex_unlock(&devlink->lock); 5645} 5646EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister); 5647 5648/** 5649 * devlink_resource_register - devlink resource register 5650 * 5651 * @devlink: devlink 5652 * @resource_name: resource's name 5653 * @resource_size: resource's size 5654 * @resource_id: resource's id 5655 * @parent_resource_id: resource's parent id 5656 * @size_params: size parameters 5657 */ 5658int devlink_resource_register(struct devlink *devlink, 5659 const char *resource_name, 5660 u64 resource_size, 5661 u64 resource_id, 5662 u64 parent_resource_id, 5663 const struct devlink_resource_size_params *size_params) 5664{ 5665 struct devlink_resource *resource; 5666 struct list_head *resource_list; 5667 bool top_hierarchy; 5668 int err = 0; 5669 5670 top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP; 5671 5672 mutex_lock(&devlink->lock); 5673 resource = devlink_resource_find(devlink, NULL, resource_id); 5674 if (resource) { 5675 err = -EINVAL; 5676 goto out; 5677 } 5678 5679 resource = kzalloc(sizeof(*resource), GFP_KERNEL); 5680 if (!resource) { 5681 err = -ENOMEM; 5682 goto out; 5683 } 5684 5685 if (top_hierarchy) { 5686 resource_list = &devlink->resource_list; 5687 } else { 5688 struct devlink_resource *parent_resource; 5689 5690 parent_resource = devlink_resource_find(devlink, NULL, 5691 parent_resource_id); 5692 if (parent_resource) { 5693 resource_list = &parent_resource->resource_list; 5694 resource->parent = parent_resource; 5695 } else { 5696 kfree(resource); 5697 err = -EINVAL; 5698 goto out; 5699 } 5700 } 5701 5702 resource->name = resource_name; 5703 resource->size = resource_size; 5704 resource->size_new = resource_size; 5705 resource->id = resource_id; 5706 resource->size_valid = true; 5707 memcpy(&resource->size_params, size_params, 5708 sizeof(resource->size_params)); 5709 INIT_LIST_HEAD(&resource->resource_list); 5710 list_add_tail(&resource->list, resource_list); 5711out: 5712 mutex_unlock(&devlink->lock); 5713 return err; 5714} 5715EXPORT_SYMBOL_GPL(devlink_resource_register); 5716 5717/** 5718 * devlink_resources_unregister - free all resources 5719 * 5720 * @devlink: devlink 5721 * @resource: resource 5722 */ 5723void devlink_resources_unregister(struct devlink *devlink, 5724 struct devlink_resource *resource) 5725{ 5726 struct devlink_resource *tmp, *child_resource; 5727 struct list_head *resource_list; 5728 5729 if (resource) 5730 resource_list = &resource->resource_list; 5731 else 5732 resource_list = &devlink->resource_list; 5733 5734 if (!resource) 5735 mutex_lock(&devlink->lock); 5736 5737 list_for_each_entry_safe(child_resource, tmp, resource_list, list) { 5738 devlink_resources_unregister(devlink, child_resource); 5739 list_del(&child_resource->list); 5740 kfree(child_resource); 5741 } 5742 5743 if (!resource) 5744 mutex_unlock(&devlink->lock); 5745} 5746EXPORT_SYMBOL_GPL(devlink_resources_unregister); 5747 5748/** 5749 * devlink_resource_size_get - get and update size 5750 * 5751 * @devlink: devlink 5752 * @resource_id: the requested resource id 5753 * @p_resource_size: ptr to update 5754 */ 5755int devlink_resource_size_get(struct devlink *devlink, 5756 u64 resource_id, 5757 u64 *p_resource_size) 5758{ 5759 struct devlink_resource *resource; 5760 int err = 0; 5761 5762 mutex_lock(&devlink->lock); 5763 resource = devlink_resource_find(devlink, NULL, resource_id); 5764 if (!resource) { 5765 err = -EINVAL; 5766 goto out; 5767 } 5768 *p_resource_size = resource->size_new; 5769 resource->size = resource->size_new; 5770out: 5771 mutex_unlock(&devlink->lock); 5772 return err; 5773} 5774EXPORT_SYMBOL_GPL(devlink_resource_size_get); 5775 5776/** 5777 * devlink_dpipe_table_resource_set - set the resource id 5778 * 5779 * @devlink: devlink 5780 * @table_name: table name 5781 * @resource_id: resource id 5782 * @resource_units: number of resource's units consumed per table's entry 5783 */ 5784int devlink_dpipe_table_resource_set(struct devlink *devlink, 5785 const char *table_name, u64 resource_id, 5786 u64 resource_units) 5787{ 5788 struct devlink_dpipe_table *table; 5789 int err = 0; 5790 5791 mutex_lock(&devlink->lock); 5792 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 5793 table_name); 5794 if (!table) { 5795 err = -EINVAL; 5796 goto out; 5797 } 5798 table->resource_id = resource_id; 5799 table->resource_units = resource_units; 5800 table->resource_valid = true; 5801out: 5802 mutex_unlock(&devlink->lock); 5803 return err; 5804} 5805EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set); 5806 5807/** 5808 * devlink_resource_occ_get_register - register occupancy getter 5809 * 5810 * @devlink: devlink 5811 * @resource_id: resource id 5812 * @occ_get: occupancy getter callback 5813 * @occ_get_priv: occupancy getter callback priv 5814 */ 5815void devlink_resource_occ_get_register(struct devlink *devlink, 5816 u64 resource_id, 5817 devlink_resource_occ_get_t *occ_get, 5818 void *occ_get_priv) 5819{ 5820 struct devlink_resource *resource; 5821 5822 mutex_lock(&devlink->lock); 5823 resource = devlink_resource_find(devlink, NULL, resource_id); 5824 if (WARN_ON(!resource)) 5825 goto out; 5826 WARN_ON(resource->occ_get); 5827 5828 resource->occ_get = occ_get; 5829 resource->occ_get_priv = occ_get_priv; 5830out: 5831 mutex_unlock(&devlink->lock); 5832} 5833EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register); 5834 5835/** 5836 * devlink_resource_occ_get_unregister - unregister occupancy getter 5837 * 5838 * @devlink: devlink 5839 * @resource_id: resource id 5840 */ 5841void devlink_resource_occ_get_unregister(struct devlink *devlink, 5842 u64 resource_id) 5843{ 5844 struct devlink_resource *resource; 5845 5846 mutex_lock(&devlink->lock); 5847 resource = devlink_resource_find(devlink, NULL, resource_id); 5848 if (WARN_ON(!resource)) 5849 goto out; 5850 WARN_ON(!resource->occ_get); 5851 5852 resource->occ_get = NULL; 5853 resource->occ_get_priv = NULL; 5854out: 5855 mutex_unlock(&devlink->lock); 5856} 5857EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister); 5858 5859static int devlink_param_verify(const struct devlink_param *param) 5860{ 5861 if (!param || !param->name || !param->supported_cmodes) 5862 return -EINVAL; 5863 if (param->generic) 5864 return devlink_param_generic_verify(param); 5865 else 5866 return devlink_param_driver_verify(param); 5867} 5868 5869static int __devlink_params_register(struct devlink *devlink, 5870 unsigned int port_index, 5871 struct list_head *param_list, 5872 const struct devlink_param *params, 5873 size_t params_count, 5874 enum devlink_command reg_cmd, 5875 enum devlink_command unreg_cmd) 5876{ 5877 const struct devlink_param *param = params; 5878 int i; 5879 int err; 5880 5881 mutex_lock(&devlink->lock); 5882 for (i = 0; i < params_count; i++, param++) { 5883 err = devlink_param_verify(param); 5884 if (err) 5885 goto rollback; 5886 5887 err = devlink_param_register_one(devlink, port_index, 5888 param_list, param, reg_cmd); 5889 if (err) 5890 goto rollback; 5891 } 5892 5893 mutex_unlock(&devlink->lock); 5894 return 0; 5895 5896rollback: 5897 if (!i) 5898 goto unlock; 5899 for (param--; i > 0; i--, param--) 5900 devlink_param_unregister_one(devlink, port_index, param_list, 5901 param, unreg_cmd); 5902unlock: 5903 mutex_unlock(&devlink->lock); 5904 return err; 5905} 5906 5907static void __devlink_params_unregister(struct devlink *devlink, 5908 unsigned int port_index, 5909 struct list_head *param_list, 5910 const struct devlink_param *params, 5911 size_t params_count, 5912 enum devlink_command cmd) 5913{ 5914 const struct devlink_param *param = params; 5915 int i; 5916 5917 mutex_lock(&devlink->lock); 5918 for (i = 0; i < params_count; i++, param++) 5919 devlink_param_unregister_one(devlink, 0, param_list, param, 5920 cmd); 5921 mutex_unlock(&devlink->lock); 5922} 5923 5924/** 5925 * devlink_params_register - register configuration parameters 5926 * 5927 * @devlink: devlink 5928 * @params: configuration parameters array 5929 * @params_count: number of parameters provided 5930 * 5931 * Register the configuration parameters supported by the driver. 5932 */ 5933int devlink_params_register(struct devlink *devlink, 5934 const struct devlink_param *params, 5935 size_t params_count) 5936{ 5937 return __devlink_params_register(devlink, 0, &devlink->param_list, 5938 params, params_count, 5939 DEVLINK_CMD_PARAM_NEW, 5940 DEVLINK_CMD_PARAM_DEL); 5941} 5942EXPORT_SYMBOL_GPL(devlink_params_register); 5943 5944/** 5945 * devlink_params_unregister - unregister configuration parameters 5946 * @devlink: devlink 5947 * @params: configuration parameters to unregister 5948 * @params_count: number of parameters provided 5949 */ 5950void devlink_params_unregister(struct devlink *devlink, 5951 const struct devlink_param *params, 5952 size_t params_count) 5953{ 5954 return __devlink_params_unregister(devlink, 0, &devlink->param_list, 5955 params, params_count, 5956 DEVLINK_CMD_PARAM_DEL); 5957} 5958EXPORT_SYMBOL_GPL(devlink_params_unregister); 5959 5960/** 5961 * devlink_params_publish - publish configuration parameters 5962 * 5963 * @devlink: devlink 5964 * 5965 * Publish previously registered configuration parameters. 5966 */ 5967void devlink_params_publish(struct devlink *devlink) 5968{ 5969 struct devlink_param_item *param_item; 5970 5971 list_for_each_entry(param_item, &devlink->param_list, list) { 5972 if (param_item->published) 5973 continue; 5974 param_item->published = true; 5975 devlink_param_notify(devlink, 0, param_item, 5976 DEVLINK_CMD_PARAM_NEW); 5977 } 5978} 5979EXPORT_SYMBOL_GPL(devlink_params_publish); 5980 5981/** 5982 * devlink_params_unpublish - unpublish configuration parameters 5983 * 5984 * @devlink: devlink 5985 * 5986 * Unpublish previously registered configuration parameters. 5987 */ 5988void devlink_params_unpublish(struct devlink *devlink) 5989{ 5990 struct devlink_param_item *param_item; 5991 5992 list_for_each_entry(param_item, &devlink->param_list, list) { 5993 if (!param_item->published) 5994 continue; 5995 param_item->published = false; 5996 devlink_param_notify(devlink, 0, param_item, 5997 DEVLINK_CMD_PARAM_DEL); 5998 } 5999} 6000EXPORT_SYMBOL_GPL(devlink_params_unpublish); 6001 6002/** 6003 * devlink_port_params_register - register port configuration parameters 6004 * 6005 * @devlink_port: devlink port 6006 * @params: configuration parameters array 6007 * @params_count: number of parameters provided 6008 * 6009 * Register the configuration parameters supported by the port. 6010 */ 6011int devlink_port_params_register(struct devlink_port *devlink_port, 6012 const struct devlink_param *params, 6013 size_t params_count) 6014{ 6015 return __devlink_params_register(devlink_port->devlink, 6016 devlink_port->index, 6017 &devlink_port->param_list, params, 6018 params_count, 6019 DEVLINK_CMD_PORT_PARAM_NEW, 6020 DEVLINK_CMD_PORT_PARAM_DEL); 6021} 6022EXPORT_SYMBOL_GPL(devlink_port_params_register); 6023 6024/** 6025 * devlink_port_params_unregister - unregister port configuration 6026 * parameters 6027 * 6028 * @devlink_port: devlink port 6029 * @params: configuration parameters array 6030 * @params_count: number of parameters provided 6031 */ 6032void devlink_port_params_unregister(struct devlink_port *devlink_port, 6033 const struct devlink_param *params, 6034 size_t params_count) 6035{ 6036 return __devlink_params_unregister(devlink_port->devlink, 6037 devlink_port->index, 6038 &devlink_port->param_list, 6039 params, params_count, 6040 DEVLINK_CMD_PORT_PARAM_DEL); 6041} 6042EXPORT_SYMBOL_GPL(devlink_port_params_unregister); 6043 6044static int 6045__devlink_param_driverinit_value_get(struct list_head *param_list, u32 param_id, 6046 union devlink_param_value *init_val) 6047{ 6048 struct devlink_param_item *param_item; 6049 6050 param_item = devlink_param_find_by_id(param_list, param_id); 6051 if (!param_item) 6052 return -EINVAL; 6053 6054 if (!param_item->driverinit_value_valid || 6055 !devlink_param_cmode_is_supported(param_item->param, 6056 DEVLINK_PARAM_CMODE_DRIVERINIT)) 6057 return -EOPNOTSUPP; 6058 6059 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING) 6060 strcpy(init_val->vstr, param_item->driverinit_value.vstr); 6061 else 6062 *init_val = param_item->driverinit_value; 6063 6064 return 0; 6065} 6066 6067static int 6068__devlink_param_driverinit_value_set(struct devlink *devlink, 6069 unsigned int port_index, 6070 struct list_head *param_list, u32 param_id, 6071 union devlink_param_value init_val, 6072 enum devlink_command cmd) 6073{ 6074 struct devlink_param_item *param_item; 6075 6076 param_item = devlink_param_find_by_id(param_list, param_id); 6077 if (!param_item) 6078 return -EINVAL; 6079 6080 if (!devlink_param_cmode_is_supported(param_item->param, 6081 DEVLINK_PARAM_CMODE_DRIVERINIT)) 6082 return -EOPNOTSUPP; 6083 6084 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING) 6085 strcpy(param_item->driverinit_value.vstr, init_val.vstr); 6086 else 6087 param_item->driverinit_value = init_val; 6088 param_item->driverinit_value_valid = true; 6089 6090 devlink_param_notify(devlink, port_index, param_item, cmd); 6091 return 0; 6092} 6093 6094/** 6095 * devlink_param_driverinit_value_get - get configuration parameter 6096 * value for driver initializing 6097 * 6098 * @devlink: devlink 6099 * @param_id: parameter ID 6100 * @init_val: value of parameter in driverinit configuration mode 6101 * 6102 * This function should be used by the driver to get driverinit 6103 * configuration for initialization after reload command. 6104 */ 6105int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id, 6106 union devlink_param_value *init_val) 6107{ 6108 if (!devlink->ops->reload) 6109 return -EOPNOTSUPP; 6110 6111 return __devlink_param_driverinit_value_get(&devlink->param_list, 6112 param_id, init_val); 6113} 6114EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_get); 6115 6116/** 6117 * devlink_param_driverinit_value_set - set value of configuration 6118 * parameter for driverinit 6119 * configuration mode 6120 * 6121 * @devlink: devlink 6122 * @param_id: parameter ID 6123 * @init_val: value of parameter to set for driverinit configuration mode 6124 * 6125 * This function should be used by the driver to set driverinit 6126 * configuration mode default value. 6127 */ 6128int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id, 6129 union devlink_param_value init_val) 6130{ 6131 return __devlink_param_driverinit_value_set(devlink, 0, 6132 &devlink->param_list, 6133 param_id, init_val, 6134 DEVLINK_CMD_PARAM_NEW); 6135} 6136EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_set); 6137 6138/** 6139 * devlink_port_param_driverinit_value_get - get configuration parameter 6140 * value for driver initializing 6141 * 6142 * @devlink_port: devlink_port 6143 * @param_id: parameter ID 6144 * @init_val: value of parameter in driverinit configuration mode 6145 * 6146 * This function should be used by the driver to get driverinit 6147 * configuration for initialization after reload command. 6148 */ 6149int devlink_port_param_driverinit_value_get(struct devlink_port *devlink_port, 6150 u32 param_id, 6151 union devlink_param_value *init_val) 6152{ 6153 struct devlink *devlink = devlink_port->devlink; 6154 6155 if (!devlink->ops->reload) 6156 return -EOPNOTSUPP; 6157 6158 return __devlink_param_driverinit_value_get(&devlink_port->param_list, 6159 param_id, init_val); 6160} 6161EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_get); 6162 6163/** 6164 * devlink_port_param_driverinit_value_set - set value of configuration 6165 * parameter for driverinit 6166 * configuration mode 6167 * 6168 * @devlink_port: devlink_port 6169 * @param_id: parameter ID 6170 * @init_val: value of parameter to set for driverinit configuration mode 6171 * 6172 * This function should be used by the driver to set driverinit 6173 * configuration mode default value. 6174 */ 6175int devlink_port_param_driverinit_value_set(struct devlink_port *devlink_port, 6176 u32 param_id, 6177 union devlink_param_value init_val) 6178{ 6179 return __devlink_param_driverinit_value_set(devlink_port->devlink, 6180 devlink_port->index, 6181 &devlink_port->param_list, 6182 param_id, init_val, 6183 DEVLINK_CMD_PORT_PARAM_NEW); 6184} 6185EXPORT_SYMBOL_GPL(devlink_port_param_driverinit_value_set); 6186 6187/** 6188 * devlink_param_value_changed - notify devlink on a parameter's value 6189 * change. Should be called by the driver 6190 * right after the change. 6191 * 6192 * @devlink: devlink 6193 * @param_id: parameter ID 6194 * 6195 * This function should be used by the driver to notify devlink on value 6196 * change, excluding driverinit configuration mode. 6197 * For driverinit configuration mode driver should use the function 6198 */ 6199void devlink_param_value_changed(struct devlink *devlink, u32 param_id) 6200{ 6201 struct devlink_param_item *param_item; 6202 6203 param_item = devlink_param_find_by_id(&devlink->param_list, param_id); 6204 WARN_ON(!param_item); 6205 6206 devlink_param_notify(devlink, 0, param_item, DEVLINK_CMD_PARAM_NEW); 6207} 6208EXPORT_SYMBOL_GPL(devlink_param_value_changed); 6209 6210/** 6211 * devlink_port_param_value_changed - notify devlink on a parameter's value 6212 * change. Should be called by the driver 6213 * right after the change. 6214 * 6215 * @devlink_port: devlink_port 6216 * @param_id: parameter ID 6217 * 6218 * This function should be used by the driver to notify devlink on value 6219 * change, excluding driverinit configuration mode. 6220 * For driverinit configuration mode driver should use the function 6221 * devlink_port_param_driverinit_value_set() instead. 6222 */ 6223void devlink_port_param_value_changed(struct devlink_port *devlink_port, 6224 u32 param_id) 6225{ 6226 struct devlink_param_item *param_item; 6227 6228 param_item = devlink_param_find_by_id(&devlink_port->param_list, 6229 param_id); 6230 WARN_ON(!param_item); 6231 6232 devlink_param_notify(devlink_port->devlink, devlink_port->index, 6233 param_item, DEVLINK_CMD_PORT_PARAM_NEW); 6234} 6235EXPORT_SYMBOL_GPL(devlink_port_param_value_changed); 6236 6237/** 6238 * devlink_param_value_str_fill - Safely fill-up the string preventing 6239 * from overflow of the preallocated buffer 6240 * 6241 * @dst_val: destination devlink_param_value 6242 * @src: source buffer 6243 */ 6244void devlink_param_value_str_fill(union devlink_param_value *dst_val, 6245 const char *src) 6246{ 6247 size_t len; 6248 6249 len = strlcpy(dst_val->vstr, src, __DEVLINK_PARAM_MAX_STRING_VALUE); 6250 WARN_ON(len >= __DEVLINK_PARAM_MAX_STRING_VALUE); 6251} 6252EXPORT_SYMBOL_GPL(devlink_param_value_str_fill); 6253 6254/** 6255 * devlink_region_create - create a new address region 6256 * 6257 * @devlink: devlink 6258 * @region_name: region name 6259 * @region_max_snapshots: Maximum supported number of snapshots for region 6260 * @region_size: size of region 6261 */ 6262struct devlink_region *devlink_region_create(struct devlink *devlink, 6263 const char *region_name, 6264 u32 region_max_snapshots, 6265 u64 region_size) 6266{ 6267 struct devlink_region *region; 6268 int err = 0; 6269 6270 mutex_lock(&devlink->lock); 6271 6272 if (devlink_region_get_by_name(devlink, region_name)) { 6273 err = -EEXIST; 6274 goto unlock; 6275 } 6276 6277 region = kzalloc(sizeof(*region), GFP_KERNEL); 6278 if (!region) { 6279 err = -ENOMEM; 6280 goto unlock; 6281 } 6282 6283 region->devlink = devlink; 6284 region->max_snapshots = region_max_snapshots; 6285 region->name = region_name; 6286 region->size = region_size; 6287 INIT_LIST_HEAD(&region->snapshot_list); 6288 list_add_tail(&region->list, &devlink->region_list); 6289 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW); 6290 6291 mutex_unlock(&devlink->lock); 6292 return region; 6293 6294unlock: 6295 mutex_unlock(&devlink->lock); 6296 return ERR_PTR(err); 6297} 6298EXPORT_SYMBOL_GPL(devlink_region_create); 6299 6300/** 6301 * devlink_region_destroy - destroy address region 6302 * 6303 * @region: devlink region to destroy 6304 */ 6305void devlink_region_destroy(struct devlink_region *region) 6306{ 6307 struct devlink *devlink = region->devlink; 6308 struct devlink_snapshot *snapshot, *ts; 6309 6310 mutex_lock(&devlink->lock); 6311 6312 /* Free all snapshots of region */ 6313 list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list) 6314 devlink_region_snapshot_del(snapshot); 6315 6316 list_del(&region->list); 6317 6318 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL); 6319 mutex_unlock(&devlink->lock); 6320 kfree(region); 6321} 6322EXPORT_SYMBOL_GPL(devlink_region_destroy); 6323 6324/** 6325 * devlink_region_shapshot_id_get - get snapshot ID 6326 * 6327 * This callback should be called when adding a new snapshot, 6328 * Driver should use the same id for multiple snapshots taken 6329 * on multiple regions at the same time/by the same trigger. 6330 * 6331 * @devlink: devlink 6332 */ 6333u32 devlink_region_shapshot_id_get(struct devlink *devlink) 6334{ 6335 u32 id; 6336 6337 mutex_lock(&devlink->lock); 6338 id = ++devlink->snapshot_id; 6339 mutex_unlock(&devlink->lock); 6340 6341 return id; 6342} 6343EXPORT_SYMBOL_GPL(devlink_region_shapshot_id_get); 6344 6345/** 6346 * devlink_region_snapshot_create - create a new snapshot 6347 * This will add a new snapshot of a region. The snapshot 6348 * will be stored on the region struct and can be accessed 6349 * from devlink. This is useful for future analyses of snapshots. 6350 * Multiple snapshots can be created on a region. 6351 * The @snapshot_id should be obtained using the getter function. 6352 * 6353 * @region: devlink region of the snapshot 6354 * @data_len: size of snapshot data 6355 * @data: snapshot data 6356 * @snapshot_id: snapshot id to be created 6357 * @data_destructor: pointer to destructor function to free data 6358 */ 6359int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len, 6360 u8 *data, u32 snapshot_id, 6361 devlink_snapshot_data_dest_t *data_destructor) 6362{ 6363 struct devlink *devlink = region->devlink; 6364 struct devlink_snapshot *snapshot; 6365 int err; 6366 6367 mutex_lock(&devlink->lock); 6368 6369 /* check if region can hold one more snapshot */ 6370 if (region->cur_snapshots == region->max_snapshots) { 6371 err = -ENOMEM; 6372 goto unlock; 6373 } 6374 6375 if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { 6376 err = -EEXIST; 6377 goto unlock; 6378 } 6379 6380 snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL); 6381 if (!snapshot) { 6382 err = -ENOMEM; 6383 goto unlock; 6384 } 6385 6386 snapshot->id = snapshot_id; 6387 snapshot->region = region; 6388 snapshot->data = data; 6389 snapshot->data_len = data_len; 6390 snapshot->data_destructor = data_destructor; 6391 6392 list_add_tail(&snapshot->list, &region->snapshot_list); 6393 6394 region->cur_snapshots++; 6395 6396 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW); 6397 mutex_unlock(&devlink->lock); 6398 return 0; 6399 6400unlock: 6401 mutex_unlock(&devlink->lock); 6402 return err; 6403} 6404EXPORT_SYMBOL_GPL(devlink_region_snapshot_create); 6405 6406static void __devlink_compat_running_version(struct devlink *devlink, 6407 char *buf, size_t len) 6408{ 6409 const struct nlattr *nlattr; 6410 struct devlink_info_req req; 6411 struct sk_buff *msg; 6412 int rem, err; 6413 6414 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 6415 if (!msg) 6416 return; 6417 6418 req.msg = msg; 6419 err = devlink->ops->info_get(devlink, &req, NULL); 6420 if (err) 6421 goto free_msg; 6422 6423 nla_for_each_attr(nlattr, (void *)msg->data, msg->len, rem) { 6424 const struct nlattr *kv; 6425 int rem_kv; 6426 6427 if (nla_type(nlattr) != DEVLINK_ATTR_INFO_VERSION_RUNNING) 6428 continue; 6429 6430 nla_for_each_nested(kv, nlattr, rem_kv) { 6431 if (nla_type(kv) != DEVLINK_ATTR_INFO_VERSION_VALUE) 6432 continue; 6433 6434 strlcat(buf, nla_data(kv), len); 6435 strlcat(buf, " ", len); 6436 } 6437 } 6438free_msg: 6439 nlmsg_free(msg); 6440} 6441 6442void devlink_compat_running_version(struct net_device *dev, 6443 char *buf, size_t len) 6444{ 6445 struct devlink *devlink; 6446 6447 dev_hold(dev); 6448 rtnl_unlock(); 6449 6450 mutex_lock(&devlink_mutex); 6451 devlink = netdev_to_devlink(dev); 6452 if (!devlink || !devlink->ops->info_get) 6453 goto unlock_list; 6454 6455 mutex_lock(&devlink->lock); 6456 __devlink_compat_running_version(devlink, buf, len); 6457 mutex_unlock(&devlink->lock); 6458unlock_list: 6459 mutex_unlock(&devlink_mutex); 6460 6461 rtnl_lock(); 6462 dev_put(dev); 6463} 6464 6465int devlink_compat_flash_update(struct net_device *dev, const char *file_name) 6466{ 6467 struct devlink *devlink; 6468 int ret = -EOPNOTSUPP; 6469 6470 dev_hold(dev); 6471 rtnl_unlock(); 6472 6473 mutex_lock(&devlink_mutex); 6474 devlink = netdev_to_devlink(dev); 6475 if (!devlink || !devlink->ops->flash_update) 6476 goto unlock_list; 6477 6478 mutex_lock(&devlink->lock); 6479 ret = devlink->ops->flash_update(devlink, file_name, NULL, NULL); 6480 mutex_unlock(&devlink->lock); 6481unlock_list: 6482 mutex_unlock(&devlink_mutex); 6483 6484 rtnl_lock(); 6485 dev_put(dev); 6486 6487 return ret; 6488} 6489 6490static int __init devlink_init(void) 6491{ 6492 return genl_register_family(&devlink_nl_family); 6493} 6494 6495subsys_initcall(devlink_init);