at v4.19-rc6 4774 lines 124 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); 84 85static LIST_HEAD(devlink_list); 86 87/* devlink_mutex 88 * 89 * An overall lock guarding every operation coming from userspace. 90 * It also guards devlink devices list and it is taken when 91 * driver registers/unregisters it. 92 */ 93static DEFINE_MUTEX(devlink_mutex); 94 95static struct net *devlink_net(const struct devlink *devlink) 96{ 97 return read_pnet(&devlink->_net); 98} 99 100static void devlink_net_set(struct devlink *devlink, struct net *net) 101{ 102 write_pnet(&devlink->_net, net); 103} 104 105static struct devlink *devlink_get_from_attrs(struct net *net, 106 struct nlattr **attrs) 107{ 108 struct devlink *devlink; 109 char *busname; 110 char *devname; 111 112 if (!attrs[DEVLINK_ATTR_BUS_NAME] || !attrs[DEVLINK_ATTR_DEV_NAME]) 113 return ERR_PTR(-EINVAL); 114 115 busname = nla_data(attrs[DEVLINK_ATTR_BUS_NAME]); 116 devname = nla_data(attrs[DEVLINK_ATTR_DEV_NAME]); 117 118 list_for_each_entry(devlink, &devlink_list, list) { 119 if (strcmp(devlink->dev->bus->name, busname) == 0 && 120 strcmp(dev_name(devlink->dev), devname) == 0 && 121 net_eq(devlink_net(devlink), net)) 122 return devlink; 123 } 124 125 return ERR_PTR(-ENODEV); 126} 127 128static struct devlink *devlink_get_from_info(struct genl_info *info) 129{ 130 return devlink_get_from_attrs(genl_info_net(info), info->attrs); 131} 132 133static struct devlink_port *devlink_port_get_by_index(struct devlink *devlink, 134 int port_index) 135{ 136 struct devlink_port *devlink_port; 137 138 list_for_each_entry(devlink_port, &devlink->port_list, list) { 139 if (devlink_port->index == port_index) 140 return devlink_port; 141 } 142 return NULL; 143} 144 145static bool devlink_port_index_exists(struct devlink *devlink, int port_index) 146{ 147 return devlink_port_get_by_index(devlink, port_index); 148} 149 150static struct devlink_port *devlink_port_get_from_attrs(struct devlink *devlink, 151 struct nlattr **attrs) 152{ 153 if (attrs[DEVLINK_ATTR_PORT_INDEX]) { 154 u32 port_index = nla_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]); 155 struct devlink_port *devlink_port; 156 157 devlink_port = devlink_port_get_by_index(devlink, port_index); 158 if (!devlink_port) 159 return ERR_PTR(-ENODEV); 160 return devlink_port; 161 } 162 return ERR_PTR(-EINVAL); 163} 164 165static struct devlink_port *devlink_port_get_from_info(struct devlink *devlink, 166 struct genl_info *info) 167{ 168 return devlink_port_get_from_attrs(devlink, info->attrs); 169} 170 171struct devlink_sb { 172 struct list_head list; 173 unsigned int index; 174 u32 size; 175 u16 ingress_pools_count; 176 u16 egress_pools_count; 177 u16 ingress_tc_count; 178 u16 egress_tc_count; 179}; 180 181static u16 devlink_sb_pool_count(struct devlink_sb *devlink_sb) 182{ 183 return devlink_sb->ingress_pools_count + devlink_sb->egress_pools_count; 184} 185 186static struct devlink_sb *devlink_sb_get_by_index(struct devlink *devlink, 187 unsigned int sb_index) 188{ 189 struct devlink_sb *devlink_sb; 190 191 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 192 if (devlink_sb->index == sb_index) 193 return devlink_sb; 194 } 195 return NULL; 196} 197 198static bool devlink_sb_index_exists(struct devlink *devlink, 199 unsigned int sb_index) 200{ 201 return devlink_sb_get_by_index(devlink, sb_index); 202} 203 204static struct devlink_sb *devlink_sb_get_from_attrs(struct devlink *devlink, 205 struct nlattr **attrs) 206{ 207 if (attrs[DEVLINK_ATTR_SB_INDEX]) { 208 u32 sb_index = nla_get_u32(attrs[DEVLINK_ATTR_SB_INDEX]); 209 struct devlink_sb *devlink_sb; 210 211 devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 212 if (!devlink_sb) 213 return ERR_PTR(-ENODEV); 214 return devlink_sb; 215 } 216 return ERR_PTR(-EINVAL); 217} 218 219static struct devlink_sb *devlink_sb_get_from_info(struct devlink *devlink, 220 struct genl_info *info) 221{ 222 return devlink_sb_get_from_attrs(devlink, info->attrs); 223} 224 225static int devlink_sb_pool_index_get_from_attrs(struct devlink_sb *devlink_sb, 226 struct nlattr **attrs, 227 u16 *p_pool_index) 228{ 229 u16 val; 230 231 if (!attrs[DEVLINK_ATTR_SB_POOL_INDEX]) 232 return -EINVAL; 233 234 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_POOL_INDEX]); 235 if (val >= devlink_sb_pool_count(devlink_sb)) 236 return -EINVAL; 237 *p_pool_index = val; 238 return 0; 239} 240 241static int devlink_sb_pool_index_get_from_info(struct devlink_sb *devlink_sb, 242 struct genl_info *info, 243 u16 *p_pool_index) 244{ 245 return devlink_sb_pool_index_get_from_attrs(devlink_sb, info->attrs, 246 p_pool_index); 247} 248 249static int 250devlink_sb_pool_type_get_from_attrs(struct nlattr **attrs, 251 enum devlink_sb_pool_type *p_pool_type) 252{ 253 u8 val; 254 255 if (!attrs[DEVLINK_ATTR_SB_POOL_TYPE]) 256 return -EINVAL; 257 258 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_TYPE]); 259 if (val != DEVLINK_SB_POOL_TYPE_INGRESS && 260 val != DEVLINK_SB_POOL_TYPE_EGRESS) 261 return -EINVAL; 262 *p_pool_type = val; 263 return 0; 264} 265 266static int 267devlink_sb_pool_type_get_from_info(struct genl_info *info, 268 enum devlink_sb_pool_type *p_pool_type) 269{ 270 return devlink_sb_pool_type_get_from_attrs(info->attrs, p_pool_type); 271} 272 273static int 274devlink_sb_th_type_get_from_attrs(struct nlattr **attrs, 275 enum devlink_sb_threshold_type *p_th_type) 276{ 277 u8 val; 278 279 if (!attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]) 280 return -EINVAL; 281 282 val = nla_get_u8(attrs[DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE]); 283 if (val != DEVLINK_SB_THRESHOLD_TYPE_STATIC && 284 val != DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC) 285 return -EINVAL; 286 *p_th_type = val; 287 return 0; 288} 289 290static int 291devlink_sb_th_type_get_from_info(struct genl_info *info, 292 enum devlink_sb_threshold_type *p_th_type) 293{ 294 return devlink_sb_th_type_get_from_attrs(info->attrs, p_th_type); 295} 296 297static int 298devlink_sb_tc_index_get_from_attrs(struct devlink_sb *devlink_sb, 299 struct nlattr **attrs, 300 enum devlink_sb_pool_type pool_type, 301 u16 *p_tc_index) 302{ 303 u16 val; 304 305 if (!attrs[DEVLINK_ATTR_SB_TC_INDEX]) 306 return -EINVAL; 307 308 val = nla_get_u16(attrs[DEVLINK_ATTR_SB_TC_INDEX]); 309 if (pool_type == DEVLINK_SB_POOL_TYPE_INGRESS && 310 val >= devlink_sb->ingress_tc_count) 311 return -EINVAL; 312 if (pool_type == DEVLINK_SB_POOL_TYPE_EGRESS && 313 val >= devlink_sb->egress_tc_count) 314 return -EINVAL; 315 *p_tc_index = val; 316 return 0; 317} 318 319static int 320devlink_sb_tc_index_get_from_info(struct devlink_sb *devlink_sb, 321 struct genl_info *info, 322 enum devlink_sb_pool_type pool_type, 323 u16 *p_tc_index) 324{ 325 return devlink_sb_tc_index_get_from_attrs(devlink_sb, info->attrs, 326 pool_type, p_tc_index); 327} 328 329struct devlink_region { 330 struct devlink *devlink; 331 struct list_head list; 332 const char *name; 333 struct list_head snapshot_list; 334 u32 max_snapshots; 335 u32 cur_snapshots; 336 u64 size; 337}; 338 339struct devlink_snapshot { 340 struct list_head list; 341 struct devlink_region *region; 342 devlink_snapshot_data_dest_t *data_destructor; 343 u64 data_len; 344 u8 *data; 345 u32 id; 346}; 347 348static struct devlink_region * 349devlink_region_get_by_name(struct devlink *devlink, const char *region_name) 350{ 351 struct devlink_region *region; 352 353 list_for_each_entry(region, &devlink->region_list, list) 354 if (!strcmp(region->name, region_name)) 355 return region; 356 357 return NULL; 358} 359 360static struct devlink_snapshot * 361devlink_region_snapshot_get_by_id(struct devlink_region *region, u32 id) 362{ 363 struct devlink_snapshot *snapshot; 364 365 list_for_each_entry(snapshot, &region->snapshot_list, list) 366 if (snapshot->id == id) 367 return snapshot; 368 369 return NULL; 370} 371 372static void devlink_region_snapshot_del(struct devlink_snapshot *snapshot) 373{ 374 snapshot->region->cur_snapshots--; 375 list_del(&snapshot->list); 376 (*snapshot->data_destructor)(snapshot->data); 377 kfree(snapshot); 378} 379 380#define DEVLINK_NL_FLAG_NEED_DEVLINK BIT(0) 381#define DEVLINK_NL_FLAG_NEED_PORT BIT(1) 382#define DEVLINK_NL_FLAG_NEED_SB BIT(2) 383 384/* The per devlink instance lock is taken by default in the pre-doit 385 * operation, yet several commands do not require this. The global 386 * devlink lock is taken and protects from disruption by user-calls. 387 */ 388#define DEVLINK_NL_FLAG_NO_LOCK BIT(3) 389 390static int devlink_nl_pre_doit(const struct genl_ops *ops, 391 struct sk_buff *skb, struct genl_info *info) 392{ 393 struct devlink *devlink; 394 int err; 395 396 mutex_lock(&devlink_mutex); 397 devlink = devlink_get_from_info(info); 398 if (IS_ERR(devlink)) { 399 mutex_unlock(&devlink_mutex); 400 return PTR_ERR(devlink); 401 } 402 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 403 mutex_lock(&devlink->lock); 404 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_DEVLINK) { 405 info->user_ptr[0] = devlink; 406 } else if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_PORT) { 407 struct devlink_port *devlink_port; 408 409 devlink_port = devlink_port_get_from_info(devlink, info); 410 if (IS_ERR(devlink_port)) { 411 err = PTR_ERR(devlink_port); 412 goto unlock; 413 } 414 info->user_ptr[0] = devlink_port; 415 } 416 if (ops->internal_flags & DEVLINK_NL_FLAG_NEED_SB) { 417 struct devlink_sb *devlink_sb; 418 419 devlink_sb = devlink_sb_get_from_info(devlink, info); 420 if (IS_ERR(devlink_sb)) { 421 err = PTR_ERR(devlink_sb); 422 goto unlock; 423 } 424 info->user_ptr[1] = devlink_sb; 425 } 426 return 0; 427 428unlock: 429 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 430 mutex_unlock(&devlink->lock); 431 mutex_unlock(&devlink_mutex); 432 return err; 433} 434 435static void devlink_nl_post_doit(const struct genl_ops *ops, 436 struct sk_buff *skb, struct genl_info *info) 437{ 438 struct devlink *devlink; 439 440 devlink = devlink_get_from_info(info); 441 if (~ops->internal_flags & DEVLINK_NL_FLAG_NO_LOCK) 442 mutex_unlock(&devlink->lock); 443 mutex_unlock(&devlink_mutex); 444} 445 446static struct genl_family devlink_nl_family; 447 448enum devlink_multicast_groups { 449 DEVLINK_MCGRP_CONFIG, 450}; 451 452static const struct genl_multicast_group devlink_nl_mcgrps[] = { 453 [DEVLINK_MCGRP_CONFIG] = { .name = DEVLINK_GENL_MCGRP_CONFIG_NAME }, 454}; 455 456static int devlink_nl_put_handle(struct sk_buff *msg, struct devlink *devlink) 457{ 458 if (nla_put_string(msg, DEVLINK_ATTR_BUS_NAME, devlink->dev->bus->name)) 459 return -EMSGSIZE; 460 if (nla_put_string(msg, DEVLINK_ATTR_DEV_NAME, dev_name(devlink->dev))) 461 return -EMSGSIZE; 462 return 0; 463} 464 465static int devlink_nl_fill(struct sk_buff *msg, struct devlink *devlink, 466 enum devlink_command cmd, u32 portid, 467 u32 seq, int flags) 468{ 469 void *hdr; 470 471 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 472 if (!hdr) 473 return -EMSGSIZE; 474 475 if (devlink_nl_put_handle(msg, devlink)) 476 goto nla_put_failure; 477 478 genlmsg_end(msg, hdr); 479 return 0; 480 481nla_put_failure: 482 genlmsg_cancel(msg, hdr); 483 return -EMSGSIZE; 484} 485 486static void devlink_notify(struct devlink *devlink, enum devlink_command cmd) 487{ 488 struct sk_buff *msg; 489 int err; 490 491 WARN_ON(cmd != DEVLINK_CMD_NEW && cmd != DEVLINK_CMD_DEL); 492 493 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 494 if (!msg) 495 return; 496 497 err = devlink_nl_fill(msg, devlink, cmd, 0, 0, 0); 498 if (err) { 499 nlmsg_free(msg); 500 return; 501 } 502 503 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 504 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 505} 506 507static int devlink_nl_port_attrs_put(struct sk_buff *msg, 508 struct devlink_port *devlink_port) 509{ 510 struct devlink_port_attrs *attrs = &devlink_port->attrs; 511 512 if (!attrs->set) 513 return 0; 514 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_FLAVOUR, attrs->flavour)) 515 return -EMSGSIZE; 516 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_NUMBER, attrs->port_number)) 517 return -EMSGSIZE; 518 if (!attrs->split) 519 return 0; 520 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_GROUP, attrs->port_number)) 521 return -EMSGSIZE; 522 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER, 523 attrs->split_subport_number)) 524 return -EMSGSIZE; 525 return 0; 526} 527 528static int devlink_nl_port_fill(struct sk_buff *msg, struct devlink *devlink, 529 struct devlink_port *devlink_port, 530 enum devlink_command cmd, u32 portid, 531 u32 seq, int flags) 532{ 533 void *hdr; 534 535 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 536 if (!hdr) 537 return -EMSGSIZE; 538 539 if (devlink_nl_put_handle(msg, devlink)) 540 goto nla_put_failure; 541 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 542 goto nla_put_failure; 543 if (nla_put_u16(msg, DEVLINK_ATTR_PORT_TYPE, devlink_port->type)) 544 goto nla_put_failure; 545 if (devlink_port->desired_type != DEVLINK_PORT_TYPE_NOTSET && 546 nla_put_u16(msg, DEVLINK_ATTR_PORT_DESIRED_TYPE, 547 devlink_port->desired_type)) 548 goto nla_put_failure; 549 if (devlink_port->type == DEVLINK_PORT_TYPE_ETH) { 550 struct net_device *netdev = devlink_port->type_dev; 551 552 if (netdev && 553 (nla_put_u32(msg, DEVLINK_ATTR_PORT_NETDEV_IFINDEX, 554 netdev->ifindex) || 555 nla_put_string(msg, DEVLINK_ATTR_PORT_NETDEV_NAME, 556 netdev->name))) 557 goto nla_put_failure; 558 } 559 if (devlink_port->type == DEVLINK_PORT_TYPE_IB) { 560 struct ib_device *ibdev = devlink_port->type_dev; 561 562 if (ibdev && 563 nla_put_string(msg, DEVLINK_ATTR_PORT_IBDEV_NAME, 564 ibdev->name)) 565 goto nla_put_failure; 566 } 567 if (devlink_nl_port_attrs_put(msg, devlink_port)) 568 goto nla_put_failure; 569 570 genlmsg_end(msg, hdr); 571 return 0; 572 573nla_put_failure: 574 genlmsg_cancel(msg, hdr); 575 return -EMSGSIZE; 576} 577 578static void devlink_port_notify(struct devlink_port *devlink_port, 579 enum devlink_command cmd) 580{ 581 struct devlink *devlink = devlink_port->devlink; 582 struct sk_buff *msg; 583 int err; 584 585 if (!devlink_port->registered) 586 return; 587 588 WARN_ON(cmd != DEVLINK_CMD_PORT_NEW && cmd != DEVLINK_CMD_PORT_DEL); 589 590 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 591 if (!msg) 592 return; 593 594 err = devlink_nl_port_fill(msg, devlink, devlink_port, cmd, 0, 0, 0); 595 if (err) { 596 nlmsg_free(msg); 597 return; 598 } 599 600 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 601 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 602} 603 604static int devlink_nl_cmd_get_doit(struct sk_buff *skb, struct genl_info *info) 605{ 606 struct devlink *devlink = info->user_ptr[0]; 607 struct sk_buff *msg; 608 int err; 609 610 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 611 if (!msg) 612 return -ENOMEM; 613 614 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW, 615 info->snd_portid, info->snd_seq, 0); 616 if (err) { 617 nlmsg_free(msg); 618 return err; 619 } 620 621 return genlmsg_reply(msg, info); 622} 623 624static int devlink_nl_cmd_get_dumpit(struct sk_buff *msg, 625 struct netlink_callback *cb) 626{ 627 struct devlink *devlink; 628 int start = cb->args[0]; 629 int idx = 0; 630 int err; 631 632 mutex_lock(&devlink_mutex); 633 list_for_each_entry(devlink, &devlink_list, list) { 634 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 635 continue; 636 if (idx < start) { 637 idx++; 638 continue; 639 } 640 err = devlink_nl_fill(msg, devlink, DEVLINK_CMD_NEW, 641 NETLINK_CB(cb->skb).portid, 642 cb->nlh->nlmsg_seq, NLM_F_MULTI); 643 if (err) 644 goto out; 645 idx++; 646 } 647out: 648 mutex_unlock(&devlink_mutex); 649 650 cb->args[0] = idx; 651 return msg->len; 652} 653 654static int devlink_nl_cmd_port_get_doit(struct sk_buff *skb, 655 struct genl_info *info) 656{ 657 struct devlink_port *devlink_port = info->user_ptr[0]; 658 struct devlink *devlink = devlink_port->devlink; 659 struct sk_buff *msg; 660 int err; 661 662 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 663 if (!msg) 664 return -ENOMEM; 665 666 err = devlink_nl_port_fill(msg, devlink, devlink_port, 667 DEVLINK_CMD_PORT_NEW, 668 info->snd_portid, info->snd_seq, 0); 669 if (err) { 670 nlmsg_free(msg); 671 return err; 672 } 673 674 return genlmsg_reply(msg, info); 675} 676 677static int devlink_nl_cmd_port_get_dumpit(struct sk_buff *msg, 678 struct netlink_callback *cb) 679{ 680 struct devlink *devlink; 681 struct devlink_port *devlink_port; 682 int start = cb->args[0]; 683 int idx = 0; 684 int err; 685 686 mutex_lock(&devlink_mutex); 687 list_for_each_entry(devlink, &devlink_list, list) { 688 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 689 continue; 690 mutex_lock(&devlink->lock); 691 list_for_each_entry(devlink_port, &devlink->port_list, list) { 692 if (idx < start) { 693 idx++; 694 continue; 695 } 696 err = devlink_nl_port_fill(msg, devlink, devlink_port, 697 DEVLINK_CMD_NEW, 698 NETLINK_CB(cb->skb).portid, 699 cb->nlh->nlmsg_seq, 700 NLM_F_MULTI); 701 if (err) { 702 mutex_unlock(&devlink->lock); 703 goto out; 704 } 705 idx++; 706 } 707 mutex_unlock(&devlink->lock); 708 } 709out: 710 mutex_unlock(&devlink_mutex); 711 712 cb->args[0] = idx; 713 return msg->len; 714} 715 716static int devlink_port_type_set(struct devlink *devlink, 717 struct devlink_port *devlink_port, 718 enum devlink_port_type port_type) 719 720{ 721 int err; 722 723 if (devlink->ops && devlink->ops->port_type_set) { 724 if (port_type == DEVLINK_PORT_TYPE_NOTSET) 725 return -EINVAL; 726 if (port_type == devlink_port->type) 727 return 0; 728 err = devlink->ops->port_type_set(devlink_port, port_type); 729 if (err) 730 return err; 731 devlink_port->desired_type = port_type; 732 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 733 return 0; 734 } 735 return -EOPNOTSUPP; 736} 737 738static int devlink_nl_cmd_port_set_doit(struct sk_buff *skb, 739 struct genl_info *info) 740{ 741 struct devlink_port *devlink_port = info->user_ptr[0]; 742 struct devlink *devlink = devlink_port->devlink; 743 int err; 744 745 if (info->attrs[DEVLINK_ATTR_PORT_TYPE]) { 746 enum devlink_port_type port_type; 747 748 port_type = nla_get_u16(info->attrs[DEVLINK_ATTR_PORT_TYPE]); 749 err = devlink_port_type_set(devlink, devlink_port, port_type); 750 if (err) 751 return err; 752 } 753 return 0; 754} 755 756static int devlink_port_split(struct devlink *devlink, u32 port_index, 757 u32 count, struct netlink_ext_ack *extack) 758 759{ 760 if (devlink->ops && devlink->ops->port_split) 761 return devlink->ops->port_split(devlink, port_index, count, 762 extack); 763 return -EOPNOTSUPP; 764} 765 766static int devlink_nl_cmd_port_split_doit(struct sk_buff *skb, 767 struct genl_info *info) 768{ 769 struct devlink *devlink = info->user_ptr[0]; 770 u32 port_index; 771 u32 count; 772 773 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX] || 774 !info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]) 775 return -EINVAL; 776 777 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 778 count = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_SPLIT_COUNT]); 779 return devlink_port_split(devlink, port_index, count, info->extack); 780} 781 782static int devlink_port_unsplit(struct devlink *devlink, u32 port_index, 783 struct netlink_ext_ack *extack) 784 785{ 786 if (devlink->ops && devlink->ops->port_unsplit) 787 return devlink->ops->port_unsplit(devlink, port_index, extack); 788 return -EOPNOTSUPP; 789} 790 791static int devlink_nl_cmd_port_unsplit_doit(struct sk_buff *skb, 792 struct genl_info *info) 793{ 794 struct devlink *devlink = info->user_ptr[0]; 795 u32 port_index; 796 797 if (!info->attrs[DEVLINK_ATTR_PORT_INDEX]) 798 return -EINVAL; 799 800 port_index = nla_get_u32(info->attrs[DEVLINK_ATTR_PORT_INDEX]); 801 return devlink_port_unsplit(devlink, port_index, info->extack); 802} 803 804static int devlink_nl_sb_fill(struct sk_buff *msg, struct devlink *devlink, 805 struct devlink_sb *devlink_sb, 806 enum devlink_command cmd, u32 portid, 807 u32 seq, int flags) 808{ 809 void *hdr; 810 811 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 812 if (!hdr) 813 return -EMSGSIZE; 814 815 if (devlink_nl_put_handle(msg, devlink)) 816 goto nla_put_failure; 817 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 818 goto nla_put_failure; 819 if (nla_put_u32(msg, DEVLINK_ATTR_SB_SIZE, devlink_sb->size)) 820 goto nla_put_failure; 821 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_POOL_COUNT, 822 devlink_sb->ingress_pools_count)) 823 goto nla_put_failure; 824 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_POOL_COUNT, 825 devlink_sb->egress_pools_count)) 826 goto nla_put_failure; 827 if (nla_put_u16(msg, DEVLINK_ATTR_SB_INGRESS_TC_COUNT, 828 devlink_sb->ingress_tc_count)) 829 goto nla_put_failure; 830 if (nla_put_u16(msg, DEVLINK_ATTR_SB_EGRESS_TC_COUNT, 831 devlink_sb->egress_tc_count)) 832 goto nla_put_failure; 833 834 genlmsg_end(msg, hdr); 835 return 0; 836 837nla_put_failure: 838 genlmsg_cancel(msg, hdr); 839 return -EMSGSIZE; 840} 841 842static int devlink_nl_cmd_sb_get_doit(struct sk_buff *skb, 843 struct genl_info *info) 844{ 845 struct devlink *devlink = info->user_ptr[0]; 846 struct devlink_sb *devlink_sb = info->user_ptr[1]; 847 struct sk_buff *msg; 848 int err; 849 850 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 851 if (!msg) 852 return -ENOMEM; 853 854 err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 855 DEVLINK_CMD_SB_NEW, 856 info->snd_portid, info->snd_seq, 0); 857 if (err) { 858 nlmsg_free(msg); 859 return err; 860 } 861 862 return genlmsg_reply(msg, info); 863} 864 865static int devlink_nl_cmd_sb_get_dumpit(struct sk_buff *msg, 866 struct netlink_callback *cb) 867{ 868 struct devlink *devlink; 869 struct devlink_sb *devlink_sb; 870 int start = cb->args[0]; 871 int idx = 0; 872 int err; 873 874 mutex_lock(&devlink_mutex); 875 list_for_each_entry(devlink, &devlink_list, list) { 876 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 877 continue; 878 mutex_lock(&devlink->lock); 879 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 880 if (idx < start) { 881 idx++; 882 continue; 883 } 884 err = devlink_nl_sb_fill(msg, devlink, devlink_sb, 885 DEVLINK_CMD_SB_NEW, 886 NETLINK_CB(cb->skb).portid, 887 cb->nlh->nlmsg_seq, 888 NLM_F_MULTI); 889 if (err) { 890 mutex_unlock(&devlink->lock); 891 goto out; 892 } 893 idx++; 894 } 895 mutex_unlock(&devlink->lock); 896 } 897out: 898 mutex_unlock(&devlink_mutex); 899 900 cb->args[0] = idx; 901 return msg->len; 902} 903 904static int devlink_nl_sb_pool_fill(struct sk_buff *msg, struct devlink *devlink, 905 struct devlink_sb *devlink_sb, 906 u16 pool_index, enum devlink_command cmd, 907 u32 portid, u32 seq, int flags) 908{ 909 struct devlink_sb_pool_info pool_info; 910 void *hdr; 911 int err; 912 913 err = devlink->ops->sb_pool_get(devlink, devlink_sb->index, 914 pool_index, &pool_info); 915 if (err) 916 return err; 917 918 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 919 if (!hdr) 920 return -EMSGSIZE; 921 922 if (devlink_nl_put_handle(msg, devlink)) 923 goto nla_put_failure; 924 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 925 goto nla_put_failure; 926 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 927 goto nla_put_failure; 928 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_info.pool_type)) 929 goto nla_put_failure; 930 if (nla_put_u32(msg, DEVLINK_ATTR_SB_POOL_SIZE, pool_info.size)) 931 goto nla_put_failure; 932 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, 933 pool_info.threshold_type)) 934 goto nla_put_failure; 935 936 genlmsg_end(msg, hdr); 937 return 0; 938 939nla_put_failure: 940 genlmsg_cancel(msg, hdr); 941 return -EMSGSIZE; 942} 943 944static int devlink_nl_cmd_sb_pool_get_doit(struct sk_buff *skb, 945 struct genl_info *info) 946{ 947 struct devlink *devlink = info->user_ptr[0]; 948 struct devlink_sb *devlink_sb = info->user_ptr[1]; 949 struct sk_buff *msg; 950 u16 pool_index; 951 int err; 952 953 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 954 &pool_index); 955 if (err) 956 return err; 957 958 if (!devlink->ops || !devlink->ops->sb_pool_get) 959 return -EOPNOTSUPP; 960 961 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 962 if (!msg) 963 return -ENOMEM; 964 965 err = devlink_nl_sb_pool_fill(msg, devlink, devlink_sb, pool_index, 966 DEVLINK_CMD_SB_POOL_NEW, 967 info->snd_portid, info->snd_seq, 0); 968 if (err) { 969 nlmsg_free(msg); 970 return err; 971 } 972 973 return genlmsg_reply(msg, info); 974} 975 976static int __sb_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 977 struct devlink *devlink, 978 struct devlink_sb *devlink_sb, 979 u32 portid, u32 seq) 980{ 981 u16 pool_count = devlink_sb_pool_count(devlink_sb); 982 u16 pool_index; 983 int err; 984 985 for (pool_index = 0; pool_index < pool_count; pool_index++) { 986 if (*p_idx < start) { 987 (*p_idx)++; 988 continue; 989 } 990 err = devlink_nl_sb_pool_fill(msg, devlink, 991 devlink_sb, 992 pool_index, 993 DEVLINK_CMD_SB_POOL_NEW, 994 portid, seq, NLM_F_MULTI); 995 if (err) 996 return err; 997 (*p_idx)++; 998 } 999 return 0; 1000} 1001 1002static int devlink_nl_cmd_sb_pool_get_dumpit(struct sk_buff *msg, 1003 struct netlink_callback *cb) 1004{ 1005 struct devlink *devlink; 1006 struct devlink_sb *devlink_sb; 1007 int start = cb->args[0]; 1008 int idx = 0; 1009 int err; 1010 1011 mutex_lock(&devlink_mutex); 1012 list_for_each_entry(devlink, &devlink_list, list) { 1013 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 1014 !devlink->ops || !devlink->ops->sb_pool_get) 1015 continue; 1016 mutex_lock(&devlink->lock); 1017 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 1018 err = __sb_pool_get_dumpit(msg, start, &idx, devlink, 1019 devlink_sb, 1020 NETLINK_CB(cb->skb).portid, 1021 cb->nlh->nlmsg_seq); 1022 if (err && err != -EOPNOTSUPP) { 1023 mutex_unlock(&devlink->lock); 1024 goto out; 1025 } 1026 } 1027 mutex_unlock(&devlink->lock); 1028 } 1029out: 1030 mutex_unlock(&devlink_mutex); 1031 1032 cb->args[0] = idx; 1033 return msg->len; 1034} 1035 1036static int devlink_sb_pool_set(struct devlink *devlink, unsigned int sb_index, 1037 u16 pool_index, u32 size, 1038 enum devlink_sb_threshold_type threshold_type) 1039 1040{ 1041 const struct devlink_ops *ops = devlink->ops; 1042 1043 if (ops && ops->sb_pool_set) 1044 return ops->sb_pool_set(devlink, sb_index, pool_index, 1045 size, threshold_type); 1046 return -EOPNOTSUPP; 1047} 1048 1049static int devlink_nl_cmd_sb_pool_set_doit(struct sk_buff *skb, 1050 struct genl_info *info) 1051{ 1052 struct devlink *devlink = info->user_ptr[0]; 1053 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1054 enum devlink_sb_threshold_type threshold_type; 1055 u16 pool_index; 1056 u32 size; 1057 int err; 1058 1059 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1060 &pool_index); 1061 if (err) 1062 return err; 1063 1064 err = devlink_sb_th_type_get_from_info(info, &threshold_type); 1065 if (err) 1066 return err; 1067 1068 if (!info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]) 1069 return -EINVAL; 1070 1071 size = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_POOL_SIZE]); 1072 return devlink_sb_pool_set(devlink, devlink_sb->index, 1073 pool_index, size, threshold_type); 1074} 1075 1076static int devlink_nl_sb_port_pool_fill(struct sk_buff *msg, 1077 struct devlink *devlink, 1078 struct devlink_port *devlink_port, 1079 struct devlink_sb *devlink_sb, 1080 u16 pool_index, 1081 enum devlink_command cmd, 1082 u32 portid, u32 seq, int flags) 1083{ 1084 const struct devlink_ops *ops = devlink->ops; 1085 u32 threshold; 1086 void *hdr; 1087 int err; 1088 1089 err = ops->sb_port_pool_get(devlink_port, devlink_sb->index, 1090 pool_index, &threshold); 1091 if (err) 1092 return err; 1093 1094 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1095 if (!hdr) 1096 return -EMSGSIZE; 1097 1098 if (devlink_nl_put_handle(msg, devlink)) 1099 goto nla_put_failure; 1100 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 1101 goto nla_put_failure; 1102 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 1103 goto nla_put_failure; 1104 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 1105 goto nla_put_failure; 1106 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 1107 goto nla_put_failure; 1108 1109 if (ops->sb_occ_port_pool_get) { 1110 u32 cur; 1111 u32 max; 1112 1113 err = ops->sb_occ_port_pool_get(devlink_port, devlink_sb->index, 1114 pool_index, &cur, &max); 1115 if (err && err != -EOPNOTSUPP) 1116 return err; 1117 if (!err) { 1118 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 1119 goto nla_put_failure; 1120 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 1121 goto nla_put_failure; 1122 } 1123 } 1124 1125 genlmsg_end(msg, hdr); 1126 return 0; 1127 1128nla_put_failure: 1129 genlmsg_cancel(msg, hdr); 1130 return -EMSGSIZE; 1131} 1132 1133static int devlink_nl_cmd_sb_port_pool_get_doit(struct sk_buff *skb, 1134 struct genl_info *info) 1135{ 1136 struct devlink_port *devlink_port = info->user_ptr[0]; 1137 struct devlink *devlink = devlink_port->devlink; 1138 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1139 struct sk_buff *msg; 1140 u16 pool_index; 1141 int err; 1142 1143 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1144 &pool_index); 1145 if (err) 1146 return err; 1147 1148 if (!devlink->ops || !devlink->ops->sb_port_pool_get) 1149 return -EOPNOTSUPP; 1150 1151 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1152 if (!msg) 1153 return -ENOMEM; 1154 1155 err = devlink_nl_sb_port_pool_fill(msg, devlink, devlink_port, 1156 devlink_sb, pool_index, 1157 DEVLINK_CMD_SB_PORT_POOL_NEW, 1158 info->snd_portid, info->snd_seq, 0); 1159 if (err) { 1160 nlmsg_free(msg); 1161 return err; 1162 } 1163 1164 return genlmsg_reply(msg, info); 1165} 1166 1167static int __sb_port_pool_get_dumpit(struct sk_buff *msg, int start, int *p_idx, 1168 struct devlink *devlink, 1169 struct devlink_sb *devlink_sb, 1170 u32 portid, u32 seq) 1171{ 1172 struct devlink_port *devlink_port; 1173 u16 pool_count = devlink_sb_pool_count(devlink_sb); 1174 u16 pool_index; 1175 int err; 1176 1177 list_for_each_entry(devlink_port, &devlink->port_list, list) { 1178 for (pool_index = 0; pool_index < pool_count; pool_index++) { 1179 if (*p_idx < start) { 1180 (*p_idx)++; 1181 continue; 1182 } 1183 err = devlink_nl_sb_port_pool_fill(msg, devlink, 1184 devlink_port, 1185 devlink_sb, 1186 pool_index, 1187 DEVLINK_CMD_SB_PORT_POOL_NEW, 1188 portid, seq, 1189 NLM_F_MULTI); 1190 if (err) 1191 return err; 1192 (*p_idx)++; 1193 } 1194 } 1195 return 0; 1196} 1197 1198static int devlink_nl_cmd_sb_port_pool_get_dumpit(struct sk_buff *msg, 1199 struct netlink_callback *cb) 1200{ 1201 struct devlink *devlink; 1202 struct devlink_sb *devlink_sb; 1203 int start = cb->args[0]; 1204 int idx = 0; 1205 int err; 1206 1207 mutex_lock(&devlink_mutex); 1208 list_for_each_entry(devlink, &devlink_list, list) { 1209 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 1210 !devlink->ops || !devlink->ops->sb_port_pool_get) 1211 continue; 1212 mutex_lock(&devlink->lock); 1213 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 1214 err = __sb_port_pool_get_dumpit(msg, start, &idx, 1215 devlink, devlink_sb, 1216 NETLINK_CB(cb->skb).portid, 1217 cb->nlh->nlmsg_seq); 1218 if (err && err != -EOPNOTSUPP) { 1219 mutex_unlock(&devlink->lock); 1220 goto out; 1221 } 1222 } 1223 mutex_unlock(&devlink->lock); 1224 } 1225out: 1226 mutex_unlock(&devlink_mutex); 1227 1228 cb->args[0] = idx; 1229 return msg->len; 1230} 1231 1232static int devlink_sb_port_pool_set(struct devlink_port *devlink_port, 1233 unsigned int sb_index, u16 pool_index, 1234 u32 threshold) 1235 1236{ 1237 const struct devlink_ops *ops = devlink_port->devlink->ops; 1238 1239 if (ops && ops->sb_port_pool_set) 1240 return ops->sb_port_pool_set(devlink_port, sb_index, 1241 pool_index, threshold); 1242 return -EOPNOTSUPP; 1243} 1244 1245static int devlink_nl_cmd_sb_port_pool_set_doit(struct sk_buff *skb, 1246 struct genl_info *info) 1247{ 1248 struct devlink_port *devlink_port = info->user_ptr[0]; 1249 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1250 u16 pool_index; 1251 u32 threshold; 1252 int err; 1253 1254 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1255 &pool_index); 1256 if (err) 1257 return err; 1258 1259 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD]) 1260 return -EINVAL; 1261 1262 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 1263 return devlink_sb_port_pool_set(devlink_port, devlink_sb->index, 1264 pool_index, threshold); 1265} 1266 1267static int 1268devlink_nl_sb_tc_pool_bind_fill(struct sk_buff *msg, struct devlink *devlink, 1269 struct devlink_port *devlink_port, 1270 struct devlink_sb *devlink_sb, u16 tc_index, 1271 enum devlink_sb_pool_type pool_type, 1272 enum devlink_command cmd, 1273 u32 portid, u32 seq, int flags) 1274{ 1275 const struct devlink_ops *ops = devlink->ops; 1276 u16 pool_index; 1277 u32 threshold; 1278 void *hdr; 1279 int err; 1280 1281 err = ops->sb_tc_pool_bind_get(devlink_port, devlink_sb->index, 1282 tc_index, pool_type, 1283 &pool_index, &threshold); 1284 if (err) 1285 return err; 1286 1287 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1288 if (!hdr) 1289 return -EMSGSIZE; 1290 1291 if (devlink_nl_put_handle(msg, devlink)) 1292 goto nla_put_failure; 1293 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, devlink_port->index)) 1294 goto nla_put_failure; 1295 if (nla_put_u32(msg, DEVLINK_ATTR_SB_INDEX, devlink_sb->index)) 1296 goto nla_put_failure; 1297 if (nla_put_u16(msg, DEVLINK_ATTR_SB_TC_INDEX, tc_index)) 1298 goto nla_put_failure; 1299 if (nla_put_u8(msg, DEVLINK_ATTR_SB_POOL_TYPE, pool_type)) 1300 goto nla_put_failure; 1301 if (nla_put_u16(msg, DEVLINK_ATTR_SB_POOL_INDEX, pool_index)) 1302 goto nla_put_failure; 1303 if (nla_put_u32(msg, DEVLINK_ATTR_SB_THRESHOLD, threshold)) 1304 goto nla_put_failure; 1305 1306 if (ops->sb_occ_tc_port_bind_get) { 1307 u32 cur; 1308 u32 max; 1309 1310 err = ops->sb_occ_tc_port_bind_get(devlink_port, 1311 devlink_sb->index, 1312 tc_index, pool_type, 1313 &cur, &max); 1314 if (err && err != -EOPNOTSUPP) 1315 return err; 1316 if (!err) { 1317 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_CUR, cur)) 1318 goto nla_put_failure; 1319 if (nla_put_u32(msg, DEVLINK_ATTR_SB_OCC_MAX, max)) 1320 goto nla_put_failure; 1321 } 1322 } 1323 1324 genlmsg_end(msg, hdr); 1325 return 0; 1326 1327nla_put_failure: 1328 genlmsg_cancel(msg, hdr); 1329 return -EMSGSIZE; 1330} 1331 1332static int devlink_nl_cmd_sb_tc_pool_bind_get_doit(struct sk_buff *skb, 1333 struct genl_info *info) 1334{ 1335 struct devlink_port *devlink_port = info->user_ptr[0]; 1336 struct devlink *devlink = devlink_port->devlink; 1337 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1338 struct sk_buff *msg; 1339 enum devlink_sb_pool_type pool_type; 1340 u16 tc_index; 1341 int err; 1342 1343 err = devlink_sb_pool_type_get_from_info(info, &pool_type); 1344 if (err) 1345 return err; 1346 1347 err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 1348 pool_type, &tc_index); 1349 if (err) 1350 return err; 1351 1352 if (!devlink->ops || !devlink->ops->sb_tc_pool_bind_get) 1353 return -EOPNOTSUPP; 1354 1355 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1356 if (!msg) 1357 return -ENOMEM; 1358 1359 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, devlink_port, 1360 devlink_sb, tc_index, pool_type, 1361 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1362 info->snd_portid, 1363 info->snd_seq, 0); 1364 if (err) { 1365 nlmsg_free(msg); 1366 return err; 1367 } 1368 1369 return genlmsg_reply(msg, info); 1370} 1371 1372static int __sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, 1373 int start, int *p_idx, 1374 struct devlink *devlink, 1375 struct devlink_sb *devlink_sb, 1376 u32 portid, u32 seq) 1377{ 1378 struct devlink_port *devlink_port; 1379 u16 tc_index; 1380 int err; 1381 1382 list_for_each_entry(devlink_port, &devlink->port_list, list) { 1383 for (tc_index = 0; 1384 tc_index < devlink_sb->ingress_tc_count; tc_index++) { 1385 if (*p_idx < start) { 1386 (*p_idx)++; 1387 continue; 1388 } 1389 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 1390 devlink_port, 1391 devlink_sb, 1392 tc_index, 1393 DEVLINK_SB_POOL_TYPE_INGRESS, 1394 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1395 portid, seq, 1396 NLM_F_MULTI); 1397 if (err) 1398 return err; 1399 (*p_idx)++; 1400 } 1401 for (tc_index = 0; 1402 tc_index < devlink_sb->egress_tc_count; tc_index++) { 1403 if (*p_idx < start) { 1404 (*p_idx)++; 1405 continue; 1406 } 1407 err = devlink_nl_sb_tc_pool_bind_fill(msg, devlink, 1408 devlink_port, 1409 devlink_sb, 1410 tc_index, 1411 DEVLINK_SB_POOL_TYPE_EGRESS, 1412 DEVLINK_CMD_SB_TC_POOL_BIND_NEW, 1413 portid, seq, 1414 NLM_F_MULTI); 1415 if (err) 1416 return err; 1417 (*p_idx)++; 1418 } 1419 } 1420 return 0; 1421} 1422 1423static int 1424devlink_nl_cmd_sb_tc_pool_bind_get_dumpit(struct sk_buff *msg, 1425 struct netlink_callback *cb) 1426{ 1427 struct devlink *devlink; 1428 struct devlink_sb *devlink_sb; 1429 int start = cb->args[0]; 1430 int idx = 0; 1431 int err; 1432 1433 mutex_lock(&devlink_mutex); 1434 list_for_each_entry(devlink, &devlink_list, list) { 1435 if (!net_eq(devlink_net(devlink), sock_net(msg->sk)) || 1436 !devlink->ops || !devlink->ops->sb_tc_pool_bind_get) 1437 continue; 1438 1439 mutex_lock(&devlink->lock); 1440 list_for_each_entry(devlink_sb, &devlink->sb_list, list) { 1441 err = __sb_tc_pool_bind_get_dumpit(msg, start, &idx, 1442 devlink, 1443 devlink_sb, 1444 NETLINK_CB(cb->skb).portid, 1445 cb->nlh->nlmsg_seq); 1446 if (err && err != -EOPNOTSUPP) { 1447 mutex_unlock(&devlink->lock); 1448 goto out; 1449 } 1450 } 1451 mutex_unlock(&devlink->lock); 1452 } 1453out: 1454 mutex_unlock(&devlink_mutex); 1455 1456 cb->args[0] = idx; 1457 return msg->len; 1458} 1459 1460static int devlink_sb_tc_pool_bind_set(struct devlink_port *devlink_port, 1461 unsigned int sb_index, u16 tc_index, 1462 enum devlink_sb_pool_type pool_type, 1463 u16 pool_index, u32 threshold) 1464 1465{ 1466 const struct devlink_ops *ops = devlink_port->devlink->ops; 1467 1468 if (ops && ops->sb_tc_pool_bind_set) 1469 return ops->sb_tc_pool_bind_set(devlink_port, sb_index, 1470 tc_index, pool_type, 1471 pool_index, threshold); 1472 return -EOPNOTSUPP; 1473} 1474 1475static int devlink_nl_cmd_sb_tc_pool_bind_set_doit(struct sk_buff *skb, 1476 struct genl_info *info) 1477{ 1478 struct devlink_port *devlink_port = info->user_ptr[0]; 1479 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1480 enum devlink_sb_pool_type pool_type; 1481 u16 tc_index; 1482 u16 pool_index; 1483 u32 threshold; 1484 int err; 1485 1486 err = devlink_sb_pool_type_get_from_info(info, &pool_type); 1487 if (err) 1488 return err; 1489 1490 err = devlink_sb_tc_index_get_from_info(devlink_sb, info, 1491 pool_type, &tc_index); 1492 if (err) 1493 return err; 1494 1495 err = devlink_sb_pool_index_get_from_info(devlink_sb, info, 1496 &pool_index); 1497 if (err) 1498 return err; 1499 1500 if (!info->attrs[DEVLINK_ATTR_SB_THRESHOLD]) 1501 return -EINVAL; 1502 1503 threshold = nla_get_u32(info->attrs[DEVLINK_ATTR_SB_THRESHOLD]); 1504 return devlink_sb_tc_pool_bind_set(devlink_port, devlink_sb->index, 1505 tc_index, pool_type, 1506 pool_index, threshold); 1507} 1508 1509static int devlink_nl_cmd_sb_occ_snapshot_doit(struct sk_buff *skb, 1510 struct genl_info *info) 1511{ 1512 struct devlink *devlink = info->user_ptr[0]; 1513 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1514 const struct devlink_ops *ops = devlink->ops; 1515 1516 if (ops && ops->sb_occ_snapshot) 1517 return ops->sb_occ_snapshot(devlink, devlink_sb->index); 1518 return -EOPNOTSUPP; 1519} 1520 1521static int devlink_nl_cmd_sb_occ_max_clear_doit(struct sk_buff *skb, 1522 struct genl_info *info) 1523{ 1524 struct devlink *devlink = info->user_ptr[0]; 1525 struct devlink_sb *devlink_sb = info->user_ptr[1]; 1526 const struct devlink_ops *ops = devlink->ops; 1527 1528 if (ops && ops->sb_occ_max_clear) 1529 return ops->sb_occ_max_clear(devlink, devlink_sb->index); 1530 return -EOPNOTSUPP; 1531} 1532 1533static int devlink_nl_eswitch_fill(struct sk_buff *msg, struct devlink *devlink, 1534 enum devlink_command cmd, u32 portid, 1535 u32 seq, int flags) 1536{ 1537 const struct devlink_ops *ops = devlink->ops; 1538 u8 inline_mode, encap_mode; 1539 void *hdr; 1540 int err = 0; 1541 u16 mode; 1542 1543 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 1544 if (!hdr) 1545 return -EMSGSIZE; 1546 1547 err = devlink_nl_put_handle(msg, devlink); 1548 if (err) 1549 goto nla_put_failure; 1550 1551 if (ops->eswitch_mode_get) { 1552 err = ops->eswitch_mode_get(devlink, &mode); 1553 if (err) 1554 goto nla_put_failure; 1555 err = nla_put_u16(msg, DEVLINK_ATTR_ESWITCH_MODE, mode); 1556 if (err) 1557 goto nla_put_failure; 1558 } 1559 1560 if (ops->eswitch_inline_mode_get) { 1561 err = ops->eswitch_inline_mode_get(devlink, &inline_mode); 1562 if (err) 1563 goto nla_put_failure; 1564 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_INLINE_MODE, 1565 inline_mode); 1566 if (err) 1567 goto nla_put_failure; 1568 } 1569 1570 if (ops->eswitch_encap_mode_get) { 1571 err = ops->eswitch_encap_mode_get(devlink, &encap_mode); 1572 if (err) 1573 goto nla_put_failure; 1574 err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, encap_mode); 1575 if (err) 1576 goto nla_put_failure; 1577 } 1578 1579 genlmsg_end(msg, hdr); 1580 return 0; 1581 1582nla_put_failure: 1583 genlmsg_cancel(msg, hdr); 1584 return err; 1585} 1586 1587static int devlink_nl_cmd_eswitch_get_doit(struct sk_buff *skb, 1588 struct genl_info *info) 1589{ 1590 struct devlink *devlink = info->user_ptr[0]; 1591 const struct devlink_ops *ops = devlink->ops; 1592 struct sk_buff *msg; 1593 int err; 1594 1595 if (!ops) 1596 return -EOPNOTSUPP; 1597 1598 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 1599 if (!msg) 1600 return -ENOMEM; 1601 1602 err = devlink_nl_eswitch_fill(msg, devlink, DEVLINK_CMD_ESWITCH_GET, 1603 info->snd_portid, info->snd_seq, 0); 1604 1605 if (err) { 1606 nlmsg_free(msg); 1607 return err; 1608 } 1609 1610 return genlmsg_reply(msg, info); 1611} 1612 1613static int devlink_nl_cmd_eswitch_set_doit(struct sk_buff *skb, 1614 struct genl_info *info) 1615{ 1616 struct devlink *devlink = info->user_ptr[0]; 1617 const struct devlink_ops *ops = devlink->ops; 1618 u8 inline_mode, encap_mode; 1619 int err = 0; 1620 u16 mode; 1621 1622 if (!ops) 1623 return -EOPNOTSUPP; 1624 1625 if (info->attrs[DEVLINK_ATTR_ESWITCH_MODE]) { 1626 if (!ops->eswitch_mode_set) 1627 return -EOPNOTSUPP; 1628 mode = nla_get_u16(info->attrs[DEVLINK_ATTR_ESWITCH_MODE]); 1629 err = ops->eswitch_mode_set(devlink, mode); 1630 if (err) 1631 return err; 1632 } 1633 1634 if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) { 1635 if (!ops->eswitch_inline_mode_set) 1636 return -EOPNOTSUPP; 1637 inline_mode = nla_get_u8( 1638 info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]); 1639 err = ops->eswitch_inline_mode_set(devlink, inline_mode); 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 if (err) 1650 return err; 1651 } 1652 1653 return 0; 1654} 1655 1656int devlink_dpipe_match_put(struct sk_buff *skb, 1657 struct devlink_dpipe_match *match) 1658{ 1659 struct devlink_dpipe_header *header = match->header; 1660 struct devlink_dpipe_field *field = &header->fields[match->field_id]; 1661 struct nlattr *match_attr; 1662 1663 match_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_MATCH); 1664 if (!match_attr) 1665 return -EMSGSIZE; 1666 1667 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_MATCH_TYPE, match->type) || 1668 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, match->header_index) || 1669 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 1670 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 1671 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 1672 goto nla_put_failure; 1673 1674 nla_nest_end(skb, match_attr); 1675 return 0; 1676 1677nla_put_failure: 1678 nla_nest_cancel(skb, match_attr); 1679 return -EMSGSIZE; 1680} 1681EXPORT_SYMBOL_GPL(devlink_dpipe_match_put); 1682 1683static int devlink_dpipe_matches_put(struct devlink_dpipe_table *table, 1684 struct sk_buff *skb) 1685{ 1686 struct nlattr *matches_attr; 1687 1688 matches_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLE_MATCHES); 1689 if (!matches_attr) 1690 return -EMSGSIZE; 1691 1692 if (table->table_ops->matches_dump(table->priv, skb)) 1693 goto nla_put_failure; 1694 1695 nla_nest_end(skb, matches_attr); 1696 return 0; 1697 1698nla_put_failure: 1699 nla_nest_cancel(skb, matches_attr); 1700 return -EMSGSIZE; 1701} 1702 1703int devlink_dpipe_action_put(struct sk_buff *skb, 1704 struct devlink_dpipe_action *action) 1705{ 1706 struct devlink_dpipe_header *header = action->header; 1707 struct devlink_dpipe_field *field = &header->fields[action->field_id]; 1708 struct nlattr *action_attr; 1709 1710 action_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_ACTION); 1711 if (!action_attr) 1712 return -EMSGSIZE; 1713 1714 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_ACTION_TYPE, action->type) || 1715 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_INDEX, action->header_index) || 1716 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 1717 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 1718 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 1719 goto nla_put_failure; 1720 1721 nla_nest_end(skb, action_attr); 1722 return 0; 1723 1724nla_put_failure: 1725 nla_nest_cancel(skb, action_attr); 1726 return -EMSGSIZE; 1727} 1728EXPORT_SYMBOL_GPL(devlink_dpipe_action_put); 1729 1730static int devlink_dpipe_actions_put(struct devlink_dpipe_table *table, 1731 struct sk_buff *skb) 1732{ 1733 struct nlattr *actions_attr; 1734 1735 actions_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLE_ACTIONS); 1736 if (!actions_attr) 1737 return -EMSGSIZE; 1738 1739 if (table->table_ops->actions_dump(table->priv, skb)) 1740 goto nla_put_failure; 1741 1742 nla_nest_end(skb, actions_attr); 1743 return 0; 1744 1745nla_put_failure: 1746 nla_nest_cancel(skb, actions_attr); 1747 return -EMSGSIZE; 1748} 1749 1750static int devlink_dpipe_table_put(struct sk_buff *skb, 1751 struct devlink_dpipe_table *table) 1752{ 1753 struct nlattr *table_attr; 1754 u64 table_size; 1755 1756 table_size = table->table_ops->size_get(table->priv); 1757 table_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLE); 1758 if (!table_attr) 1759 return -EMSGSIZE; 1760 1761 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_TABLE_NAME, table->name) || 1762 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_SIZE, table_size, 1763 DEVLINK_ATTR_PAD)) 1764 goto nla_put_failure; 1765 if (nla_put_u8(skb, DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED, 1766 table->counters_enabled)) 1767 goto nla_put_failure; 1768 1769 if (table->resource_valid) { 1770 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID, 1771 table->resource_id, DEVLINK_ATTR_PAD) || 1772 nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS, 1773 table->resource_units, DEVLINK_ATTR_PAD)) 1774 goto nla_put_failure; 1775 } 1776 if (devlink_dpipe_matches_put(table, skb)) 1777 goto nla_put_failure; 1778 1779 if (devlink_dpipe_actions_put(table, skb)) 1780 goto nla_put_failure; 1781 1782 nla_nest_end(skb, table_attr); 1783 return 0; 1784 1785nla_put_failure: 1786 nla_nest_cancel(skb, table_attr); 1787 return -EMSGSIZE; 1788} 1789 1790static int devlink_dpipe_send_and_alloc_skb(struct sk_buff **pskb, 1791 struct genl_info *info) 1792{ 1793 int err; 1794 1795 if (*pskb) { 1796 err = genlmsg_reply(*pskb, info); 1797 if (err) 1798 return err; 1799 } 1800 *pskb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); 1801 if (!*pskb) 1802 return -ENOMEM; 1803 return 0; 1804} 1805 1806static int devlink_dpipe_tables_fill(struct genl_info *info, 1807 enum devlink_command cmd, int flags, 1808 struct list_head *dpipe_tables, 1809 const char *table_name) 1810{ 1811 struct devlink *devlink = info->user_ptr[0]; 1812 struct devlink_dpipe_table *table; 1813 struct nlattr *tables_attr; 1814 struct sk_buff *skb = NULL; 1815 struct nlmsghdr *nlh; 1816 bool incomplete; 1817 void *hdr; 1818 int i; 1819 int err; 1820 1821 table = list_first_entry(dpipe_tables, 1822 struct devlink_dpipe_table, list); 1823start_again: 1824 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 1825 if (err) 1826 return err; 1827 1828 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 1829 &devlink_nl_family, NLM_F_MULTI, cmd); 1830 if (!hdr) { 1831 nlmsg_free(skb); 1832 return -EMSGSIZE; 1833 } 1834 1835 if (devlink_nl_put_handle(skb, devlink)) 1836 goto nla_put_failure; 1837 tables_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_TABLES); 1838 if (!tables_attr) 1839 goto nla_put_failure; 1840 1841 i = 0; 1842 incomplete = false; 1843 list_for_each_entry_from(table, dpipe_tables, list) { 1844 if (!table_name) { 1845 err = devlink_dpipe_table_put(skb, table); 1846 if (err) { 1847 if (!i) 1848 goto err_table_put; 1849 incomplete = true; 1850 break; 1851 } 1852 } else { 1853 if (!strcmp(table->name, table_name)) { 1854 err = devlink_dpipe_table_put(skb, table); 1855 if (err) 1856 break; 1857 } 1858 } 1859 i++; 1860 } 1861 1862 nla_nest_end(skb, tables_attr); 1863 genlmsg_end(skb, hdr); 1864 if (incomplete) 1865 goto start_again; 1866 1867send_done: 1868 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 1869 NLMSG_DONE, 0, flags | NLM_F_MULTI); 1870 if (!nlh) { 1871 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 1872 if (err) 1873 return err; 1874 goto send_done; 1875 } 1876 1877 return genlmsg_reply(skb, info); 1878 1879nla_put_failure: 1880 err = -EMSGSIZE; 1881err_table_put: 1882 nlmsg_free(skb); 1883 return err; 1884} 1885 1886static int devlink_nl_cmd_dpipe_table_get(struct sk_buff *skb, 1887 struct genl_info *info) 1888{ 1889 struct devlink *devlink = info->user_ptr[0]; 1890 const char *table_name = NULL; 1891 1892 if (info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]) 1893 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 1894 1895 return devlink_dpipe_tables_fill(info, DEVLINK_CMD_DPIPE_TABLE_GET, 0, 1896 &devlink->dpipe_table_list, 1897 table_name); 1898} 1899 1900static int devlink_dpipe_value_put(struct sk_buff *skb, 1901 struct devlink_dpipe_value *value) 1902{ 1903 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE, 1904 value->value_size, value->value)) 1905 return -EMSGSIZE; 1906 if (value->mask) 1907 if (nla_put(skb, DEVLINK_ATTR_DPIPE_VALUE_MASK, 1908 value->value_size, value->mask)) 1909 return -EMSGSIZE; 1910 if (value->mapping_valid) 1911 if (nla_put_u32(skb, DEVLINK_ATTR_DPIPE_VALUE_MAPPING, 1912 value->mapping_value)) 1913 return -EMSGSIZE; 1914 return 0; 1915} 1916 1917static int devlink_dpipe_action_value_put(struct sk_buff *skb, 1918 struct devlink_dpipe_value *value) 1919{ 1920 if (!value->action) 1921 return -EINVAL; 1922 if (devlink_dpipe_action_put(skb, value->action)) 1923 return -EMSGSIZE; 1924 if (devlink_dpipe_value_put(skb, value)) 1925 return -EMSGSIZE; 1926 return 0; 1927} 1928 1929static int devlink_dpipe_action_values_put(struct sk_buff *skb, 1930 struct devlink_dpipe_value *values, 1931 unsigned int values_count) 1932{ 1933 struct nlattr *action_attr; 1934 int i; 1935 int err; 1936 1937 for (i = 0; i < values_count; i++) { 1938 action_attr = nla_nest_start(skb, 1939 DEVLINK_ATTR_DPIPE_ACTION_VALUE); 1940 if (!action_attr) 1941 return -EMSGSIZE; 1942 err = devlink_dpipe_action_value_put(skb, &values[i]); 1943 if (err) 1944 goto err_action_value_put; 1945 nla_nest_end(skb, action_attr); 1946 } 1947 return 0; 1948 1949err_action_value_put: 1950 nla_nest_cancel(skb, action_attr); 1951 return err; 1952} 1953 1954static int devlink_dpipe_match_value_put(struct sk_buff *skb, 1955 struct devlink_dpipe_value *value) 1956{ 1957 if (!value->match) 1958 return -EINVAL; 1959 if (devlink_dpipe_match_put(skb, value->match)) 1960 return -EMSGSIZE; 1961 if (devlink_dpipe_value_put(skb, value)) 1962 return -EMSGSIZE; 1963 return 0; 1964} 1965 1966static int devlink_dpipe_match_values_put(struct sk_buff *skb, 1967 struct devlink_dpipe_value *values, 1968 unsigned int values_count) 1969{ 1970 struct nlattr *match_attr; 1971 int i; 1972 int err; 1973 1974 for (i = 0; i < values_count; i++) { 1975 match_attr = nla_nest_start(skb, 1976 DEVLINK_ATTR_DPIPE_MATCH_VALUE); 1977 if (!match_attr) 1978 return -EMSGSIZE; 1979 err = devlink_dpipe_match_value_put(skb, &values[i]); 1980 if (err) 1981 goto err_match_value_put; 1982 nla_nest_end(skb, match_attr); 1983 } 1984 return 0; 1985 1986err_match_value_put: 1987 nla_nest_cancel(skb, match_attr); 1988 return err; 1989} 1990 1991static int devlink_dpipe_entry_put(struct sk_buff *skb, 1992 struct devlink_dpipe_entry *entry) 1993{ 1994 struct nlattr *entry_attr, *matches_attr, *actions_attr; 1995 int err; 1996 1997 entry_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_ENTRY); 1998 if (!entry_attr) 1999 return -EMSGSIZE; 2000 2001 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_INDEX, entry->index, 2002 DEVLINK_ATTR_PAD)) 2003 goto nla_put_failure; 2004 if (entry->counter_valid) 2005 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_DPIPE_ENTRY_COUNTER, 2006 entry->counter, DEVLINK_ATTR_PAD)) 2007 goto nla_put_failure; 2008 2009 matches_attr = nla_nest_start(skb, 2010 DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES); 2011 if (!matches_attr) 2012 goto nla_put_failure; 2013 2014 err = devlink_dpipe_match_values_put(skb, entry->match_values, 2015 entry->match_values_count); 2016 if (err) { 2017 nla_nest_cancel(skb, matches_attr); 2018 goto err_match_values_put; 2019 } 2020 nla_nest_end(skb, matches_attr); 2021 2022 actions_attr = nla_nest_start(skb, 2023 DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES); 2024 if (!actions_attr) 2025 goto nla_put_failure; 2026 2027 err = devlink_dpipe_action_values_put(skb, entry->action_values, 2028 entry->action_values_count); 2029 if (err) { 2030 nla_nest_cancel(skb, actions_attr); 2031 goto err_action_values_put; 2032 } 2033 nla_nest_end(skb, actions_attr); 2034 2035 nla_nest_end(skb, entry_attr); 2036 return 0; 2037 2038nla_put_failure: 2039 err = -EMSGSIZE; 2040err_match_values_put: 2041err_action_values_put: 2042 nla_nest_cancel(skb, entry_attr); 2043 return err; 2044} 2045 2046static struct devlink_dpipe_table * 2047devlink_dpipe_table_find(struct list_head *dpipe_tables, 2048 const char *table_name) 2049{ 2050 struct devlink_dpipe_table *table; 2051 2052 list_for_each_entry_rcu(table, dpipe_tables, list) { 2053 if (!strcmp(table->name, table_name)) 2054 return table; 2055 } 2056 return NULL; 2057} 2058 2059int devlink_dpipe_entry_ctx_prepare(struct devlink_dpipe_dump_ctx *dump_ctx) 2060{ 2061 struct devlink *devlink; 2062 int err; 2063 2064 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx->skb, 2065 dump_ctx->info); 2066 if (err) 2067 return err; 2068 2069 dump_ctx->hdr = genlmsg_put(dump_ctx->skb, 2070 dump_ctx->info->snd_portid, 2071 dump_ctx->info->snd_seq, 2072 &devlink_nl_family, NLM_F_MULTI, 2073 dump_ctx->cmd); 2074 if (!dump_ctx->hdr) 2075 goto nla_put_failure; 2076 2077 devlink = dump_ctx->info->user_ptr[0]; 2078 if (devlink_nl_put_handle(dump_ctx->skb, devlink)) 2079 goto nla_put_failure; 2080 dump_ctx->nest = nla_nest_start(dump_ctx->skb, 2081 DEVLINK_ATTR_DPIPE_ENTRIES); 2082 if (!dump_ctx->nest) 2083 goto nla_put_failure; 2084 return 0; 2085 2086nla_put_failure: 2087 nlmsg_free(dump_ctx->skb); 2088 return -EMSGSIZE; 2089} 2090EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_prepare); 2091 2092int devlink_dpipe_entry_ctx_append(struct devlink_dpipe_dump_ctx *dump_ctx, 2093 struct devlink_dpipe_entry *entry) 2094{ 2095 return devlink_dpipe_entry_put(dump_ctx->skb, entry); 2096} 2097EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_append); 2098 2099int devlink_dpipe_entry_ctx_close(struct devlink_dpipe_dump_ctx *dump_ctx) 2100{ 2101 nla_nest_end(dump_ctx->skb, dump_ctx->nest); 2102 genlmsg_end(dump_ctx->skb, dump_ctx->hdr); 2103 return 0; 2104} 2105EXPORT_SYMBOL_GPL(devlink_dpipe_entry_ctx_close); 2106 2107void devlink_dpipe_entry_clear(struct devlink_dpipe_entry *entry) 2108 2109{ 2110 unsigned int value_count, value_index; 2111 struct devlink_dpipe_value *value; 2112 2113 value = entry->action_values; 2114 value_count = entry->action_values_count; 2115 for (value_index = 0; value_index < value_count; value_index++) { 2116 kfree(value[value_index].value); 2117 kfree(value[value_index].mask); 2118 } 2119 2120 value = entry->match_values; 2121 value_count = entry->match_values_count; 2122 for (value_index = 0; value_index < value_count; value_index++) { 2123 kfree(value[value_index].value); 2124 kfree(value[value_index].mask); 2125 } 2126} 2127EXPORT_SYMBOL(devlink_dpipe_entry_clear); 2128 2129static int devlink_dpipe_entries_fill(struct genl_info *info, 2130 enum devlink_command cmd, int flags, 2131 struct devlink_dpipe_table *table) 2132{ 2133 struct devlink_dpipe_dump_ctx dump_ctx; 2134 struct nlmsghdr *nlh; 2135 int err; 2136 2137 dump_ctx.skb = NULL; 2138 dump_ctx.cmd = cmd; 2139 dump_ctx.info = info; 2140 2141 err = table->table_ops->entries_dump(table->priv, 2142 table->counters_enabled, 2143 &dump_ctx); 2144 if (err) 2145 return err; 2146 2147send_done: 2148 nlh = nlmsg_put(dump_ctx.skb, info->snd_portid, info->snd_seq, 2149 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2150 if (!nlh) { 2151 err = devlink_dpipe_send_and_alloc_skb(&dump_ctx.skb, info); 2152 if (err) 2153 return err; 2154 goto send_done; 2155 } 2156 return genlmsg_reply(dump_ctx.skb, info); 2157} 2158 2159static int devlink_nl_cmd_dpipe_entries_get(struct sk_buff *skb, 2160 struct genl_info *info) 2161{ 2162 struct devlink *devlink = info->user_ptr[0]; 2163 struct devlink_dpipe_table *table; 2164 const char *table_name; 2165 2166 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]) 2167 return -EINVAL; 2168 2169 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 2170 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 2171 table_name); 2172 if (!table) 2173 return -EINVAL; 2174 2175 if (!table->table_ops->entries_dump) 2176 return -EINVAL; 2177 2178 return devlink_dpipe_entries_fill(info, DEVLINK_CMD_DPIPE_ENTRIES_GET, 2179 0, table); 2180} 2181 2182static int devlink_dpipe_fields_put(struct sk_buff *skb, 2183 const struct devlink_dpipe_header *header) 2184{ 2185 struct devlink_dpipe_field *field; 2186 struct nlattr *field_attr; 2187 int i; 2188 2189 for (i = 0; i < header->fields_count; i++) { 2190 field = &header->fields[i]; 2191 field_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_FIELD); 2192 if (!field_attr) 2193 return -EMSGSIZE; 2194 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_FIELD_NAME, field->name) || 2195 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_ID, field->id) || 2196 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, field->bitwidth) || 2197 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, field->mapping_type)) 2198 goto nla_put_failure; 2199 nla_nest_end(skb, field_attr); 2200 } 2201 return 0; 2202 2203nla_put_failure: 2204 nla_nest_cancel(skb, field_attr); 2205 return -EMSGSIZE; 2206} 2207 2208static int devlink_dpipe_header_put(struct sk_buff *skb, 2209 struct devlink_dpipe_header *header) 2210{ 2211 struct nlattr *fields_attr, *header_attr; 2212 int err; 2213 2214 header_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADER); 2215 if (!header_attr) 2216 return -EMSGSIZE; 2217 2218 if (nla_put_string(skb, DEVLINK_ATTR_DPIPE_HEADER_NAME, header->name) || 2219 nla_put_u32(skb, DEVLINK_ATTR_DPIPE_HEADER_ID, header->id) || 2220 nla_put_u8(skb, DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, header->global)) 2221 goto nla_put_failure; 2222 2223 fields_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADER_FIELDS); 2224 if (!fields_attr) 2225 goto nla_put_failure; 2226 2227 err = devlink_dpipe_fields_put(skb, header); 2228 if (err) { 2229 nla_nest_cancel(skb, fields_attr); 2230 goto nla_put_failure; 2231 } 2232 nla_nest_end(skb, fields_attr); 2233 nla_nest_end(skb, header_attr); 2234 return 0; 2235 2236nla_put_failure: 2237 err = -EMSGSIZE; 2238 nla_nest_cancel(skb, header_attr); 2239 return err; 2240} 2241 2242static int devlink_dpipe_headers_fill(struct genl_info *info, 2243 enum devlink_command cmd, int flags, 2244 struct devlink_dpipe_headers * 2245 dpipe_headers) 2246{ 2247 struct devlink *devlink = info->user_ptr[0]; 2248 struct nlattr *headers_attr; 2249 struct sk_buff *skb = NULL; 2250 struct nlmsghdr *nlh; 2251 void *hdr; 2252 int i, j; 2253 int err; 2254 2255 i = 0; 2256start_again: 2257 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2258 if (err) 2259 return err; 2260 2261 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 2262 &devlink_nl_family, NLM_F_MULTI, cmd); 2263 if (!hdr) { 2264 nlmsg_free(skb); 2265 return -EMSGSIZE; 2266 } 2267 2268 if (devlink_nl_put_handle(skb, devlink)) 2269 goto nla_put_failure; 2270 headers_attr = nla_nest_start(skb, DEVLINK_ATTR_DPIPE_HEADERS); 2271 if (!headers_attr) 2272 goto nla_put_failure; 2273 2274 j = 0; 2275 for (; i < dpipe_headers->headers_count; i++) { 2276 err = devlink_dpipe_header_put(skb, dpipe_headers->headers[i]); 2277 if (err) { 2278 if (!j) 2279 goto err_table_put; 2280 break; 2281 } 2282 j++; 2283 } 2284 nla_nest_end(skb, headers_attr); 2285 genlmsg_end(skb, hdr); 2286 if (i != dpipe_headers->headers_count) 2287 goto start_again; 2288 2289send_done: 2290 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 2291 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2292 if (!nlh) { 2293 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2294 if (err) 2295 return err; 2296 goto send_done; 2297 } 2298 return genlmsg_reply(skb, info); 2299 2300nla_put_failure: 2301 err = -EMSGSIZE; 2302err_table_put: 2303 nlmsg_free(skb); 2304 return err; 2305} 2306 2307static int devlink_nl_cmd_dpipe_headers_get(struct sk_buff *skb, 2308 struct genl_info *info) 2309{ 2310 struct devlink *devlink = info->user_ptr[0]; 2311 2312 if (!devlink->dpipe_headers) 2313 return -EOPNOTSUPP; 2314 return devlink_dpipe_headers_fill(info, DEVLINK_CMD_DPIPE_HEADERS_GET, 2315 0, devlink->dpipe_headers); 2316} 2317 2318static int devlink_dpipe_table_counters_set(struct devlink *devlink, 2319 const char *table_name, 2320 bool enable) 2321{ 2322 struct devlink_dpipe_table *table; 2323 2324 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 2325 table_name); 2326 if (!table) 2327 return -EINVAL; 2328 2329 if (table->counter_control_extern) 2330 return -EOPNOTSUPP; 2331 2332 if (!(table->counters_enabled ^ enable)) 2333 return 0; 2334 2335 table->counters_enabled = enable; 2336 if (table->table_ops->counters_set_update) 2337 table->table_ops->counters_set_update(table->priv, enable); 2338 return 0; 2339} 2340 2341static int devlink_nl_cmd_dpipe_table_counters_set(struct sk_buff *skb, 2342 struct genl_info *info) 2343{ 2344 struct devlink *devlink = info->user_ptr[0]; 2345 const char *table_name; 2346 bool counters_enable; 2347 2348 if (!info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME] || 2349 !info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]) 2350 return -EINVAL; 2351 2352 table_name = nla_data(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_NAME]); 2353 counters_enable = !!nla_get_u8(info->attrs[DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED]); 2354 2355 return devlink_dpipe_table_counters_set(devlink, table_name, 2356 counters_enable); 2357} 2358 2359static struct devlink_resource * 2360devlink_resource_find(struct devlink *devlink, 2361 struct devlink_resource *resource, u64 resource_id) 2362{ 2363 struct list_head *resource_list; 2364 2365 if (resource) 2366 resource_list = &resource->resource_list; 2367 else 2368 resource_list = &devlink->resource_list; 2369 2370 list_for_each_entry(resource, resource_list, list) { 2371 struct devlink_resource *child_resource; 2372 2373 if (resource->id == resource_id) 2374 return resource; 2375 2376 child_resource = devlink_resource_find(devlink, resource, 2377 resource_id); 2378 if (child_resource) 2379 return child_resource; 2380 } 2381 return NULL; 2382} 2383 2384static void 2385devlink_resource_validate_children(struct devlink_resource *resource) 2386{ 2387 struct devlink_resource *child_resource; 2388 bool size_valid = true; 2389 u64 parts_size = 0; 2390 2391 if (list_empty(&resource->resource_list)) 2392 goto out; 2393 2394 list_for_each_entry(child_resource, &resource->resource_list, list) 2395 parts_size += child_resource->size_new; 2396 2397 if (parts_size > resource->size_new) 2398 size_valid = false; 2399out: 2400 resource->size_valid = size_valid; 2401} 2402 2403static int 2404devlink_resource_validate_size(struct devlink_resource *resource, u64 size, 2405 struct netlink_ext_ack *extack) 2406{ 2407 u64 reminder; 2408 int err = 0; 2409 2410 if (size > resource->size_params.size_max) { 2411 NL_SET_ERR_MSG_MOD(extack, "Size larger than maximum"); 2412 err = -EINVAL; 2413 } 2414 2415 if (size < resource->size_params.size_min) { 2416 NL_SET_ERR_MSG_MOD(extack, "Size smaller than minimum"); 2417 err = -EINVAL; 2418 } 2419 2420 div64_u64_rem(size, resource->size_params.size_granularity, &reminder); 2421 if (reminder) { 2422 NL_SET_ERR_MSG_MOD(extack, "Wrong granularity"); 2423 err = -EINVAL; 2424 } 2425 2426 return err; 2427} 2428 2429static int devlink_nl_cmd_resource_set(struct sk_buff *skb, 2430 struct genl_info *info) 2431{ 2432 struct devlink *devlink = info->user_ptr[0]; 2433 struct devlink_resource *resource; 2434 u64 resource_id; 2435 u64 size; 2436 int err; 2437 2438 if (!info->attrs[DEVLINK_ATTR_RESOURCE_ID] || 2439 !info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]) 2440 return -EINVAL; 2441 resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]); 2442 2443 resource = devlink_resource_find(devlink, NULL, resource_id); 2444 if (!resource) 2445 return -EINVAL; 2446 2447 size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]); 2448 err = devlink_resource_validate_size(resource, size, info->extack); 2449 if (err) 2450 return err; 2451 2452 resource->size_new = size; 2453 devlink_resource_validate_children(resource); 2454 if (resource->parent) 2455 devlink_resource_validate_children(resource->parent); 2456 return 0; 2457} 2458 2459static int 2460devlink_resource_size_params_put(struct devlink_resource *resource, 2461 struct sk_buff *skb) 2462{ 2463 struct devlink_resource_size_params *size_params; 2464 2465 size_params = &resource->size_params; 2466 if (nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN, 2467 size_params->size_granularity, DEVLINK_ATTR_PAD) || 2468 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX, 2469 size_params->size_max, DEVLINK_ATTR_PAD) || 2470 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN, 2471 size_params->size_min, DEVLINK_ATTR_PAD) || 2472 nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit)) 2473 return -EMSGSIZE; 2474 return 0; 2475} 2476 2477static int devlink_resource_occ_put(struct devlink_resource *resource, 2478 struct sk_buff *skb) 2479{ 2480 if (!resource->occ_get) 2481 return 0; 2482 return nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_OCC, 2483 resource->occ_get(resource->occ_get_priv), 2484 DEVLINK_ATTR_PAD); 2485} 2486 2487static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb, 2488 struct devlink_resource *resource) 2489{ 2490 struct devlink_resource *child_resource; 2491 struct nlattr *child_resource_attr; 2492 struct nlattr *resource_attr; 2493 2494 resource_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE); 2495 if (!resource_attr) 2496 return -EMSGSIZE; 2497 2498 if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) || 2499 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size, 2500 DEVLINK_ATTR_PAD) || 2501 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id, 2502 DEVLINK_ATTR_PAD)) 2503 goto nla_put_failure; 2504 if (resource->size != resource->size_new) 2505 nla_put_u64_64bit(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW, 2506 resource->size_new, DEVLINK_ATTR_PAD); 2507 if (devlink_resource_occ_put(resource, skb)) 2508 goto nla_put_failure; 2509 if (devlink_resource_size_params_put(resource, skb)) 2510 goto nla_put_failure; 2511 if (list_empty(&resource->resource_list)) 2512 goto out; 2513 2514 if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID, 2515 resource->size_valid)) 2516 goto nla_put_failure; 2517 2518 child_resource_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE_LIST); 2519 if (!child_resource_attr) 2520 goto nla_put_failure; 2521 2522 list_for_each_entry(child_resource, &resource->resource_list, list) { 2523 if (devlink_resource_put(devlink, skb, child_resource)) 2524 goto resource_put_failure; 2525 } 2526 2527 nla_nest_end(skb, child_resource_attr); 2528out: 2529 nla_nest_end(skb, resource_attr); 2530 return 0; 2531 2532resource_put_failure: 2533 nla_nest_cancel(skb, child_resource_attr); 2534nla_put_failure: 2535 nla_nest_cancel(skb, resource_attr); 2536 return -EMSGSIZE; 2537} 2538 2539static int devlink_resource_fill(struct genl_info *info, 2540 enum devlink_command cmd, int flags) 2541{ 2542 struct devlink *devlink = info->user_ptr[0]; 2543 struct devlink_resource *resource; 2544 struct nlattr *resources_attr; 2545 struct sk_buff *skb = NULL; 2546 struct nlmsghdr *nlh; 2547 bool incomplete; 2548 void *hdr; 2549 int i; 2550 int err; 2551 2552 resource = list_first_entry(&devlink->resource_list, 2553 struct devlink_resource, list); 2554start_again: 2555 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2556 if (err) 2557 return err; 2558 2559 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq, 2560 &devlink_nl_family, NLM_F_MULTI, cmd); 2561 if (!hdr) { 2562 nlmsg_free(skb); 2563 return -EMSGSIZE; 2564 } 2565 2566 if (devlink_nl_put_handle(skb, devlink)) 2567 goto nla_put_failure; 2568 2569 resources_attr = nla_nest_start(skb, DEVLINK_ATTR_RESOURCE_LIST); 2570 if (!resources_attr) 2571 goto nla_put_failure; 2572 2573 incomplete = false; 2574 i = 0; 2575 list_for_each_entry_from(resource, &devlink->resource_list, list) { 2576 err = devlink_resource_put(devlink, skb, resource); 2577 if (err) { 2578 if (!i) 2579 goto err_resource_put; 2580 incomplete = true; 2581 break; 2582 } 2583 i++; 2584 } 2585 nla_nest_end(skb, resources_attr); 2586 genlmsg_end(skb, hdr); 2587 if (incomplete) 2588 goto start_again; 2589send_done: 2590 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq, 2591 NLMSG_DONE, 0, flags | NLM_F_MULTI); 2592 if (!nlh) { 2593 err = devlink_dpipe_send_and_alloc_skb(&skb, info); 2594 if (err) 2595 return err; 2596 goto send_done; 2597 } 2598 return genlmsg_reply(skb, info); 2599 2600nla_put_failure: 2601 err = -EMSGSIZE; 2602err_resource_put: 2603 nlmsg_free(skb); 2604 return err; 2605} 2606 2607static int devlink_nl_cmd_resource_dump(struct sk_buff *skb, 2608 struct genl_info *info) 2609{ 2610 struct devlink *devlink = info->user_ptr[0]; 2611 2612 if (list_empty(&devlink->resource_list)) 2613 return -EOPNOTSUPP; 2614 2615 return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0); 2616} 2617 2618static int 2619devlink_resources_validate(struct devlink *devlink, 2620 struct devlink_resource *resource, 2621 struct genl_info *info) 2622{ 2623 struct list_head *resource_list; 2624 int err = 0; 2625 2626 if (resource) 2627 resource_list = &resource->resource_list; 2628 else 2629 resource_list = &devlink->resource_list; 2630 2631 list_for_each_entry(resource, resource_list, list) { 2632 if (!resource->size_valid) 2633 return -EINVAL; 2634 err = devlink_resources_validate(devlink, resource, info); 2635 if (err) 2636 return err; 2637 } 2638 return err; 2639} 2640 2641static int devlink_nl_cmd_reload(struct sk_buff *skb, struct genl_info *info) 2642{ 2643 struct devlink *devlink = info->user_ptr[0]; 2644 int err; 2645 2646 if (!devlink->ops->reload) 2647 return -EOPNOTSUPP; 2648 2649 err = devlink_resources_validate(devlink, NULL, info); 2650 if (err) { 2651 NL_SET_ERR_MSG_MOD(info->extack, "resources size validation failed"); 2652 return err; 2653 } 2654 return devlink->ops->reload(devlink, info->extack); 2655} 2656 2657static const struct devlink_param devlink_param_generic[] = { 2658 { 2659 .id = DEVLINK_PARAM_GENERIC_ID_INT_ERR_RESET, 2660 .name = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_NAME, 2661 .type = DEVLINK_PARAM_GENERIC_INT_ERR_RESET_TYPE, 2662 }, 2663 { 2664 .id = DEVLINK_PARAM_GENERIC_ID_MAX_MACS, 2665 .name = DEVLINK_PARAM_GENERIC_MAX_MACS_NAME, 2666 .type = DEVLINK_PARAM_GENERIC_MAX_MACS_TYPE, 2667 }, 2668 { 2669 .id = DEVLINK_PARAM_GENERIC_ID_ENABLE_SRIOV, 2670 .name = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_NAME, 2671 .type = DEVLINK_PARAM_GENERIC_ENABLE_SRIOV_TYPE, 2672 }, 2673 { 2674 .id = DEVLINK_PARAM_GENERIC_ID_REGION_SNAPSHOT, 2675 .name = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_NAME, 2676 .type = DEVLINK_PARAM_GENERIC_REGION_SNAPSHOT_TYPE, 2677 }, 2678}; 2679 2680static int devlink_param_generic_verify(const struct devlink_param *param) 2681{ 2682 /* verify it match generic parameter by id and name */ 2683 if (param->id > DEVLINK_PARAM_GENERIC_ID_MAX) 2684 return -EINVAL; 2685 if (strcmp(param->name, devlink_param_generic[param->id].name)) 2686 return -ENOENT; 2687 2688 WARN_ON(param->type != devlink_param_generic[param->id].type); 2689 2690 return 0; 2691} 2692 2693static int devlink_param_driver_verify(const struct devlink_param *param) 2694{ 2695 int i; 2696 2697 if (param->id <= DEVLINK_PARAM_GENERIC_ID_MAX) 2698 return -EINVAL; 2699 /* verify no such name in generic params */ 2700 for (i = 0; i <= DEVLINK_PARAM_GENERIC_ID_MAX; i++) 2701 if (!strcmp(param->name, devlink_param_generic[i].name)) 2702 return -EEXIST; 2703 2704 return 0; 2705} 2706 2707static struct devlink_param_item * 2708devlink_param_find_by_name(struct list_head *param_list, 2709 const char *param_name) 2710{ 2711 struct devlink_param_item *param_item; 2712 2713 list_for_each_entry(param_item, param_list, list) 2714 if (!strcmp(param_item->param->name, param_name)) 2715 return param_item; 2716 return NULL; 2717} 2718 2719static struct devlink_param_item * 2720devlink_param_find_by_id(struct list_head *param_list, u32 param_id) 2721{ 2722 struct devlink_param_item *param_item; 2723 2724 list_for_each_entry(param_item, param_list, list) 2725 if (param_item->param->id == param_id) 2726 return param_item; 2727 return NULL; 2728} 2729 2730static bool 2731devlink_param_cmode_is_supported(const struct devlink_param *param, 2732 enum devlink_param_cmode cmode) 2733{ 2734 return test_bit(cmode, &param->supported_cmodes); 2735} 2736 2737static int devlink_param_get(struct devlink *devlink, 2738 const struct devlink_param *param, 2739 struct devlink_param_gset_ctx *ctx) 2740{ 2741 if (!param->get) 2742 return -EOPNOTSUPP; 2743 return param->get(devlink, param->id, ctx); 2744} 2745 2746static int devlink_param_set(struct devlink *devlink, 2747 const struct devlink_param *param, 2748 struct devlink_param_gset_ctx *ctx) 2749{ 2750 if (!param->set) 2751 return -EOPNOTSUPP; 2752 return param->set(devlink, param->id, ctx); 2753} 2754 2755static int 2756devlink_param_type_to_nla_type(enum devlink_param_type param_type) 2757{ 2758 switch (param_type) { 2759 case DEVLINK_PARAM_TYPE_U8: 2760 return NLA_U8; 2761 case DEVLINK_PARAM_TYPE_U16: 2762 return NLA_U16; 2763 case DEVLINK_PARAM_TYPE_U32: 2764 return NLA_U32; 2765 case DEVLINK_PARAM_TYPE_STRING: 2766 return NLA_STRING; 2767 case DEVLINK_PARAM_TYPE_BOOL: 2768 return NLA_FLAG; 2769 default: 2770 return -EINVAL; 2771 } 2772} 2773 2774static int 2775devlink_nl_param_value_fill_one(struct sk_buff *msg, 2776 enum devlink_param_type type, 2777 enum devlink_param_cmode cmode, 2778 union devlink_param_value val) 2779{ 2780 struct nlattr *param_value_attr; 2781 2782 param_value_attr = nla_nest_start(msg, DEVLINK_ATTR_PARAM_VALUE); 2783 if (!param_value_attr) 2784 goto nla_put_failure; 2785 2786 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_CMODE, cmode)) 2787 goto value_nest_cancel; 2788 2789 switch (type) { 2790 case DEVLINK_PARAM_TYPE_U8: 2791 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu8)) 2792 goto value_nest_cancel; 2793 break; 2794 case DEVLINK_PARAM_TYPE_U16: 2795 if (nla_put_u16(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu16)) 2796 goto value_nest_cancel; 2797 break; 2798 case DEVLINK_PARAM_TYPE_U32: 2799 if (nla_put_u32(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, val.vu32)) 2800 goto value_nest_cancel; 2801 break; 2802 case DEVLINK_PARAM_TYPE_STRING: 2803 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_VALUE_DATA, 2804 val.vstr)) 2805 goto value_nest_cancel; 2806 break; 2807 case DEVLINK_PARAM_TYPE_BOOL: 2808 if (val.vbool && 2809 nla_put_flag(msg, DEVLINK_ATTR_PARAM_VALUE_DATA)) 2810 goto value_nest_cancel; 2811 break; 2812 } 2813 2814 nla_nest_end(msg, param_value_attr); 2815 return 0; 2816 2817value_nest_cancel: 2818 nla_nest_cancel(msg, param_value_attr); 2819nla_put_failure: 2820 return -EMSGSIZE; 2821} 2822 2823static int devlink_nl_param_fill(struct sk_buff *msg, struct devlink *devlink, 2824 struct devlink_param_item *param_item, 2825 enum devlink_command cmd, 2826 u32 portid, u32 seq, int flags) 2827{ 2828 union devlink_param_value param_value[DEVLINK_PARAM_CMODE_MAX + 1]; 2829 const struct devlink_param *param = param_item->param; 2830 struct devlink_param_gset_ctx ctx; 2831 struct nlattr *param_values_list; 2832 struct nlattr *param_attr; 2833 int nla_type; 2834 void *hdr; 2835 int err; 2836 int i; 2837 2838 /* Get value from driver part to driverinit configuration mode */ 2839 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 2840 if (!devlink_param_cmode_is_supported(param, i)) 2841 continue; 2842 if (i == DEVLINK_PARAM_CMODE_DRIVERINIT) { 2843 if (!param_item->driverinit_value_valid) 2844 return -EOPNOTSUPP; 2845 param_value[i] = param_item->driverinit_value; 2846 } else { 2847 ctx.cmode = i; 2848 err = devlink_param_get(devlink, param, &ctx); 2849 if (err) 2850 return err; 2851 param_value[i] = ctx.val; 2852 } 2853 } 2854 2855 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 2856 if (!hdr) 2857 return -EMSGSIZE; 2858 2859 if (devlink_nl_put_handle(msg, devlink)) 2860 goto genlmsg_cancel; 2861 param_attr = nla_nest_start(msg, DEVLINK_ATTR_PARAM); 2862 if (!param_attr) 2863 goto genlmsg_cancel; 2864 if (nla_put_string(msg, DEVLINK_ATTR_PARAM_NAME, param->name)) 2865 goto param_nest_cancel; 2866 if (param->generic && nla_put_flag(msg, DEVLINK_ATTR_PARAM_GENERIC)) 2867 goto param_nest_cancel; 2868 2869 nla_type = devlink_param_type_to_nla_type(param->type); 2870 if (nla_type < 0) 2871 goto param_nest_cancel; 2872 if (nla_put_u8(msg, DEVLINK_ATTR_PARAM_TYPE, nla_type)) 2873 goto param_nest_cancel; 2874 2875 param_values_list = nla_nest_start(msg, DEVLINK_ATTR_PARAM_VALUES_LIST); 2876 if (!param_values_list) 2877 goto param_nest_cancel; 2878 2879 for (i = 0; i <= DEVLINK_PARAM_CMODE_MAX; i++) { 2880 if (!devlink_param_cmode_is_supported(param, i)) 2881 continue; 2882 err = devlink_nl_param_value_fill_one(msg, param->type, 2883 i, param_value[i]); 2884 if (err) 2885 goto values_list_nest_cancel; 2886 } 2887 2888 nla_nest_end(msg, param_values_list); 2889 nla_nest_end(msg, param_attr); 2890 genlmsg_end(msg, hdr); 2891 return 0; 2892 2893values_list_nest_cancel: 2894 nla_nest_end(msg, param_values_list); 2895param_nest_cancel: 2896 nla_nest_cancel(msg, param_attr); 2897genlmsg_cancel: 2898 genlmsg_cancel(msg, hdr); 2899 return -EMSGSIZE; 2900} 2901 2902static void devlink_param_notify(struct devlink *devlink, 2903 struct devlink_param_item *param_item, 2904 enum devlink_command cmd) 2905{ 2906 struct sk_buff *msg; 2907 int err; 2908 2909 WARN_ON(cmd != DEVLINK_CMD_PARAM_NEW && cmd != DEVLINK_CMD_PARAM_DEL); 2910 2911 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 2912 if (!msg) 2913 return; 2914 err = devlink_nl_param_fill(msg, devlink, param_item, cmd, 0, 0, 0); 2915 if (err) { 2916 nlmsg_free(msg); 2917 return; 2918 } 2919 2920 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 2921 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 2922} 2923 2924static int devlink_nl_cmd_param_get_dumpit(struct sk_buff *msg, 2925 struct netlink_callback *cb) 2926{ 2927 struct devlink_param_item *param_item; 2928 struct devlink *devlink; 2929 int start = cb->args[0]; 2930 int idx = 0; 2931 int err; 2932 2933 mutex_lock(&devlink_mutex); 2934 list_for_each_entry(devlink, &devlink_list, list) { 2935 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 2936 continue; 2937 mutex_lock(&devlink->lock); 2938 list_for_each_entry(param_item, &devlink->param_list, list) { 2939 if (idx < start) { 2940 idx++; 2941 continue; 2942 } 2943 err = devlink_nl_param_fill(msg, devlink, param_item, 2944 DEVLINK_CMD_PARAM_GET, 2945 NETLINK_CB(cb->skb).portid, 2946 cb->nlh->nlmsg_seq, 2947 NLM_F_MULTI); 2948 if (err) { 2949 mutex_unlock(&devlink->lock); 2950 goto out; 2951 } 2952 idx++; 2953 } 2954 mutex_unlock(&devlink->lock); 2955 } 2956out: 2957 mutex_unlock(&devlink_mutex); 2958 2959 cb->args[0] = idx; 2960 return msg->len; 2961} 2962 2963static int 2964devlink_param_type_get_from_info(struct genl_info *info, 2965 enum devlink_param_type *param_type) 2966{ 2967 if (!info->attrs[DEVLINK_ATTR_PARAM_TYPE]) 2968 return -EINVAL; 2969 2970 switch (nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_TYPE])) { 2971 case NLA_U8: 2972 *param_type = DEVLINK_PARAM_TYPE_U8; 2973 break; 2974 case NLA_U16: 2975 *param_type = DEVLINK_PARAM_TYPE_U16; 2976 break; 2977 case NLA_U32: 2978 *param_type = DEVLINK_PARAM_TYPE_U32; 2979 break; 2980 case NLA_STRING: 2981 *param_type = DEVLINK_PARAM_TYPE_STRING; 2982 break; 2983 case NLA_FLAG: 2984 *param_type = DEVLINK_PARAM_TYPE_BOOL; 2985 break; 2986 default: 2987 return -EINVAL; 2988 } 2989 2990 return 0; 2991} 2992 2993static int 2994devlink_param_value_get_from_info(const struct devlink_param *param, 2995 struct genl_info *info, 2996 union devlink_param_value *value) 2997{ 2998 if (param->type != DEVLINK_PARAM_TYPE_BOOL && 2999 !info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) 3000 return -EINVAL; 3001 3002 switch (param->type) { 3003 case DEVLINK_PARAM_TYPE_U8: 3004 value->vu8 = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3005 break; 3006 case DEVLINK_PARAM_TYPE_U16: 3007 value->vu16 = nla_get_u16(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3008 break; 3009 case DEVLINK_PARAM_TYPE_U32: 3010 value->vu32 = nla_get_u32(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3011 break; 3012 case DEVLINK_PARAM_TYPE_STRING: 3013 if (nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) > 3014 DEVLINK_PARAM_MAX_STRING_VALUE) 3015 return -EINVAL; 3016 value->vstr = nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3017 break; 3018 case DEVLINK_PARAM_TYPE_BOOL: 3019 value->vbool = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA] ? 3020 true : false; 3021 break; 3022 } 3023 return 0; 3024} 3025 3026static struct devlink_param_item * 3027devlink_param_get_from_info(struct devlink *devlink, 3028 struct genl_info *info) 3029{ 3030 char *param_name; 3031 3032 if (!info->attrs[DEVLINK_ATTR_PARAM_NAME]) 3033 return NULL; 3034 3035 param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]); 3036 return devlink_param_find_by_name(&devlink->param_list, param_name); 3037} 3038 3039static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb, 3040 struct genl_info *info) 3041{ 3042 struct devlink *devlink = info->user_ptr[0]; 3043 struct devlink_param_item *param_item; 3044 struct sk_buff *msg; 3045 int err; 3046 3047 param_item = devlink_param_get_from_info(devlink, info); 3048 if (!param_item) 3049 return -EINVAL; 3050 3051 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3052 if (!msg) 3053 return -ENOMEM; 3054 3055 err = devlink_nl_param_fill(msg, devlink, param_item, 3056 DEVLINK_CMD_PARAM_GET, 3057 info->snd_portid, info->snd_seq, 0); 3058 if (err) { 3059 nlmsg_free(msg); 3060 return err; 3061 } 3062 3063 return genlmsg_reply(msg, info); 3064} 3065 3066static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb, 3067 struct genl_info *info) 3068{ 3069 struct devlink *devlink = info->user_ptr[0]; 3070 enum devlink_param_type param_type; 3071 struct devlink_param_gset_ctx ctx; 3072 enum devlink_param_cmode cmode; 3073 struct devlink_param_item *param_item; 3074 const struct devlink_param *param; 3075 union devlink_param_value value; 3076 int err = 0; 3077 3078 param_item = devlink_param_get_from_info(devlink, info); 3079 if (!param_item) 3080 return -EINVAL; 3081 param = param_item->param; 3082 err = devlink_param_type_get_from_info(info, &param_type); 3083 if (err) 3084 return err; 3085 if (param_type != param->type) 3086 return -EINVAL; 3087 err = devlink_param_value_get_from_info(param, info, &value); 3088 if (err) 3089 return err; 3090 if (param->validate) { 3091 err = param->validate(devlink, param->id, value, info->extack); 3092 if (err) 3093 return err; 3094 } 3095 3096 if (!info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]) 3097 return -EINVAL; 3098 cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]); 3099 if (!devlink_param_cmode_is_supported(param, cmode)) 3100 return -EOPNOTSUPP; 3101 3102 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) { 3103 param_item->driverinit_value = value; 3104 param_item->driverinit_value_valid = true; 3105 } else { 3106 if (!param->set) 3107 return -EOPNOTSUPP; 3108 ctx.val = value; 3109 ctx.cmode = cmode; 3110 err = devlink_param_set(devlink, param, &ctx); 3111 if (err) 3112 return err; 3113 } 3114 3115 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW); 3116 return 0; 3117} 3118 3119static int devlink_param_register_one(struct devlink *devlink, 3120 const struct devlink_param *param) 3121{ 3122 struct devlink_param_item *param_item; 3123 3124 if (devlink_param_find_by_name(&devlink->param_list, 3125 param->name)) 3126 return -EEXIST; 3127 3128 if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT)) 3129 WARN_ON(param->get || param->set); 3130 else 3131 WARN_ON(!param->get || !param->set); 3132 3133 param_item = kzalloc(sizeof(*param_item), GFP_KERNEL); 3134 if (!param_item) 3135 return -ENOMEM; 3136 param_item->param = param; 3137 3138 list_add_tail(&param_item->list, &devlink->param_list); 3139 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW); 3140 return 0; 3141} 3142 3143static void devlink_param_unregister_one(struct devlink *devlink, 3144 const struct devlink_param *param) 3145{ 3146 struct devlink_param_item *param_item; 3147 3148 param_item = devlink_param_find_by_name(&devlink->param_list, 3149 param->name); 3150 WARN_ON(!param_item); 3151 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_DEL); 3152 list_del(&param_item->list); 3153 kfree(param_item); 3154} 3155 3156static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg, 3157 struct devlink *devlink, 3158 struct devlink_snapshot *snapshot) 3159{ 3160 struct nlattr *snap_attr; 3161 int err; 3162 3163 snap_attr = nla_nest_start(msg, DEVLINK_ATTR_REGION_SNAPSHOT); 3164 if (!snap_attr) 3165 return -EINVAL; 3166 3167 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id); 3168 if (err) 3169 goto nla_put_failure; 3170 3171 nla_nest_end(msg, snap_attr); 3172 return 0; 3173 3174nla_put_failure: 3175 nla_nest_cancel(msg, snap_attr); 3176 return err; 3177} 3178 3179static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg, 3180 struct devlink *devlink, 3181 struct devlink_region *region) 3182{ 3183 struct devlink_snapshot *snapshot; 3184 struct nlattr *snapshots_attr; 3185 int err; 3186 3187 snapshots_attr = nla_nest_start(msg, DEVLINK_ATTR_REGION_SNAPSHOTS); 3188 if (!snapshots_attr) 3189 return -EINVAL; 3190 3191 list_for_each_entry(snapshot, &region->snapshot_list, list) { 3192 err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot); 3193 if (err) 3194 goto nla_put_failure; 3195 } 3196 3197 nla_nest_end(msg, snapshots_attr); 3198 return 0; 3199 3200nla_put_failure: 3201 nla_nest_cancel(msg, snapshots_attr); 3202 return err; 3203} 3204 3205static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink, 3206 enum devlink_command cmd, u32 portid, 3207 u32 seq, int flags, 3208 struct devlink_region *region) 3209{ 3210 void *hdr; 3211 int err; 3212 3213 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 3214 if (!hdr) 3215 return -EMSGSIZE; 3216 3217 err = devlink_nl_put_handle(msg, devlink); 3218 if (err) 3219 goto nla_put_failure; 3220 3221 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->name); 3222 if (err) 3223 goto nla_put_failure; 3224 3225 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE, 3226 region->size, 3227 DEVLINK_ATTR_PAD); 3228 if (err) 3229 goto nla_put_failure; 3230 3231 err = devlink_nl_region_snapshots_id_put(msg, devlink, region); 3232 if (err) 3233 goto nla_put_failure; 3234 3235 genlmsg_end(msg, hdr); 3236 return 0; 3237 3238nla_put_failure: 3239 genlmsg_cancel(msg, hdr); 3240 return err; 3241} 3242 3243static void devlink_nl_region_notify(struct devlink_region *region, 3244 struct devlink_snapshot *snapshot, 3245 enum devlink_command cmd) 3246{ 3247 struct devlink *devlink = region->devlink; 3248 struct sk_buff *msg; 3249 void *hdr; 3250 int err; 3251 3252 WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL); 3253 3254 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3255 if (!msg) 3256 return; 3257 3258 hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd); 3259 if (!hdr) 3260 goto out_free_msg; 3261 3262 err = devlink_nl_put_handle(msg, devlink); 3263 if (err) 3264 goto out_cancel_msg; 3265 3266 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, 3267 region->name); 3268 if (err) 3269 goto out_cancel_msg; 3270 3271 if (snapshot) { 3272 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, 3273 snapshot->id); 3274 if (err) 3275 goto out_cancel_msg; 3276 } else { 3277 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE, 3278 region->size, DEVLINK_ATTR_PAD); 3279 if (err) 3280 goto out_cancel_msg; 3281 } 3282 genlmsg_end(msg, hdr); 3283 3284 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 3285 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 3286 3287 return; 3288 3289out_cancel_msg: 3290 genlmsg_cancel(msg, hdr); 3291out_free_msg: 3292 nlmsg_free(msg); 3293} 3294 3295static int devlink_nl_cmd_region_get_doit(struct sk_buff *skb, 3296 struct genl_info *info) 3297{ 3298 struct devlink *devlink = info->user_ptr[0]; 3299 struct devlink_region *region; 3300 const char *region_name; 3301 struct sk_buff *msg; 3302 int err; 3303 3304 if (!info->attrs[DEVLINK_ATTR_REGION_NAME]) 3305 return -EINVAL; 3306 3307 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 3308 region = devlink_region_get_by_name(devlink, region_name); 3309 if (!region) 3310 return -EINVAL; 3311 3312 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3313 if (!msg) 3314 return -ENOMEM; 3315 3316 err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET, 3317 info->snd_portid, info->snd_seq, 0, 3318 region); 3319 if (err) { 3320 nlmsg_free(msg); 3321 return err; 3322 } 3323 3324 return genlmsg_reply(msg, info); 3325} 3326 3327static int devlink_nl_cmd_region_get_dumpit(struct sk_buff *msg, 3328 struct netlink_callback *cb) 3329{ 3330 struct devlink_region *region; 3331 struct devlink *devlink; 3332 int start = cb->args[0]; 3333 int idx = 0; 3334 int err; 3335 3336 mutex_lock(&devlink_mutex); 3337 list_for_each_entry(devlink, &devlink_list, list) { 3338 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 3339 continue; 3340 3341 mutex_lock(&devlink->lock); 3342 list_for_each_entry(region, &devlink->region_list, list) { 3343 if (idx < start) { 3344 idx++; 3345 continue; 3346 } 3347 err = devlink_nl_region_fill(msg, devlink, 3348 DEVLINK_CMD_REGION_GET, 3349 NETLINK_CB(cb->skb).portid, 3350 cb->nlh->nlmsg_seq, 3351 NLM_F_MULTI, region); 3352 if (err) { 3353 mutex_unlock(&devlink->lock); 3354 goto out; 3355 } 3356 idx++; 3357 } 3358 mutex_unlock(&devlink->lock); 3359 } 3360out: 3361 mutex_unlock(&devlink_mutex); 3362 cb->args[0] = idx; 3363 return msg->len; 3364} 3365 3366static int devlink_nl_cmd_region_del(struct sk_buff *skb, 3367 struct genl_info *info) 3368{ 3369 struct devlink *devlink = info->user_ptr[0]; 3370 struct devlink_snapshot *snapshot; 3371 struct devlink_region *region; 3372 const char *region_name; 3373 u32 snapshot_id; 3374 3375 if (!info->attrs[DEVLINK_ATTR_REGION_NAME] || 3376 !info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) 3377 return -EINVAL; 3378 3379 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 3380 snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); 3381 3382 region = devlink_region_get_by_name(devlink, region_name); 3383 if (!region) 3384 return -EINVAL; 3385 3386 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); 3387 if (!snapshot) 3388 return -EINVAL; 3389 3390 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL); 3391 devlink_region_snapshot_del(snapshot); 3392 return 0; 3393} 3394 3395static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg, 3396 struct devlink *devlink, 3397 u8 *chunk, u32 chunk_size, 3398 u64 addr) 3399{ 3400 struct nlattr *chunk_attr; 3401 int err; 3402 3403 chunk_attr = nla_nest_start(msg, DEVLINK_ATTR_REGION_CHUNK); 3404 if (!chunk_attr) 3405 return -EINVAL; 3406 3407 err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk); 3408 if (err) 3409 goto nla_put_failure; 3410 3411 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr, 3412 DEVLINK_ATTR_PAD); 3413 if (err) 3414 goto nla_put_failure; 3415 3416 nla_nest_end(msg, chunk_attr); 3417 return 0; 3418 3419nla_put_failure: 3420 nla_nest_cancel(msg, chunk_attr); 3421 return err; 3422} 3423 3424#define DEVLINK_REGION_READ_CHUNK_SIZE 256 3425 3426static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb, 3427 struct devlink *devlink, 3428 struct devlink_region *region, 3429 struct nlattr **attrs, 3430 u64 start_offset, 3431 u64 end_offset, 3432 bool dump, 3433 u64 *new_offset) 3434{ 3435 struct devlink_snapshot *snapshot; 3436 u64 curr_offset = start_offset; 3437 u32 snapshot_id; 3438 int err = 0; 3439 3440 *new_offset = start_offset; 3441 3442 snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); 3443 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); 3444 if (!snapshot) 3445 return -EINVAL; 3446 3447 if (end_offset > snapshot->data_len || dump) 3448 end_offset = snapshot->data_len; 3449 3450 while (curr_offset < end_offset) { 3451 u32 data_size; 3452 u8 *data; 3453 3454 if (end_offset - curr_offset < DEVLINK_REGION_READ_CHUNK_SIZE) 3455 data_size = end_offset - curr_offset; 3456 else 3457 data_size = DEVLINK_REGION_READ_CHUNK_SIZE; 3458 3459 data = &snapshot->data[curr_offset]; 3460 err = devlink_nl_cmd_region_read_chunk_fill(skb, devlink, 3461 data, data_size, 3462 curr_offset); 3463 if (err) 3464 break; 3465 3466 curr_offset += data_size; 3467 } 3468 *new_offset = curr_offset; 3469 3470 return err; 3471} 3472 3473static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, 3474 struct netlink_callback *cb) 3475{ 3476 u64 ret_offset, start_offset, end_offset = 0; 3477 struct nlattr *attrs[DEVLINK_ATTR_MAX + 1]; 3478 const struct genl_ops *ops = cb->data; 3479 struct devlink_region *region; 3480 struct nlattr *chunks_attr; 3481 const char *region_name; 3482 struct devlink *devlink; 3483 bool dump = true; 3484 void *hdr; 3485 int err; 3486 3487 start_offset = *((u64 *)&cb->args[0]); 3488 3489 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + devlink_nl_family.hdrsize, 3490 attrs, DEVLINK_ATTR_MAX, ops->policy, NULL); 3491 if (err) 3492 goto out; 3493 3494 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs); 3495 if (IS_ERR(devlink)) 3496 goto out; 3497 3498 mutex_lock(&devlink_mutex); 3499 mutex_lock(&devlink->lock); 3500 3501 if (!attrs[DEVLINK_ATTR_REGION_NAME] || 3502 !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) 3503 goto out_unlock; 3504 3505 region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]); 3506 region = devlink_region_get_by_name(devlink, region_name); 3507 if (!region) 3508 goto out_unlock; 3509 3510 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 3511 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, 3512 DEVLINK_CMD_REGION_READ); 3513 if (!hdr) 3514 goto out_unlock; 3515 3516 err = devlink_nl_put_handle(skb, devlink); 3517 if (err) 3518 goto nla_put_failure; 3519 3520 err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name); 3521 if (err) 3522 goto nla_put_failure; 3523 3524 chunks_attr = nla_nest_start(skb, DEVLINK_ATTR_REGION_CHUNKS); 3525 if (!chunks_attr) 3526 goto nla_put_failure; 3527 3528 if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] && 3529 attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) { 3530 if (!start_offset) 3531 start_offset = 3532 nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); 3533 3534 end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); 3535 end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]); 3536 dump = false; 3537 } 3538 3539 err = devlink_nl_region_read_snapshot_fill(skb, devlink, 3540 region, attrs, 3541 start_offset, 3542 end_offset, dump, 3543 &ret_offset); 3544 3545 if (err && err != -EMSGSIZE) 3546 goto nla_put_failure; 3547 3548 /* Check if there was any progress done to prevent infinite loop */ 3549 if (ret_offset == start_offset) 3550 goto nla_put_failure; 3551 3552 *((u64 *)&cb->args[0]) = ret_offset; 3553 3554 nla_nest_end(skb, chunks_attr); 3555 genlmsg_end(skb, hdr); 3556 mutex_unlock(&devlink->lock); 3557 mutex_unlock(&devlink_mutex); 3558 3559 return skb->len; 3560 3561nla_put_failure: 3562 genlmsg_cancel(skb, hdr); 3563out_unlock: 3564 mutex_unlock(&devlink->lock); 3565 mutex_unlock(&devlink_mutex); 3566out: 3567 return 0; 3568} 3569 3570static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { 3571 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING }, 3572 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING }, 3573 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 }, 3574 [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 }, 3575 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 }, 3576 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 }, 3577 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 }, 3578 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 }, 3579 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 }, 3580 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 }, 3581 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 }, 3582 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 }, 3583 [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 }, 3584 [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 }, 3585 [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 }, 3586 [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING }, 3587 [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 }, 3588 [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64}, 3589 [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64}, 3590 [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING }, 3591 [DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 }, 3592 [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 }, 3593 [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING }, 3594 [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 }, 3595}; 3596 3597static const struct genl_ops devlink_nl_ops[] = { 3598 { 3599 .cmd = DEVLINK_CMD_GET, 3600 .doit = devlink_nl_cmd_get_doit, 3601 .dumpit = devlink_nl_cmd_get_dumpit, 3602 .policy = devlink_nl_policy, 3603 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3604 /* can be retrieved by unprivileged users */ 3605 }, 3606 { 3607 .cmd = DEVLINK_CMD_PORT_GET, 3608 .doit = devlink_nl_cmd_port_get_doit, 3609 .dumpit = devlink_nl_cmd_port_get_dumpit, 3610 .policy = devlink_nl_policy, 3611 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 3612 /* can be retrieved by unprivileged users */ 3613 }, 3614 { 3615 .cmd = DEVLINK_CMD_PORT_SET, 3616 .doit = devlink_nl_cmd_port_set_doit, 3617 .policy = devlink_nl_policy, 3618 .flags = GENL_ADMIN_PERM, 3619 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 3620 }, 3621 { 3622 .cmd = DEVLINK_CMD_PORT_SPLIT, 3623 .doit = devlink_nl_cmd_port_split_doit, 3624 .policy = devlink_nl_policy, 3625 .flags = GENL_ADMIN_PERM, 3626 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3627 DEVLINK_NL_FLAG_NO_LOCK, 3628 }, 3629 { 3630 .cmd = DEVLINK_CMD_PORT_UNSPLIT, 3631 .doit = devlink_nl_cmd_port_unsplit_doit, 3632 .policy = devlink_nl_policy, 3633 .flags = GENL_ADMIN_PERM, 3634 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3635 DEVLINK_NL_FLAG_NO_LOCK, 3636 }, 3637 { 3638 .cmd = DEVLINK_CMD_SB_GET, 3639 .doit = devlink_nl_cmd_sb_get_doit, 3640 .dumpit = devlink_nl_cmd_sb_get_dumpit, 3641 .policy = devlink_nl_policy, 3642 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3643 DEVLINK_NL_FLAG_NEED_SB, 3644 /* can be retrieved by unprivileged users */ 3645 }, 3646 { 3647 .cmd = DEVLINK_CMD_SB_POOL_GET, 3648 .doit = devlink_nl_cmd_sb_pool_get_doit, 3649 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit, 3650 .policy = devlink_nl_policy, 3651 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3652 DEVLINK_NL_FLAG_NEED_SB, 3653 /* can be retrieved by unprivileged users */ 3654 }, 3655 { 3656 .cmd = DEVLINK_CMD_SB_POOL_SET, 3657 .doit = devlink_nl_cmd_sb_pool_set_doit, 3658 .policy = devlink_nl_policy, 3659 .flags = GENL_ADMIN_PERM, 3660 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3661 DEVLINK_NL_FLAG_NEED_SB, 3662 }, 3663 { 3664 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET, 3665 .doit = devlink_nl_cmd_sb_port_pool_get_doit, 3666 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit, 3667 .policy = devlink_nl_policy, 3668 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 3669 DEVLINK_NL_FLAG_NEED_SB, 3670 /* can be retrieved by unprivileged users */ 3671 }, 3672 { 3673 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET, 3674 .doit = devlink_nl_cmd_sb_port_pool_set_doit, 3675 .policy = devlink_nl_policy, 3676 .flags = GENL_ADMIN_PERM, 3677 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 3678 DEVLINK_NL_FLAG_NEED_SB, 3679 }, 3680 { 3681 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET, 3682 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit, 3683 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit, 3684 .policy = devlink_nl_policy, 3685 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 3686 DEVLINK_NL_FLAG_NEED_SB, 3687 /* can be retrieved by unprivileged users */ 3688 }, 3689 { 3690 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET, 3691 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit, 3692 .policy = devlink_nl_policy, 3693 .flags = GENL_ADMIN_PERM, 3694 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 3695 DEVLINK_NL_FLAG_NEED_SB, 3696 }, 3697 { 3698 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT, 3699 .doit = devlink_nl_cmd_sb_occ_snapshot_doit, 3700 .policy = devlink_nl_policy, 3701 .flags = GENL_ADMIN_PERM, 3702 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3703 DEVLINK_NL_FLAG_NEED_SB, 3704 }, 3705 { 3706 .cmd = DEVLINK_CMD_SB_OCC_MAX_CLEAR, 3707 .doit = devlink_nl_cmd_sb_occ_max_clear_doit, 3708 .policy = devlink_nl_policy, 3709 .flags = GENL_ADMIN_PERM, 3710 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3711 DEVLINK_NL_FLAG_NEED_SB, 3712 }, 3713 { 3714 .cmd = DEVLINK_CMD_ESWITCH_GET, 3715 .doit = devlink_nl_cmd_eswitch_get_doit, 3716 .policy = devlink_nl_policy, 3717 .flags = GENL_ADMIN_PERM, 3718 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3719 }, 3720 { 3721 .cmd = DEVLINK_CMD_ESWITCH_SET, 3722 .doit = devlink_nl_cmd_eswitch_set_doit, 3723 .policy = devlink_nl_policy, 3724 .flags = GENL_ADMIN_PERM, 3725 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3726 DEVLINK_NL_FLAG_NO_LOCK, 3727 }, 3728 { 3729 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET, 3730 .doit = devlink_nl_cmd_dpipe_table_get, 3731 .policy = devlink_nl_policy, 3732 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3733 /* can be retrieved by unprivileged users */ 3734 }, 3735 { 3736 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET, 3737 .doit = devlink_nl_cmd_dpipe_entries_get, 3738 .policy = devlink_nl_policy, 3739 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3740 /* can be retrieved by unprivileged users */ 3741 }, 3742 { 3743 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET, 3744 .doit = devlink_nl_cmd_dpipe_headers_get, 3745 .policy = devlink_nl_policy, 3746 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3747 /* can be retrieved by unprivileged users */ 3748 }, 3749 { 3750 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET, 3751 .doit = devlink_nl_cmd_dpipe_table_counters_set, 3752 .policy = devlink_nl_policy, 3753 .flags = GENL_ADMIN_PERM, 3754 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3755 }, 3756 { 3757 .cmd = DEVLINK_CMD_RESOURCE_SET, 3758 .doit = devlink_nl_cmd_resource_set, 3759 .policy = devlink_nl_policy, 3760 .flags = GENL_ADMIN_PERM, 3761 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3762 }, 3763 { 3764 .cmd = DEVLINK_CMD_RESOURCE_DUMP, 3765 .doit = devlink_nl_cmd_resource_dump, 3766 .policy = devlink_nl_policy, 3767 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3768 /* can be retrieved by unprivileged users */ 3769 }, 3770 { 3771 .cmd = DEVLINK_CMD_RELOAD, 3772 .doit = devlink_nl_cmd_reload, 3773 .policy = devlink_nl_policy, 3774 .flags = GENL_ADMIN_PERM, 3775 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3776 DEVLINK_NL_FLAG_NO_LOCK, 3777 }, 3778 { 3779 .cmd = DEVLINK_CMD_PARAM_GET, 3780 .doit = devlink_nl_cmd_param_get_doit, 3781 .dumpit = devlink_nl_cmd_param_get_dumpit, 3782 .policy = devlink_nl_policy, 3783 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3784 /* can be retrieved by unprivileged users */ 3785 }, 3786 { 3787 .cmd = DEVLINK_CMD_PARAM_SET, 3788 .doit = devlink_nl_cmd_param_set_doit, 3789 .policy = devlink_nl_policy, 3790 .flags = GENL_ADMIN_PERM, 3791 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3792 }, 3793 { 3794 .cmd = DEVLINK_CMD_REGION_GET, 3795 .doit = devlink_nl_cmd_region_get_doit, 3796 .dumpit = devlink_nl_cmd_region_get_dumpit, 3797 .policy = devlink_nl_policy, 3798 .flags = GENL_ADMIN_PERM, 3799 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3800 }, 3801 { 3802 .cmd = DEVLINK_CMD_REGION_DEL, 3803 .doit = devlink_nl_cmd_region_del, 3804 .policy = devlink_nl_policy, 3805 .flags = GENL_ADMIN_PERM, 3806 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3807 }, 3808 { 3809 .cmd = DEVLINK_CMD_REGION_READ, 3810 .dumpit = devlink_nl_cmd_region_read_dumpit, 3811 .policy = devlink_nl_policy, 3812 .flags = GENL_ADMIN_PERM, 3813 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3814 }, 3815}; 3816 3817static struct genl_family devlink_nl_family __ro_after_init = { 3818 .name = DEVLINK_GENL_NAME, 3819 .version = DEVLINK_GENL_VERSION, 3820 .maxattr = DEVLINK_ATTR_MAX, 3821 .netnsok = true, 3822 .pre_doit = devlink_nl_pre_doit, 3823 .post_doit = devlink_nl_post_doit, 3824 .module = THIS_MODULE, 3825 .ops = devlink_nl_ops, 3826 .n_ops = ARRAY_SIZE(devlink_nl_ops), 3827 .mcgrps = devlink_nl_mcgrps, 3828 .n_mcgrps = ARRAY_SIZE(devlink_nl_mcgrps), 3829}; 3830 3831/** 3832 * devlink_alloc - Allocate new devlink instance resources 3833 * 3834 * @ops: ops 3835 * @priv_size: size of user private data 3836 * 3837 * Allocate new devlink instance resources, including devlink index 3838 * and name. 3839 */ 3840struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size) 3841{ 3842 struct devlink *devlink; 3843 3844 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL); 3845 if (!devlink) 3846 return NULL; 3847 devlink->ops = ops; 3848 devlink_net_set(devlink, &init_net); 3849 INIT_LIST_HEAD(&devlink->port_list); 3850 INIT_LIST_HEAD(&devlink->sb_list); 3851 INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list); 3852 INIT_LIST_HEAD(&devlink->resource_list); 3853 INIT_LIST_HEAD(&devlink->param_list); 3854 INIT_LIST_HEAD(&devlink->region_list); 3855 mutex_init(&devlink->lock); 3856 return devlink; 3857} 3858EXPORT_SYMBOL_GPL(devlink_alloc); 3859 3860/** 3861 * devlink_register - Register devlink instance 3862 * 3863 * @devlink: devlink 3864 */ 3865int devlink_register(struct devlink *devlink, struct device *dev) 3866{ 3867 mutex_lock(&devlink_mutex); 3868 devlink->dev = dev; 3869 list_add_tail(&devlink->list, &devlink_list); 3870 devlink_notify(devlink, DEVLINK_CMD_NEW); 3871 mutex_unlock(&devlink_mutex); 3872 return 0; 3873} 3874EXPORT_SYMBOL_GPL(devlink_register); 3875 3876/** 3877 * devlink_unregister - Unregister devlink instance 3878 * 3879 * @devlink: devlink 3880 */ 3881void devlink_unregister(struct devlink *devlink) 3882{ 3883 mutex_lock(&devlink_mutex); 3884 devlink_notify(devlink, DEVLINK_CMD_DEL); 3885 list_del(&devlink->list); 3886 mutex_unlock(&devlink_mutex); 3887} 3888EXPORT_SYMBOL_GPL(devlink_unregister); 3889 3890/** 3891 * devlink_free - Free devlink instance resources 3892 * 3893 * @devlink: devlink 3894 */ 3895void devlink_free(struct devlink *devlink) 3896{ 3897 kfree(devlink); 3898} 3899EXPORT_SYMBOL_GPL(devlink_free); 3900 3901/** 3902 * devlink_port_register - Register devlink port 3903 * 3904 * @devlink: devlink 3905 * @devlink_port: devlink port 3906 * @port_index 3907 * 3908 * Register devlink port with provided port index. User can use 3909 * any indexing, even hw-related one. devlink_port structure 3910 * is convenient to be embedded inside user driver private structure. 3911 * Note that the caller should take care of zeroing the devlink_port 3912 * structure. 3913 */ 3914int devlink_port_register(struct devlink *devlink, 3915 struct devlink_port *devlink_port, 3916 unsigned int port_index) 3917{ 3918 mutex_lock(&devlink->lock); 3919 if (devlink_port_index_exists(devlink, port_index)) { 3920 mutex_unlock(&devlink->lock); 3921 return -EEXIST; 3922 } 3923 devlink_port->devlink = devlink; 3924 devlink_port->index = port_index; 3925 devlink_port->registered = true; 3926 list_add_tail(&devlink_port->list, &devlink->port_list); 3927 mutex_unlock(&devlink->lock); 3928 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 3929 return 0; 3930} 3931EXPORT_SYMBOL_GPL(devlink_port_register); 3932 3933/** 3934 * devlink_port_unregister - Unregister devlink port 3935 * 3936 * @devlink_port: devlink port 3937 */ 3938void devlink_port_unregister(struct devlink_port *devlink_port) 3939{ 3940 struct devlink *devlink = devlink_port->devlink; 3941 3942 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL); 3943 mutex_lock(&devlink->lock); 3944 list_del(&devlink_port->list); 3945 mutex_unlock(&devlink->lock); 3946} 3947EXPORT_SYMBOL_GPL(devlink_port_unregister); 3948 3949static void __devlink_port_type_set(struct devlink_port *devlink_port, 3950 enum devlink_port_type type, 3951 void *type_dev) 3952{ 3953 devlink_port->type = type; 3954 devlink_port->type_dev = type_dev; 3955 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 3956} 3957 3958/** 3959 * devlink_port_type_eth_set - Set port type to Ethernet 3960 * 3961 * @devlink_port: devlink port 3962 * @netdev: related netdevice 3963 */ 3964void devlink_port_type_eth_set(struct devlink_port *devlink_port, 3965 struct net_device *netdev) 3966{ 3967 return __devlink_port_type_set(devlink_port, 3968 DEVLINK_PORT_TYPE_ETH, netdev); 3969} 3970EXPORT_SYMBOL_GPL(devlink_port_type_eth_set); 3971 3972/** 3973 * devlink_port_type_ib_set - Set port type to InfiniBand 3974 * 3975 * @devlink_port: devlink port 3976 * @ibdev: related IB device 3977 */ 3978void devlink_port_type_ib_set(struct devlink_port *devlink_port, 3979 struct ib_device *ibdev) 3980{ 3981 return __devlink_port_type_set(devlink_port, 3982 DEVLINK_PORT_TYPE_IB, ibdev); 3983} 3984EXPORT_SYMBOL_GPL(devlink_port_type_ib_set); 3985 3986/** 3987 * devlink_port_type_clear - Clear port type 3988 * 3989 * @devlink_port: devlink port 3990 */ 3991void devlink_port_type_clear(struct devlink_port *devlink_port) 3992{ 3993 return __devlink_port_type_set(devlink_port, 3994 DEVLINK_PORT_TYPE_NOTSET, NULL); 3995} 3996EXPORT_SYMBOL_GPL(devlink_port_type_clear); 3997 3998/** 3999 * devlink_port_attrs_set - Set port attributes 4000 * 4001 * @devlink_port: devlink port 4002 * @flavour: flavour of the port 4003 * @port_number: number of the port that is facing user, for example 4004 * the front panel port number 4005 * @split: indicates if this is split port 4006 * @split_subport_number: if the port is split, this is the number 4007 * of subport. 4008 */ 4009void devlink_port_attrs_set(struct devlink_port *devlink_port, 4010 enum devlink_port_flavour flavour, 4011 u32 port_number, bool split, 4012 u32 split_subport_number) 4013{ 4014 struct devlink_port_attrs *attrs = &devlink_port->attrs; 4015 4016 attrs->set = true; 4017 attrs->flavour = flavour; 4018 attrs->port_number = port_number; 4019 attrs->split = split; 4020 attrs->split_subport_number = split_subport_number; 4021 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 4022} 4023EXPORT_SYMBOL_GPL(devlink_port_attrs_set); 4024 4025int devlink_port_get_phys_port_name(struct devlink_port *devlink_port, 4026 char *name, size_t len) 4027{ 4028 struct devlink_port_attrs *attrs = &devlink_port->attrs; 4029 int n = 0; 4030 4031 if (!attrs->set) 4032 return -EOPNOTSUPP; 4033 4034 switch (attrs->flavour) { 4035 case DEVLINK_PORT_FLAVOUR_PHYSICAL: 4036 if (!attrs->split) 4037 n = snprintf(name, len, "p%u", attrs->port_number); 4038 else 4039 n = snprintf(name, len, "p%us%u", attrs->port_number, 4040 attrs->split_subport_number); 4041 break; 4042 case DEVLINK_PORT_FLAVOUR_CPU: 4043 case DEVLINK_PORT_FLAVOUR_DSA: 4044 /* As CPU and DSA ports do not have a netdevice associated 4045 * case should not ever happen. 4046 */ 4047 WARN_ON(1); 4048 return -EINVAL; 4049 } 4050 4051 if (n >= len) 4052 return -EINVAL; 4053 4054 return 0; 4055} 4056EXPORT_SYMBOL_GPL(devlink_port_get_phys_port_name); 4057 4058int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, 4059 u32 size, u16 ingress_pools_count, 4060 u16 egress_pools_count, u16 ingress_tc_count, 4061 u16 egress_tc_count) 4062{ 4063 struct devlink_sb *devlink_sb; 4064 int err = 0; 4065 4066 mutex_lock(&devlink->lock); 4067 if (devlink_sb_index_exists(devlink, sb_index)) { 4068 err = -EEXIST; 4069 goto unlock; 4070 } 4071 4072 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL); 4073 if (!devlink_sb) { 4074 err = -ENOMEM; 4075 goto unlock; 4076 } 4077 devlink_sb->index = sb_index; 4078 devlink_sb->size = size; 4079 devlink_sb->ingress_pools_count = ingress_pools_count; 4080 devlink_sb->egress_pools_count = egress_pools_count; 4081 devlink_sb->ingress_tc_count = ingress_tc_count; 4082 devlink_sb->egress_tc_count = egress_tc_count; 4083 list_add_tail(&devlink_sb->list, &devlink->sb_list); 4084unlock: 4085 mutex_unlock(&devlink->lock); 4086 return err; 4087} 4088EXPORT_SYMBOL_GPL(devlink_sb_register); 4089 4090void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index) 4091{ 4092 struct devlink_sb *devlink_sb; 4093 4094 mutex_lock(&devlink->lock); 4095 devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 4096 WARN_ON(!devlink_sb); 4097 list_del(&devlink_sb->list); 4098 mutex_unlock(&devlink->lock); 4099 kfree(devlink_sb); 4100} 4101EXPORT_SYMBOL_GPL(devlink_sb_unregister); 4102 4103/** 4104 * devlink_dpipe_headers_register - register dpipe headers 4105 * 4106 * @devlink: devlink 4107 * @dpipe_headers: dpipe header array 4108 * 4109 * Register the headers supported by hardware. 4110 */ 4111int devlink_dpipe_headers_register(struct devlink *devlink, 4112 struct devlink_dpipe_headers *dpipe_headers) 4113{ 4114 mutex_lock(&devlink->lock); 4115 devlink->dpipe_headers = dpipe_headers; 4116 mutex_unlock(&devlink->lock); 4117 return 0; 4118} 4119EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register); 4120 4121/** 4122 * devlink_dpipe_headers_unregister - unregister dpipe headers 4123 * 4124 * @devlink: devlink 4125 * 4126 * Unregister the headers supported by hardware. 4127 */ 4128void devlink_dpipe_headers_unregister(struct devlink *devlink) 4129{ 4130 mutex_lock(&devlink->lock); 4131 devlink->dpipe_headers = NULL; 4132 mutex_unlock(&devlink->lock); 4133} 4134EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister); 4135 4136/** 4137 * devlink_dpipe_table_counter_enabled - check if counter allocation 4138 * required 4139 * @devlink: devlink 4140 * @table_name: tables name 4141 * 4142 * Used by driver to check if counter allocation is required. 4143 * After counter allocation is turned on the table entries 4144 * are updated to include counter statistics. 4145 * 4146 * After that point on the driver must respect the counter 4147 * state so that each entry added to the table is added 4148 * with a counter. 4149 */ 4150bool devlink_dpipe_table_counter_enabled(struct devlink *devlink, 4151 const char *table_name) 4152{ 4153 struct devlink_dpipe_table *table; 4154 bool enabled; 4155 4156 rcu_read_lock(); 4157 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 4158 table_name); 4159 enabled = false; 4160 if (table) 4161 enabled = table->counters_enabled; 4162 rcu_read_unlock(); 4163 return enabled; 4164} 4165EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled); 4166 4167/** 4168 * devlink_dpipe_table_register - register dpipe table 4169 * 4170 * @devlink: devlink 4171 * @table_name: table name 4172 * @table_ops: table ops 4173 * @priv: priv 4174 * @counter_control_extern: external control for counters 4175 */ 4176int devlink_dpipe_table_register(struct devlink *devlink, 4177 const char *table_name, 4178 struct devlink_dpipe_table_ops *table_ops, 4179 void *priv, bool counter_control_extern) 4180{ 4181 struct devlink_dpipe_table *table; 4182 4183 if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name)) 4184 return -EEXIST; 4185 4186 if (WARN_ON(!table_ops->size_get)) 4187 return -EINVAL; 4188 4189 table = kzalloc(sizeof(*table), GFP_KERNEL); 4190 if (!table) 4191 return -ENOMEM; 4192 4193 table->name = table_name; 4194 table->table_ops = table_ops; 4195 table->priv = priv; 4196 table->counter_control_extern = counter_control_extern; 4197 4198 mutex_lock(&devlink->lock); 4199 list_add_tail_rcu(&table->list, &devlink->dpipe_table_list); 4200 mutex_unlock(&devlink->lock); 4201 return 0; 4202} 4203EXPORT_SYMBOL_GPL(devlink_dpipe_table_register); 4204 4205/** 4206 * devlink_dpipe_table_unregister - unregister dpipe table 4207 * 4208 * @devlink: devlink 4209 * @table_name: table name 4210 */ 4211void devlink_dpipe_table_unregister(struct devlink *devlink, 4212 const char *table_name) 4213{ 4214 struct devlink_dpipe_table *table; 4215 4216 mutex_lock(&devlink->lock); 4217 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 4218 table_name); 4219 if (!table) 4220 goto unlock; 4221 list_del_rcu(&table->list); 4222 mutex_unlock(&devlink->lock); 4223 kfree_rcu(table, rcu); 4224 return; 4225unlock: 4226 mutex_unlock(&devlink->lock); 4227} 4228EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister); 4229 4230/** 4231 * devlink_resource_register - devlink resource register 4232 * 4233 * @devlink: devlink 4234 * @resource_name: resource's name 4235 * @top_hierarchy: top hierarchy 4236 * @reload_required: reload is required for new configuration to 4237 * apply 4238 * @resource_size: resource's size 4239 * @resource_id: resource's id 4240 * @parent_reosurce_id: resource's parent id 4241 * @size params: size parameters 4242 */ 4243int devlink_resource_register(struct devlink *devlink, 4244 const char *resource_name, 4245 u64 resource_size, 4246 u64 resource_id, 4247 u64 parent_resource_id, 4248 const struct devlink_resource_size_params *size_params) 4249{ 4250 struct devlink_resource *resource; 4251 struct list_head *resource_list; 4252 bool top_hierarchy; 4253 int err = 0; 4254 4255 top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP; 4256 4257 mutex_lock(&devlink->lock); 4258 resource = devlink_resource_find(devlink, NULL, resource_id); 4259 if (resource) { 4260 err = -EINVAL; 4261 goto out; 4262 } 4263 4264 resource = kzalloc(sizeof(*resource), GFP_KERNEL); 4265 if (!resource) { 4266 err = -ENOMEM; 4267 goto out; 4268 } 4269 4270 if (top_hierarchy) { 4271 resource_list = &devlink->resource_list; 4272 } else { 4273 struct devlink_resource *parent_resource; 4274 4275 parent_resource = devlink_resource_find(devlink, NULL, 4276 parent_resource_id); 4277 if (parent_resource) { 4278 resource_list = &parent_resource->resource_list; 4279 resource->parent = parent_resource; 4280 } else { 4281 kfree(resource); 4282 err = -EINVAL; 4283 goto out; 4284 } 4285 } 4286 4287 resource->name = resource_name; 4288 resource->size = resource_size; 4289 resource->size_new = resource_size; 4290 resource->id = resource_id; 4291 resource->size_valid = true; 4292 memcpy(&resource->size_params, size_params, 4293 sizeof(resource->size_params)); 4294 INIT_LIST_HEAD(&resource->resource_list); 4295 list_add_tail(&resource->list, resource_list); 4296out: 4297 mutex_unlock(&devlink->lock); 4298 return err; 4299} 4300EXPORT_SYMBOL_GPL(devlink_resource_register); 4301 4302/** 4303 * devlink_resources_unregister - free all resources 4304 * 4305 * @devlink: devlink 4306 * @resource: resource 4307 */ 4308void devlink_resources_unregister(struct devlink *devlink, 4309 struct devlink_resource *resource) 4310{ 4311 struct devlink_resource *tmp, *child_resource; 4312 struct list_head *resource_list; 4313 4314 if (resource) 4315 resource_list = &resource->resource_list; 4316 else 4317 resource_list = &devlink->resource_list; 4318 4319 if (!resource) 4320 mutex_lock(&devlink->lock); 4321 4322 list_for_each_entry_safe(child_resource, tmp, resource_list, list) { 4323 devlink_resources_unregister(devlink, child_resource); 4324 list_del(&child_resource->list); 4325 kfree(child_resource); 4326 } 4327 4328 if (!resource) 4329 mutex_unlock(&devlink->lock); 4330} 4331EXPORT_SYMBOL_GPL(devlink_resources_unregister); 4332 4333/** 4334 * devlink_resource_size_get - get and update size 4335 * 4336 * @devlink: devlink 4337 * @resource_id: the requested resource id 4338 * @p_resource_size: ptr to update 4339 */ 4340int devlink_resource_size_get(struct devlink *devlink, 4341 u64 resource_id, 4342 u64 *p_resource_size) 4343{ 4344 struct devlink_resource *resource; 4345 int err = 0; 4346 4347 mutex_lock(&devlink->lock); 4348 resource = devlink_resource_find(devlink, NULL, resource_id); 4349 if (!resource) { 4350 err = -EINVAL; 4351 goto out; 4352 } 4353 *p_resource_size = resource->size_new; 4354 resource->size = resource->size_new; 4355out: 4356 mutex_unlock(&devlink->lock); 4357 return err; 4358} 4359EXPORT_SYMBOL_GPL(devlink_resource_size_get); 4360 4361/** 4362 * devlink_dpipe_table_resource_set - set the resource id 4363 * 4364 * @devlink: devlink 4365 * @table_name: table name 4366 * @resource_id: resource id 4367 * @resource_units: number of resource's units consumed per table's entry 4368 */ 4369int devlink_dpipe_table_resource_set(struct devlink *devlink, 4370 const char *table_name, u64 resource_id, 4371 u64 resource_units) 4372{ 4373 struct devlink_dpipe_table *table; 4374 int err = 0; 4375 4376 mutex_lock(&devlink->lock); 4377 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 4378 table_name); 4379 if (!table) { 4380 err = -EINVAL; 4381 goto out; 4382 } 4383 table->resource_id = resource_id; 4384 table->resource_units = resource_units; 4385 table->resource_valid = true; 4386out: 4387 mutex_unlock(&devlink->lock); 4388 return err; 4389} 4390EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set); 4391 4392/** 4393 * devlink_resource_occ_get_register - register occupancy getter 4394 * 4395 * @devlink: devlink 4396 * @resource_id: resource id 4397 * @occ_get: occupancy getter callback 4398 * @occ_get_priv: occupancy getter callback priv 4399 */ 4400void devlink_resource_occ_get_register(struct devlink *devlink, 4401 u64 resource_id, 4402 devlink_resource_occ_get_t *occ_get, 4403 void *occ_get_priv) 4404{ 4405 struct devlink_resource *resource; 4406 4407 mutex_lock(&devlink->lock); 4408 resource = devlink_resource_find(devlink, NULL, resource_id); 4409 if (WARN_ON(!resource)) 4410 goto out; 4411 WARN_ON(resource->occ_get); 4412 4413 resource->occ_get = occ_get; 4414 resource->occ_get_priv = occ_get_priv; 4415out: 4416 mutex_unlock(&devlink->lock); 4417} 4418EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register); 4419 4420/** 4421 * devlink_resource_occ_get_unregister - unregister occupancy getter 4422 * 4423 * @devlink: devlink 4424 * @resource_id: resource id 4425 */ 4426void devlink_resource_occ_get_unregister(struct devlink *devlink, 4427 u64 resource_id) 4428{ 4429 struct devlink_resource *resource; 4430 4431 mutex_lock(&devlink->lock); 4432 resource = devlink_resource_find(devlink, NULL, resource_id); 4433 if (WARN_ON(!resource)) 4434 goto out; 4435 WARN_ON(!resource->occ_get); 4436 4437 resource->occ_get = NULL; 4438 resource->occ_get_priv = NULL; 4439out: 4440 mutex_unlock(&devlink->lock); 4441} 4442EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister); 4443 4444/** 4445 * devlink_params_register - register configuration parameters 4446 * 4447 * @devlink: devlink 4448 * @params: configuration parameters array 4449 * @params_count: number of parameters provided 4450 * 4451 * Register the configuration parameters supported by the driver. 4452 */ 4453int devlink_params_register(struct devlink *devlink, 4454 const struct devlink_param *params, 4455 size_t params_count) 4456{ 4457 const struct devlink_param *param = params; 4458 int i; 4459 int err; 4460 4461 mutex_lock(&devlink->lock); 4462 for (i = 0; i < params_count; i++, param++) { 4463 if (!param || !param->name || !param->supported_cmodes) { 4464 err = -EINVAL; 4465 goto rollback; 4466 } 4467 if (param->generic) { 4468 err = devlink_param_generic_verify(param); 4469 if (err) 4470 goto rollback; 4471 } else { 4472 err = devlink_param_driver_verify(param); 4473 if (err) 4474 goto rollback; 4475 } 4476 err = devlink_param_register_one(devlink, param); 4477 if (err) 4478 goto rollback; 4479 } 4480 4481 mutex_unlock(&devlink->lock); 4482 return 0; 4483 4484rollback: 4485 if (!i) 4486 goto unlock; 4487 for (param--; i > 0; i--, param--) 4488 devlink_param_unregister_one(devlink, param); 4489unlock: 4490 mutex_unlock(&devlink->lock); 4491 return err; 4492} 4493EXPORT_SYMBOL_GPL(devlink_params_register); 4494 4495/** 4496 * devlink_params_unregister - unregister configuration parameters 4497 * @devlink: devlink 4498 * @params: configuration parameters to unregister 4499 * @params_count: number of parameters provided 4500 */ 4501void devlink_params_unregister(struct devlink *devlink, 4502 const struct devlink_param *params, 4503 size_t params_count) 4504{ 4505 const struct devlink_param *param = params; 4506 int i; 4507 4508 mutex_lock(&devlink->lock); 4509 for (i = 0; i < params_count; i++, param++) 4510 devlink_param_unregister_one(devlink, param); 4511 mutex_unlock(&devlink->lock); 4512} 4513EXPORT_SYMBOL_GPL(devlink_params_unregister); 4514 4515/** 4516 * devlink_param_driverinit_value_get - get configuration parameter 4517 * value for driver initializing 4518 * 4519 * @devlink: devlink 4520 * @param_id: parameter ID 4521 * @init_val: value of parameter in driverinit configuration mode 4522 * 4523 * This function should be used by the driver to get driverinit 4524 * configuration for initialization after reload command. 4525 */ 4526int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id, 4527 union devlink_param_value *init_val) 4528{ 4529 struct devlink_param_item *param_item; 4530 4531 if (!devlink->ops || !devlink->ops->reload) 4532 return -EOPNOTSUPP; 4533 4534 param_item = devlink_param_find_by_id(&devlink->param_list, param_id); 4535 if (!param_item) 4536 return -EINVAL; 4537 4538 if (!param_item->driverinit_value_valid || 4539 !devlink_param_cmode_is_supported(param_item->param, 4540 DEVLINK_PARAM_CMODE_DRIVERINIT)) 4541 return -EOPNOTSUPP; 4542 4543 *init_val = param_item->driverinit_value; 4544 4545 return 0; 4546} 4547EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_get); 4548 4549/** 4550 * devlink_param_driverinit_value_set - set value of configuration 4551 * parameter for driverinit 4552 * configuration mode 4553 * 4554 * @devlink: devlink 4555 * @param_id: parameter ID 4556 * @init_val: value of parameter to set for driverinit configuration mode 4557 * 4558 * This function should be used by the driver to set driverinit 4559 * configuration mode default value. 4560 */ 4561int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id, 4562 union devlink_param_value init_val) 4563{ 4564 struct devlink_param_item *param_item; 4565 4566 param_item = devlink_param_find_by_id(&devlink->param_list, param_id); 4567 if (!param_item) 4568 return -EINVAL; 4569 4570 if (!devlink_param_cmode_is_supported(param_item->param, 4571 DEVLINK_PARAM_CMODE_DRIVERINIT)) 4572 return -EOPNOTSUPP; 4573 4574 param_item->driverinit_value = init_val; 4575 param_item->driverinit_value_valid = true; 4576 4577 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW); 4578 return 0; 4579} 4580EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_set); 4581 4582/** 4583 * devlink_param_value_changed - notify devlink on a parameter's value 4584 * change. Should be called by the driver 4585 * right after the change. 4586 * 4587 * @devlink: devlink 4588 * @param_id: parameter ID 4589 * 4590 * This function should be used by the driver to notify devlink on value 4591 * change, excluding driverinit configuration mode. 4592 * For driverinit configuration mode driver should use the function 4593 * devlink_param_driverinit_value_set() instead. 4594 */ 4595void devlink_param_value_changed(struct devlink *devlink, u32 param_id) 4596{ 4597 struct devlink_param_item *param_item; 4598 4599 param_item = devlink_param_find_by_id(&devlink->param_list, param_id); 4600 WARN_ON(!param_item); 4601 4602 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW); 4603} 4604EXPORT_SYMBOL_GPL(devlink_param_value_changed); 4605 4606/** 4607 * devlink_region_create - create a new address region 4608 * 4609 * @devlink: devlink 4610 * @region_name: region name 4611 * @region_max_snapshots: Maximum supported number of snapshots for region 4612 * @region_size: size of region 4613 */ 4614struct devlink_region *devlink_region_create(struct devlink *devlink, 4615 const char *region_name, 4616 u32 region_max_snapshots, 4617 u64 region_size) 4618{ 4619 struct devlink_region *region; 4620 int err = 0; 4621 4622 mutex_lock(&devlink->lock); 4623 4624 if (devlink_region_get_by_name(devlink, region_name)) { 4625 err = -EEXIST; 4626 goto unlock; 4627 } 4628 4629 region = kzalloc(sizeof(*region), GFP_KERNEL); 4630 if (!region) { 4631 err = -ENOMEM; 4632 goto unlock; 4633 } 4634 4635 region->devlink = devlink; 4636 region->max_snapshots = region_max_snapshots; 4637 region->name = region_name; 4638 region->size = region_size; 4639 INIT_LIST_HEAD(&region->snapshot_list); 4640 list_add_tail(&region->list, &devlink->region_list); 4641 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW); 4642 4643 mutex_unlock(&devlink->lock); 4644 return region; 4645 4646unlock: 4647 mutex_unlock(&devlink->lock); 4648 return ERR_PTR(err); 4649} 4650EXPORT_SYMBOL_GPL(devlink_region_create); 4651 4652/** 4653 * devlink_region_destroy - destroy address region 4654 * 4655 * @region: devlink region to destroy 4656 */ 4657void devlink_region_destroy(struct devlink_region *region) 4658{ 4659 struct devlink *devlink = region->devlink; 4660 struct devlink_snapshot *snapshot, *ts; 4661 4662 mutex_lock(&devlink->lock); 4663 4664 /* Free all snapshots of region */ 4665 list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list) 4666 devlink_region_snapshot_del(snapshot); 4667 4668 list_del(&region->list); 4669 4670 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL); 4671 mutex_unlock(&devlink->lock); 4672 kfree(region); 4673} 4674EXPORT_SYMBOL_GPL(devlink_region_destroy); 4675 4676/** 4677 * devlink_region_shapshot_id_get - get snapshot ID 4678 * 4679 * This callback should be called when adding a new snapshot, 4680 * Driver should use the same id for multiple snapshots taken 4681 * on multiple regions at the same time/by the same trigger. 4682 * 4683 * @devlink: devlink 4684 */ 4685u32 devlink_region_shapshot_id_get(struct devlink *devlink) 4686{ 4687 u32 id; 4688 4689 mutex_lock(&devlink->lock); 4690 id = ++devlink->snapshot_id; 4691 mutex_unlock(&devlink->lock); 4692 4693 return id; 4694} 4695EXPORT_SYMBOL_GPL(devlink_region_shapshot_id_get); 4696 4697/** 4698 * devlink_region_snapshot_create - create a new snapshot 4699 * This will add a new snapshot of a region. The snapshot 4700 * will be stored on the region struct and can be accessed 4701 * from devlink. This is useful for future analyses of snapshots. 4702 * Multiple snapshots can be created on a region. 4703 * The @snapshot_id should be obtained using the getter function. 4704 * 4705 * @devlink_region: devlink region of the snapshot 4706 * @data_len: size of snapshot data 4707 * @data: snapshot data 4708 * @snapshot_id: snapshot id to be created 4709 * @data_destructor: pointer to destructor function to free data 4710 */ 4711int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len, 4712 u8 *data, u32 snapshot_id, 4713 devlink_snapshot_data_dest_t *data_destructor) 4714{ 4715 struct devlink *devlink = region->devlink; 4716 struct devlink_snapshot *snapshot; 4717 int err; 4718 4719 mutex_lock(&devlink->lock); 4720 4721 /* check if region can hold one more snapshot */ 4722 if (region->cur_snapshots == region->max_snapshots) { 4723 err = -ENOMEM; 4724 goto unlock; 4725 } 4726 4727 if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { 4728 err = -EEXIST; 4729 goto unlock; 4730 } 4731 4732 snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL); 4733 if (!snapshot) { 4734 err = -ENOMEM; 4735 goto unlock; 4736 } 4737 4738 snapshot->id = snapshot_id; 4739 snapshot->region = region; 4740 snapshot->data = data; 4741 snapshot->data_len = data_len; 4742 snapshot->data_destructor = data_destructor; 4743 4744 list_add_tail(&snapshot->list, &region->snapshot_list); 4745 4746 region->cur_snapshots++; 4747 4748 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW); 4749 mutex_unlock(&devlink->lock); 4750 return 0; 4751 4752unlock: 4753 mutex_unlock(&devlink->lock); 4754 return err; 4755} 4756EXPORT_SYMBOL_GPL(devlink_region_snapshot_create); 4757 4758static int __init devlink_module_init(void) 4759{ 4760 return genl_register_family(&devlink_nl_family); 4761} 4762 4763static void __exit devlink_module_exit(void) 4764{ 4765 genl_unregister_family(&devlink_nl_family); 4766} 4767 4768module_init(devlink_module_init); 4769module_exit(devlink_module_exit); 4770 4771MODULE_LICENSE("GPL v2"); 4772MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>"); 4773MODULE_DESCRIPTION("Network physical device Netlink interface"); 4774MODULE_ALIAS_GENL_FAMILY(DEVLINK_GENL_NAME);