at v4.19 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 int len; 2999 3000 if (param->type != DEVLINK_PARAM_TYPE_BOOL && 3001 !info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) 3002 return -EINVAL; 3003 3004 switch (param->type) { 3005 case DEVLINK_PARAM_TYPE_U8: 3006 value->vu8 = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3007 break; 3008 case DEVLINK_PARAM_TYPE_U16: 3009 value->vu16 = nla_get_u16(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3010 break; 3011 case DEVLINK_PARAM_TYPE_U32: 3012 value->vu32 = nla_get_u32(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]); 3013 break; 3014 case DEVLINK_PARAM_TYPE_STRING: 3015 len = strnlen(nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]), 3016 nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])); 3017 if (len == nla_len(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA]) || 3018 len >= __DEVLINK_PARAM_MAX_STRING_VALUE) 3019 return -EINVAL; 3020 strcpy(value->vstr, 3021 nla_data(info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA])); 3022 break; 3023 case DEVLINK_PARAM_TYPE_BOOL: 3024 value->vbool = info->attrs[DEVLINK_ATTR_PARAM_VALUE_DATA] ? 3025 true : false; 3026 break; 3027 } 3028 return 0; 3029} 3030 3031static struct devlink_param_item * 3032devlink_param_get_from_info(struct devlink *devlink, 3033 struct genl_info *info) 3034{ 3035 char *param_name; 3036 3037 if (!info->attrs[DEVLINK_ATTR_PARAM_NAME]) 3038 return NULL; 3039 3040 param_name = nla_data(info->attrs[DEVLINK_ATTR_PARAM_NAME]); 3041 return devlink_param_find_by_name(&devlink->param_list, param_name); 3042} 3043 3044static int devlink_nl_cmd_param_get_doit(struct sk_buff *skb, 3045 struct genl_info *info) 3046{ 3047 struct devlink *devlink = info->user_ptr[0]; 3048 struct devlink_param_item *param_item; 3049 struct sk_buff *msg; 3050 int err; 3051 3052 param_item = devlink_param_get_from_info(devlink, info); 3053 if (!param_item) 3054 return -EINVAL; 3055 3056 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3057 if (!msg) 3058 return -ENOMEM; 3059 3060 err = devlink_nl_param_fill(msg, devlink, param_item, 3061 DEVLINK_CMD_PARAM_GET, 3062 info->snd_portid, info->snd_seq, 0); 3063 if (err) { 3064 nlmsg_free(msg); 3065 return err; 3066 } 3067 3068 return genlmsg_reply(msg, info); 3069} 3070 3071static int devlink_nl_cmd_param_set_doit(struct sk_buff *skb, 3072 struct genl_info *info) 3073{ 3074 struct devlink *devlink = info->user_ptr[0]; 3075 enum devlink_param_type param_type; 3076 struct devlink_param_gset_ctx ctx; 3077 enum devlink_param_cmode cmode; 3078 struct devlink_param_item *param_item; 3079 const struct devlink_param *param; 3080 union devlink_param_value value; 3081 int err = 0; 3082 3083 param_item = devlink_param_get_from_info(devlink, info); 3084 if (!param_item) 3085 return -EINVAL; 3086 param = param_item->param; 3087 err = devlink_param_type_get_from_info(info, &param_type); 3088 if (err) 3089 return err; 3090 if (param_type != param->type) 3091 return -EINVAL; 3092 err = devlink_param_value_get_from_info(param, info, &value); 3093 if (err) 3094 return err; 3095 if (param->validate) { 3096 err = param->validate(devlink, param->id, value, info->extack); 3097 if (err) 3098 return err; 3099 } 3100 3101 if (!info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]) 3102 return -EINVAL; 3103 cmode = nla_get_u8(info->attrs[DEVLINK_ATTR_PARAM_VALUE_CMODE]); 3104 if (!devlink_param_cmode_is_supported(param, cmode)) 3105 return -EOPNOTSUPP; 3106 3107 if (cmode == DEVLINK_PARAM_CMODE_DRIVERINIT) { 3108 if (param->type == DEVLINK_PARAM_TYPE_STRING) 3109 strcpy(param_item->driverinit_value.vstr, value.vstr); 3110 else 3111 param_item->driverinit_value = value; 3112 param_item->driverinit_value_valid = true; 3113 } else { 3114 if (!param->set) 3115 return -EOPNOTSUPP; 3116 ctx.val = value; 3117 ctx.cmode = cmode; 3118 err = devlink_param_set(devlink, param, &ctx); 3119 if (err) 3120 return err; 3121 } 3122 3123 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW); 3124 return 0; 3125} 3126 3127static int devlink_param_register_one(struct devlink *devlink, 3128 const struct devlink_param *param) 3129{ 3130 struct devlink_param_item *param_item; 3131 3132 if (devlink_param_find_by_name(&devlink->param_list, 3133 param->name)) 3134 return -EEXIST; 3135 3136 if (param->supported_cmodes == BIT(DEVLINK_PARAM_CMODE_DRIVERINIT)) 3137 WARN_ON(param->get || param->set); 3138 else 3139 WARN_ON(!param->get || !param->set); 3140 3141 param_item = kzalloc(sizeof(*param_item), GFP_KERNEL); 3142 if (!param_item) 3143 return -ENOMEM; 3144 param_item->param = param; 3145 3146 list_add_tail(&param_item->list, &devlink->param_list); 3147 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW); 3148 return 0; 3149} 3150 3151static void devlink_param_unregister_one(struct devlink *devlink, 3152 const struct devlink_param *param) 3153{ 3154 struct devlink_param_item *param_item; 3155 3156 param_item = devlink_param_find_by_name(&devlink->param_list, 3157 param->name); 3158 WARN_ON(!param_item); 3159 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_DEL); 3160 list_del(&param_item->list); 3161 kfree(param_item); 3162} 3163 3164static int devlink_nl_region_snapshot_id_put(struct sk_buff *msg, 3165 struct devlink *devlink, 3166 struct devlink_snapshot *snapshot) 3167{ 3168 struct nlattr *snap_attr; 3169 int err; 3170 3171 snap_attr = nla_nest_start(msg, DEVLINK_ATTR_REGION_SNAPSHOT); 3172 if (!snap_attr) 3173 return -EINVAL; 3174 3175 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, snapshot->id); 3176 if (err) 3177 goto nla_put_failure; 3178 3179 nla_nest_end(msg, snap_attr); 3180 return 0; 3181 3182nla_put_failure: 3183 nla_nest_cancel(msg, snap_attr); 3184 return err; 3185} 3186 3187static int devlink_nl_region_snapshots_id_put(struct sk_buff *msg, 3188 struct devlink *devlink, 3189 struct devlink_region *region) 3190{ 3191 struct devlink_snapshot *snapshot; 3192 struct nlattr *snapshots_attr; 3193 int err; 3194 3195 snapshots_attr = nla_nest_start(msg, DEVLINK_ATTR_REGION_SNAPSHOTS); 3196 if (!snapshots_attr) 3197 return -EINVAL; 3198 3199 list_for_each_entry(snapshot, &region->snapshot_list, list) { 3200 err = devlink_nl_region_snapshot_id_put(msg, devlink, snapshot); 3201 if (err) 3202 goto nla_put_failure; 3203 } 3204 3205 nla_nest_end(msg, snapshots_attr); 3206 return 0; 3207 3208nla_put_failure: 3209 nla_nest_cancel(msg, snapshots_attr); 3210 return err; 3211} 3212 3213static int devlink_nl_region_fill(struct sk_buff *msg, struct devlink *devlink, 3214 enum devlink_command cmd, u32 portid, 3215 u32 seq, int flags, 3216 struct devlink_region *region) 3217{ 3218 void *hdr; 3219 int err; 3220 3221 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 3222 if (!hdr) 3223 return -EMSGSIZE; 3224 3225 err = devlink_nl_put_handle(msg, devlink); 3226 if (err) 3227 goto nla_put_failure; 3228 3229 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, region->name); 3230 if (err) 3231 goto nla_put_failure; 3232 3233 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE, 3234 region->size, 3235 DEVLINK_ATTR_PAD); 3236 if (err) 3237 goto nla_put_failure; 3238 3239 err = devlink_nl_region_snapshots_id_put(msg, devlink, region); 3240 if (err) 3241 goto nla_put_failure; 3242 3243 genlmsg_end(msg, hdr); 3244 return 0; 3245 3246nla_put_failure: 3247 genlmsg_cancel(msg, hdr); 3248 return err; 3249} 3250 3251static void devlink_nl_region_notify(struct devlink_region *region, 3252 struct devlink_snapshot *snapshot, 3253 enum devlink_command cmd) 3254{ 3255 struct devlink *devlink = region->devlink; 3256 struct sk_buff *msg; 3257 void *hdr; 3258 int err; 3259 3260 WARN_ON(cmd != DEVLINK_CMD_REGION_NEW && cmd != DEVLINK_CMD_REGION_DEL); 3261 3262 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3263 if (!msg) 3264 return; 3265 3266 hdr = genlmsg_put(msg, 0, 0, &devlink_nl_family, 0, cmd); 3267 if (!hdr) 3268 goto out_free_msg; 3269 3270 err = devlink_nl_put_handle(msg, devlink); 3271 if (err) 3272 goto out_cancel_msg; 3273 3274 err = nla_put_string(msg, DEVLINK_ATTR_REGION_NAME, 3275 region->name); 3276 if (err) 3277 goto out_cancel_msg; 3278 3279 if (snapshot) { 3280 err = nla_put_u32(msg, DEVLINK_ATTR_REGION_SNAPSHOT_ID, 3281 snapshot->id); 3282 if (err) 3283 goto out_cancel_msg; 3284 } else { 3285 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_SIZE, 3286 region->size, DEVLINK_ATTR_PAD); 3287 if (err) 3288 goto out_cancel_msg; 3289 } 3290 genlmsg_end(msg, hdr); 3291 3292 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), 3293 msg, 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 3294 3295 return; 3296 3297out_cancel_msg: 3298 genlmsg_cancel(msg, hdr); 3299out_free_msg: 3300 nlmsg_free(msg); 3301} 3302 3303static int devlink_nl_cmd_region_get_doit(struct sk_buff *skb, 3304 struct genl_info *info) 3305{ 3306 struct devlink *devlink = info->user_ptr[0]; 3307 struct devlink_region *region; 3308 const char *region_name; 3309 struct sk_buff *msg; 3310 int err; 3311 3312 if (!info->attrs[DEVLINK_ATTR_REGION_NAME]) 3313 return -EINVAL; 3314 3315 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 3316 region = devlink_region_get_by_name(devlink, region_name); 3317 if (!region) 3318 return -EINVAL; 3319 3320 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 3321 if (!msg) 3322 return -ENOMEM; 3323 3324 err = devlink_nl_region_fill(msg, devlink, DEVLINK_CMD_REGION_GET, 3325 info->snd_portid, info->snd_seq, 0, 3326 region); 3327 if (err) { 3328 nlmsg_free(msg); 3329 return err; 3330 } 3331 3332 return genlmsg_reply(msg, info); 3333} 3334 3335static int devlink_nl_cmd_region_get_dumpit(struct sk_buff *msg, 3336 struct netlink_callback *cb) 3337{ 3338 struct devlink_region *region; 3339 struct devlink *devlink; 3340 int start = cb->args[0]; 3341 int idx = 0; 3342 int err; 3343 3344 mutex_lock(&devlink_mutex); 3345 list_for_each_entry(devlink, &devlink_list, list) { 3346 if (!net_eq(devlink_net(devlink), sock_net(msg->sk))) 3347 continue; 3348 3349 mutex_lock(&devlink->lock); 3350 list_for_each_entry(region, &devlink->region_list, list) { 3351 if (idx < start) { 3352 idx++; 3353 continue; 3354 } 3355 err = devlink_nl_region_fill(msg, devlink, 3356 DEVLINK_CMD_REGION_GET, 3357 NETLINK_CB(cb->skb).portid, 3358 cb->nlh->nlmsg_seq, 3359 NLM_F_MULTI, region); 3360 if (err) { 3361 mutex_unlock(&devlink->lock); 3362 goto out; 3363 } 3364 idx++; 3365 } 3366 mutex_unlock(&devlink->lock); 3367 } 3368out: 3369 mutex_unlock(&devlink_mutex); 3370 cb->args[0] = idx; 3371 return msg->len; 3372} 3373 3374static int devlink_nl_cmd_region_del(struct sk_buff *skb, 3375 struct genl_info *info) 3376{ 3377 struct devlink *devlink = info->user_ptr[0]; 3378 struct devlink_snapshot *snapshot; 3379 struct devlink_region *region; 3380 const char *region_name; 3381 u32 snapshot_id; 3382 3383 if (!info->attrs[DEVLINK_ATTR_REGION_NAME] || 3384 !info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) 3385 return -EINVAL; 3386 3387 region_name = nla_data(info->attrs[DEVLINK_ATTR_REGION_NAME]); 3388 snapshot_id = nla_get_u32(info->attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); 3389 3390 region = devlink_region_get_by_name(devlink, region_name); 3391 if (!region) 3392 return -EINVAL; 3393 3394 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); 3395 if (!snapshot) 3396 return -EINVAL; 3397 3398 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_DEL); 3399 devlink_region_snapshot_del(snapshot); 3400 return 0; 3401} 3402 3403static int devlink_nl_cmd_region_read_chunk_fill(struct sk_buff *msg, 3404 struct devlink *devlink, 3405 u8 *chunk, u32 chunk_size, 3406 u64 addr) 3407{ 3408 struct nlattr *chunk_attr; 3409 int err; 3410 3411 chunk_attr = nla_nest_start(msg, DEVLINK_ATTR_REGION_CHUNK); 3412 if (!chunk_attr) 3413 return -EINVAL; 3414 3415 err = nla_put(msg, DEVLINK_ATTR_REGION_CHUNK_DATA, chunk_size, chunk); 3416 if (err) 3417 goto nla_put_failure; 3418 3419 err = nla_put_u64_64bit(msg, DEVLINK_ATTR_REGION_CHUNK_ADDR, addr, 3420 DEVLINK_ATTR_PAD); 3421 if (err) 3422 goto nla_put_failure; 3423 3424 nla_nest_end(msg, chunk_attr); 3425 return 0; 3426 3427nla_put_failure: 3428 nla_nest_cancel(msg, chunk_attr); 3429 return err; 3430} 3431 3432#define DEVLINK_REGION_READ_CHUNK_SIZE 256 3433 3434static int devlink_nl_region_read_snapshot_fill(struct sk_buff *skb, 3435 struct devlink *devlink, 3436 struct devlink_region *region, 3437 struct nlattr **attrs, 3438 u64 start_offset, 3439 u64 end_offset, 3440 bool dump, 3441 u64 *new_offset) 3442{ 3443 struct devlink_snapshot *snapshot; 3444 u64 curr_offset = start_offset; 3445 u32 snapshot_id; 3446 int err = 0; 3447 3448 *new_offset = start_offset; 3449 3450 snapshot_id = nla_get_u32(attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]); 3451 snapshot = devlink_region_snapshot_get_by_id(region, snapshot_id); 3452 if (!snapshot) 3453 return -EINVAL; 3454 3455 if (end_offset > snapshot->data_len || dump) 3456 end_offset = snapshot->data_len; 3457 3458 while (curr_offset < end_offset) { 3459 u32 data_size; 3460 u8 *data; 3461 3462 if (end_offset - curr_offset < DEVLINK_REGION_READ_CHUNK_SIZE) 3463 data_size = end_offset - curr_offset; 3464 else 3465 data_size = DEVLINK_REGION_READ_CHUNK_SIZE; 3466 3467 data = &snapshot->data[curr_offset]; 3468 err = devlink_nl_cmd_region_read_chunk_fill(skb, devlink, 3469 data, data_size, 3470 curr_offset); 3471 if (err) 3472 break; 3473 3474 curr_offset += data_size; 3475 } 3476 *new_offset = curr_offset; 3477 3478 return err; 3479} 3480 3481static int devlink_nl_cmd_region_read_dumpit(struct sk_buff *skb, 3482 struct netlink_callback *cb) 3483{ 3484 u64 ret_offset, start_offset, end_offset = 0; 3485 struct nlattr *attrs[DEVLINK_ATTR_MAX + 1]; 3486 const struct genl_ops *ops = cb->data; 3487 struct devlink_region *region; 3488 struct nlattr *chunks_attr; 3489 const char *region_name; 3490 struct devlink *devlink; 3491 bool dump = true; 3492 void *hdr; 3493 int err; 3494 3495 start_offset = *((u64 *)&cb->args[0]); 3496 3497 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + devlink_nl_family.hdrsize, 3498 attrs, DEVLINK_ATTR_MAX, ops->policy, NULL); 3499 if (err) 3500 goto out; 3501 3502 devlink = devlink_get_from_attrs(sock_net(cb->skb->sk), attrs); 3503 if (IS_ERR(devlink)) 3504 goto out; 3505 3506 mutex_lock(&devlink_mutex); 3507 mutex_lock(&devlink->lock); 3508 3509 if (!attrs[DEVLINK_ATTR_REGION_NAME] || 3510 !attrs[DEVLINK_ATTR_REGION_SNAPSHOT_ID]) 3511 goto out_unlock; 3512 3513 region_name = nla_data(attrs[DEVLINK_ATTR_REGION_NAME]); 3514 region = devlink_region_get_by_name(devlink, region_name); 3515 if (!region) 3516 goto out_unlock; 3517 3518 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq, 3519 &devlink_nl_family, NLM_F_ACK | NLM_F_MULTI, 3520 DEVLINK_CMD_REGION_READ); 3521 if (!hdr) 3522 goto out_unlock; 3523 3524 err = devlink_nl_put_handle(skb, devlink); 3525 if (err) 3526 goto nla_put_failure; 3527 3528 err = nla_put_string(skb, DEVLINK_ATTR_REGION_NAME, region_name); 3529 if (err) 3530 goto nla_put_failure; 3531 3532 chunks_attr = nla_nest_start(skb, DEVLINK_ATTR_REGION_CHUNKS); 3533 if (!chunks_attr) 3534 goto nla_put_failure; 3535 3536 if (attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR] && 3537 attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]) { 3538 if (!start_offset) 3539 start_offset = 3540 nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); 3541 3542 end_offset = nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_ADDR]); 3543 end_offset += nla_get_u64(attrs[DEVLINK_ATTR_REGION_CHUNK_LEN]); 3544 dump = false; 3545 } 3546 3547 err = devlink_nl_region_read_snapshot_fill(skb, devlink, 3548 region, attrs, 3549 start_offset, 3550 end_offset, dump, 3551 &ret_offset); 3552 3553 if (err && err != -EMSGSIZE) 3554 goto nla_put_failure; 3555 3556 /* Check if there was any progress done to prevent infinite loop */ 3557 if (ret_offset == start_offset) 3558 goto nla_put_failure; 3559 3560 *((u64 *)&cb->args[0]) = ret_offset; 3561 3562 nla_nest_end(skb, chunks_attr); 3563 genlmsg_end(skb, hdr); 3564 mutex_unlock(&devlink->lock); 3565 mutex_unlock(&devlink_mutex); 3566 3567 return skb->len; 3568 3569nla_put_failure: 3570 genlmsg_cancel(skb, hdr); 3571out_unlock: 3572 mutex_unlock(&devlink->lock); 3573 mutex_unlock(&devlink_mutex); 3574out: 3575 return 0; 3576} 3577 3578static const struct nla_policy devlink_nl_policy[DEVLINK_ATTR_MAX + 1] = { 3579 [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING }, 3580 [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING }, 3581 [DEVLINK_ATTR_PORT_INDEX] = { .type = NLA_U32 }, 3582 [DEVLINK_ATTR_PORT_TYPE] = { .type = NLA_U16 }, 3583 [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NLA_U32 }, 3584 [DEVLINK_ATTR_SB_INDEX] = { .type = NLA_U32 }, 3585 [DEVLINK_ATTR_SB_POOL_INDEX] = { .type = NLA_U16 }, 3586 [DEVLINK_ATTR_SB_POOL_TYPE] = { .type = NLA_U8 }, 3587 [DEVLINK_ATTR_SB_POOL_SIZE] = { .type = NLA_U32 }, 3588 [DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE] = { .type = NLA_U8 }, 3589 [DEVLINK_ATTR_SB_THRESHOLD] = { .type = NLA_U32 }, 3590 [DEVLINK_ATTR_SB_TC_INDEX] = { .type = NLA_U16 }, 3591 [DEVLINK_ATTR_ESWITCH_MODE] = { .type = NLA_U16 }, 3592 [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = { .type = NLA_U8 }, 3593 [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = { .type = NLA_U8 }, 3594 [DEVLINK_ATTR_DPIPE_TABLE_NAME] = { .type = NLA_NUL_STRING }, 3595 [DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED] = { .type = NLA_U8 }, 3596 [DEVLINK_ATTR_RESOURCE_ID] = { .type = NLA_U64}, 3597 [DEVLINK_ATTR_RESOURCE_SIZE] = { .type = NLA_U64}, 3598 [DEVLINK_ATTR_PARAM_NAME] = { .type = NLA_NUL_STRING }, 3599 [DEVLINK_ATTR_PARAM_TYPE] = { .type = NLA_U8 }, 3600 [DEVLINK_ATTR_PARAM_VALUE_CMODE] = { .type = NLA_U8 }, 3601 [DEVLINK_ATTR_REGION_NAME] = { .type = NLA_NUL_STRING }, 3602 [DEVLINK_ATTR_REGION_SNAPSHOT_ID] = { .type = NLA_U32 }, 3603}; 3604 3605static const struct genl_ops devlink_nl_ops[] = { 3606 { 3607 .cmd = DEVLINK_CMD_GET, 3608 .doit = devlink_nl_cmd_get_doit, 3609 .dumpit = devlink_nl_cmd_get_dumpit, 3610 .policy = devlink_nl_policy, 3611 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3612 /* can be retrieved by unprivileged users */ 3613 }, 3614 { 3615 .cmd = DEVLINK_CMD_PORT_GET, 3616 .doit = devlink_nl_cmd_port_get_doit, 3617 .dumpit = devlink_nl_cmd_port_get_dumpit, 3618 .policy = devlink_nl_policy, 3619 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 3620 /* can be retrieved by unprivileged users */ 3621 }, 3622 { 3623 .cmd = DEVLINK_CMD_PORT_SET, 3624 .doit = devlink_nl_cmd_port_set_doit, 3625 .policy = devlink_nl_policy, 3626 .flags = GENL_ADMIN_PERM, 3627 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT, 3628 }, 3629 { 3630 .cmd = DEVLINK_CMD_PORT_SPLIT, 3631 .doit = devlink_nl_cmd_port_split_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_PORT_UNSPLIT, 3639 .doit = devlink_nl_cmd_port_unsplit_doit, 3640 .policy = devlink_nl_policy, 3641 .flags = GENL_ADMIN_PERM, 3642 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3643 DEVLINK_NL_FLAG_NO_LOCK, 3644 }, 3645 { 3646 .cmd = DEVLINK_CMD_SB_GET, 3647 .doit = devlink_nl_cmd_sb_get_doit, 3648 .dumpit = devlink_nl_cmd_sb_get_dumpit, 3649 .policy = devlink_nl_policy, 3650 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3651 DEVLINK_NL_FLAG_NEED_SB, 3652 /* can be retrieved by unprivileged users */ 3653 }, 3654 { 3655 .cmd = DEVLINK_CMD_SB_POOL_GET, 3656 .doit = devlink_nl_cmd_sb_pool_get_doit, 3657 .dumpit = devlink_nl_cmd_sb_pool_get_dumpit, 3658 .policy = devlink_nl_policy, 3659 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3660 DEVLINK_NL_FLAG_NEED_SB, 3661 /* can be retrieved by unprivileged users */ 3662 }, 3663 { 3664 .cmd = DEVLINK_CMD_SB_POOL_SET, 3665 .doit = devlink_nl_cmd_sb_pool_set_doit, 3666 .policy = devlink_nl_policy, 3667 .flags = GENL_ADMIN_PERM, 3668 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3669 DEVLINK_NL_FLAG_NEED_SB, 3670 }, 3671 { 3672 .cmd = DEVLINK_CMD_SB_PORT_POOL_GET, 3673 .doit = devlink_nl_cmd_sb_port_pool_get_doit, 3674 .dumpit = devlink_nl_cmd_sb_port_pool_get_dumpit, 3675 .policy = devlink_nl_policy, 3676 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 3677 DEVLINK_NL_FLAG_NEED_SB, 3678 /* can be retrieved by unprivileged users */ 3679 }, 3680 { 3681 .cmd = DEVLINK_CMD_SB_PORT_POOL_SET, 3682 .doit = devlink_nl_cmd_sb_port_pool_set_doit, 3683 .policy = devlink_nl_policy, 3684 .flags = GENL_ADMIN_PERM, 3685 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 3686 DEVLINK_NL_FLAG_NEED_SB, 3687 }, 3688 { 3689 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_GET, 3690 .doit = devlink_nl_cmd_sb_tc_pool_bind_get_doit, 3691 .dumpit = devlink_nl_cmd_sb_tc_pool_bind_get_dumpit, 3692 .policy = devlink_nl_policy, 3693 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 3694 DEVLINK_NL_FLAG_NEED_SB, 3695 /* can be retrieved by unprivileged users */ 3696 }, 3697 { 3698 .cmd = DEVLINK_CMD_SB_TC_POOL_BIND_SET, 3699 .doit = devlink_nl_cmd_sb_tc_pool_bind_set_doit, 3700 .policy = devlink_nl_policy, 3701 .flags = GENL_ADMIN_PERM, 3702 .internal_flags = DEVLINK_NL_FLAG_NEED_PORT | 3703 DEVLINK_NL_FLAG_NEED_SB, 3704 }, 3705 { 3706 .cmd = DEVLINK_CMD_SB_OCC_SNAPSHOT, 3707 .doit = devlink_nl_cmd_sb_occ_snapshot_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_SB_OCC_MAX_CLEAR, 3715 .doit = devlink_nl_cmd_sb_occ_max_clear_doit, 3716 .policy = devlink_nl_policy, 3717 .flags = GENL_ADMIN_PERM, 3718 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3719 DEVLINK_NL_FLAG_NEED_SB, 3720 }, 3721 { 3722 .cmd = DEVLINK_CMD_ESWITCH_GET, 3723 .doit = devlink_nl_cmd_eswitch_get_doit, 3724 .policy = devlink_nl_policy, 3725 .flags = GENL_ADMIN_PERM, 3726 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3727 }, 3728 { 3729 .cmd = DEVLINK_CMD_ESWITCH_SET, 3730 .doit = devlink_nl_cmd_eswitch_set_doit, 3731 .policy = devlink_nl_policy, 3732 .flags = GENL_ADMIN_PERM, 3733 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3734 DEVLINK_NL_FLAG_NO_LOCK, 3735 }, 3736 { 3737 .cmd = DEVLINK_CMD_DPIPE_TABLE_GET, 3738 .doit = devlink_nl_cmd_dpipe_table_get, 3739 .policy = devlink_nl_policy, 3740 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3741 /* can be retrieved by unprivileged users */ 3742 }, 3743 { 3744 .cmd = DEVLINK_CMD_DPIPE_ENTRIES_GET, 3745 .doit = devlink_nl_cmd_dpipe_entries_get, 3746 .policy = devlink_nl_policy, 3747 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3748 /* can be retrieved by unprivileged users */ 3749 }, 3750 { 3751 .cmd = DEVLINK_CMD_DPIPE_HEADERS_GET, 3752 .doit = devlink_nl_cmd_dpipe_headers_get, 3753 .policy = devlink_nl_policy, 3754 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3755 /* can be retrieved by unprivileged users */ 3756 }, 3757 { 3758 .cmd = DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET, 3759 .doit = devlink_nl_cmd_dpipe_table_counters_set, 3760 .policy = devlink_nl_policy, 3761 .flags = GENL_ADMIN_PERM, 3762 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3763 }, 3764 { 3765 .cmd = DEVLINK_CMD_RESOURCE_SET, 3766 .doit = devlink_nl_cmd_resource_set, 3767 .policy = devlink_nl_policy, 3768 .flags = GENL_ADMIN_PERM, 3769 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3770 }, 3771 { 3772 .cmd = DEVLINK_CMD_RESOURCE_DUMP, 3773 .doit = devlink_nl_cmd_resource_dump, 3774 .policy = devlink_nl_policy, 3775 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3776 /* can be retrieved by unprivileged users */ 3777 }, 3778 { 3779 .cmd = DEVLINK_CMD_RELOAD, 3780 .doit = devlink_nl_cmd_reload, 3781 .policy = devlink_nl_policy, 3782 .flags = GENL_ADMIN_PERM, 3783 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK | 3784 DEVLINK_NL_FLAG_NO_LOCK, 3785 }, 3786 { 3787 .cmd = DEVLINK_CMD_PARAM_GET, 3788 .doit = devlink_nl_cmd_param_get_doit, 3789 .dumpit = devlink_nl_cmd_param_get_dumpit, 3790 .policy = devlink_nl_policy, 3791 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3792 /* can be retrieved by unprivileged users */ 3793 }, 3794 { 3795 .cmd = DEVLINK_CMD_PARAM_SET, 3796 .doit = devlink_nl_cmd_param_set_doit, 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_GET, 3803 .doit = devlink_nl_cmd_region_get_doit, 3804 .dumpit = devlink_nl_cmd_region_get_dumpit, 3805 .policy = devlink_nl_policy, 3806 .flags = GENL_ADMIN_PERM, 3807 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3808 }, 3809 { 3810 .cmd = DEVLINK_CMD_REGION_DEL, 3811 .doit = devlink_nl_cmd_region_del, 3812 .policy = devlink_nl_policy, 3813 .flags = GENL_ADMIN_PERM, 3814 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3815 }, 3816 { 3817 .cmd = DEVLINK_CMD_REGION_READ, 3818 .dumpit = devlink_nl_cmd_region_read_dumpit, 3819 .policy = devlink_nl_policy, 3820 .flags = GENL_ADMIN_PERM, 3821 .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK, 3822 }, 3823}; 3824 3825static struct genl_family devlink_nl_family __ro_after_init = { 3826 .name = DEVLINK_GENL_NAME, 3827 .version = DEVLINK_GENL_VERSION, 3828 .maxattr = DEVLINK_ATTR_MAX, 3829 .netnsok = true, 3830 .pre_doit = devlink_nl_pre_doit, 3831 .post_doit = devlink_nl_post_doit, 3832 .module = THIS_MODULE, 3833 .ops = devlink_nl_ops, 3834 .n_ops = ARRAY_SIZE(devlink_nl_ops), 3835 .mcgrps = devlink_nl_mcgrps, 3836 .n_mcgrps = ARRAY_SIZE(devlink_nl_mcgrps), 3837}; 3838 3839/** 3840 * devlink_alloc - Allocate new devlink instance resources 3841 * 3842 * @ops: ops 3843 * @priv_size: size of user private data 3844 * 3845 * Allocate new devlink instance resources, including devlink index 3846 * and name. 3847 */ 3848struct devlink *devlink_alloc(const struct devlink_ops *ops, size_t priv_size) 3849{ 3850 struct devlink *devlink; 3851 3852 devlink = kzalloc(sizeof(*devlink) + priv_size, GFP_KERNEL); 3853 if (!devlink) 3854 return NULL; 3855 devlink->ops = ops; 3856 devlink_net_set(devlink, &init_net); 3857 INIT_LIST_HEAD(&devlink->port_list); 3858 INIT_LIST_HEAD(&devlink->sb_list); 3859 INIT_LIST_HEAD_RCU(&devlink->dpipe_table_list); 3860 INIT_LIST_HEAD(&devlink->resource_list); 3861 INIT_LIST_HEAD(&devlink->param_list); 3862 INIT_LIST_HEAD(&devlink->region_list); 3863 mutex_init(&devlink->lock); 3864 return devlink; 3865} 3866EXPORT_SYMBOL_GPL(devlink_alloc); 3867 3868/** 3869 * devlink_register - Register devlink instance 3870 * 3871 * @devlink: devlink 3872 */ 3873int devlink_register(struct devlink *devlink, struct device *dev) 3874{ 3875 mutex_lock(&devlink_mutex); 3876 devlink->dev = dev; 3877 list_add_tail(&devlink->list, &devlink_list); 3878 devlink_notify(devlink, DEVLINK_CMD_NEW); 3879 mutex_unlock(&devlink_mutex); 3880 return 0; 3881} 3882EXPORT_SYMBOL_GPL(devlink_register); 3883 3884/** 3885 * devlink_unregister - Unregister devlink instance 3886 * 3887 * @devlink: devlink 3888 */ 3889void devlink_unregister(struct devlink *devlink) 3890{ 3891 mutex_lock(&devlink_mutex); 3892 devlink_notify(devlink, DEVLINK_CMD_DEL); 3893 list_del(&devlink->list); 3894 mutex_unlock(&devlink_mutex); 3895} 3896EXPORT_SYMBOL_GPL(devlink_unregister); 3897 3898/** 3899 * devlink_free - Free devlink instance resources 3900 * 3901 * @devlink: devlink 3902 */ 3903void devlink_free(struct devlink *devlink) 3904{ 3905 kfree(devlink); 3906} 3907EXPORT_SYMBOL_GPL(devlink_free); 3908 3909/** 3910 * devlink_port_register - Register devlink port 3911 * 3912 * @devlink: devlink 3913 * @devlink_port: devlink port 3914 * @port_index 3915 * 3916 * Register devlink port with provided port index. User can use 3917 * any indexing, even hw-related one. devlink_port structure 3918 * is convenient to be embedded inside user driver private structure. 3919 * Note that the caller should take care of zeroing the devlink_port 3920 * structure. 3921 */ 3922int devlink_port_register(struct devlink *devlink, 3923 struct devlink_port *devlink_port, 3924 unsigned int port_index) 3925{ 3926 mutex_lock(&devlink->lock); 3927 if (devlink_port_index_exists(devlink, port_index)) { 3928 mutex_unlock(&devlink->lock); 3929 return -EEXIST; 3930 } 3931 devlink_port->devlink = devlink; 3932 devlink_port->index = port_index; 3933 devlink_port->registered = true; 3934 list_add_tail(&devlink_port->list, &devlink->port_list); 3935 mutex_unlock(&devlink->lock); 3936 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 3937 return 0; 3938} 3939EXPORT_SYMBOL_GPL(devlink_port_register); 3940 3941/** 3942 * devlink_port_unregister - Unregister devlink port 3943 * 3944 * @devlink_port: devlink port 3945 */ 3946void devlink_port_unregister(struct devlink_port *devlink_port) 3947{ 3948 struct devlink *devlink = devlink_port->devlink; 3949 3950 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_DEL); 3951 mutex_lock(&devlink->lock); 3952 list_del(&devlink_port->list); 3953 mutex_unlock(&devlink->lock); 3954} 3955EXPORT_SYMBOL_GPL(devlink_port_unregister); 3956 3957static void __devlink_port_type_set(struct devlink_port *devlink_port, 3958 enum devlink_port_type type, 3959 void *type_dev) 3960{ 3961 devlink_port->type = type; 3962 devlink_port->type_dev = type_dev; 3963 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 3964} 3965 3966/** 3967 * devlink_port_type_eth_set - Set port type to Ethernet 3968 * 3969 * @devlink_port: devlink port 3970 * @netdev: related netdevice 3971 */ 3972void devlink_port_type_eth_set(struct devlink_port *devlink_port, 3973 struct net_device *netdev) 3974{ 3975 return __devlink_port_type_set(devlink_port, 3976 DEVLINK_PORT_TYPE_ETH, netdev); 3977} 3978EXPORT_SYMBOL_GPL(devlink_port_type_eth_set); 3979 3980/** 3981 * devlink_port_type_ib_set - Set port type to InfiniBand 3982 * 3983 * @devlink_port: devlink port 3984 * @ibdev: related IB device 3985 */ 3986void devlink_port_type_ib_set(struct devlink_port *devlink_port, 3987 struct ib_device *ibdev) 3988{ 3989 return __devlink_port_type_set(devlink_port, 3990 DEVLINK_PORT_TYPE_IB, ibdev); 3991} 3992EXPORT_SYMBOL_GPL(devlink_port_type_ib_set); 3993 3994/** 3995 * devlink_port_type_clear - Clear port type 3996 * 3997 * @devlink_port: devlink port 3998 */ 3999void devlink_port_type_clear(struct devlink_port *devlink_port) 4000{ 4001 return __devlink_port_type_set(devlink_port, 4002 DEVLINK_PORT_TYPE_NOTSET, NULL); 4003} 4004EXPORT_SYMBOL_GPL(devlink_port_type_clear); 4005 4006/** 4007 * devlink_port_attrs_set - Set port attributes 4008 * 4009 * @devlink_port: devlink port 4010 * @flavour: flavour of the port 4011 * @port_number: number of the port that is facing user, for example 4012 * the front panel port number 4013 * @split: indicates if this is split port 4014 * @split_subport_number: if the port is split, this is the number 4015 * of subport. 4016 */ 4017void devlink_port_attrs_set(struct devlink_port *devlink_port, 4018 enum devlink_port_flavour flavour, 4019 u32 port_number, bool split, 4020 u32 split_subport_number) 4021{ 4022 struct devlink_port_attrs *attrs = &devlink_port->attrs; 4023 4024 attrs->set = true; 4025 attrs->flavour = flavour; 4026 attrs->port_number = port_number; 4027 attrs->split = split; 4028 attrs->split_subport_number = split_subport_number; 4029 devlink_port_notify(devlink_port, DEVLINK_CMD_PORT_NEW); 4030} 4031EXPORT_SYMBOL_GPL(devlink_port_attrs_set); 4032 4033int devlink_port_get_phys_port_name(struct devlink_port *devlink_port, 4034 char *name, size_t len) 4035{ 4036 struct devlink_port_attrs *attrs = &devlink_port->attrs; 4037 int n = 0; 4038 4039 if (!attrs->set) 4040 return -EOPNOTSUPP; 4041 4042 switch (attrs->flavour) { 4043 case DEVLINK_PORT_FLAVOUR_PHYSICAL: 4044 if (!attrs->split) 4045 n = snprintf(name, len, "p%u", attrs->port_number); 4046 else 4047 n = snprintf(name, len, "p%us%u", attrs->port_number, 4048 attrs->split_subport_number); 4049 break; 4050 case DEVLINK_PORT_FLAVOUR_CPU: 4051 case DEVLINK_PORT_FLAVOUR_DSA: 4052 /* As CPU and DSA ports do not have a netdevice associated 4053 * case should not ever happen. 4054 */ 4055 WARN_ON(1); 4056 return -EINVAL; 4057 } 4058 4059 if (n >= len) 4060 return -EINVAL; 4061 4062 return 0; 4063} 4064EXPORT_SYMBOL_GPL(devlink_port_get_phys_port_name); 4065 4066int devlink_sb_register(struct devlink *devlink, unsigned int sb_index, 4067 u32 size, u16 ingress_pools_count, 4068 u16 egress_pools_count, u16 ingress_tc_count, 4069 u16 egress_tc_count) 4070{ 4071 struct devlink_sb *devlink_sb; 4072 int err = 0; 4073 4074 mutex_lock(&devlink->lock); 4075 if (devlink_sb_index_exists(devlink, sb_index)) { 4076 err = -EEXIST; 4077 goto unlock; 4078 } 4079 4080 devlink_sb = kzalloc(sizeof(*devlink_sb), GFP_KERNEL); 4081 if (!devlink_sb) { 4082 err = -ENOMEM; 4083 goto unlock; 4084 } 4085 devlink_sb->index = sb_index; 4086 devlink_sb->size = size; 4087 devlink_sb->ingress_pools_count = ingress_pools_count; 4088 devlink_sb->egress_pools_count = egress_pools_count; 4089 devlink_sb->ingress_tc_count = ingress_tc_count; 4090 devlink_sb->egress_tc_count = egress_tc_count; 4091 list_add_tail(&devlink_sb->list, &devlink->sb_list); 4092unlock: 4093 mutex_unlock(&devlink->lock); 4094 return err; 4095} 4096EXPORT_SYMBOL_GPL(devlink_sb_register); 4097 4098void devlink_sb_unregister(struct devlink *devlink, unsigned int sb_index) 4099{ 4100 struct devlink_sb *devlink_sb; 4101 4102 mutex_lock(&devlink->lock); 4103 devlink_sb = devlink_sb_get_by_index(devlink, sb_index); 4104 WARN_ON(!devlink_sb); 4105 list_del(&devlink_sb->list); 4106 mutex_unlock(&devlink->lock); 4107 kfree(devlink_sb); 4108} 4109EXPORT_SYMBOL_GPL(devlink_sb_unregister); 4110 4111/** 4112 * devlink_dpipe_headers_register - register dpipe headers 4113 * 4114 * @devlink: devlink 4115 * @dpipe_headers: dpipe header array 4116 * 4117 * Register the headers supported by hardware. 4118 */ 4119int devlink_dpipe_headers_register(struct devlink *devlink, 4120 struct devlink_dpipe_headers *dpipe_headers) 4121{ 4122 mutex_lock(&devlink->lock); 4123 devlink->dpipe_headers = dpipe_headers; 4124 mutex_unlock(&devlink->lock); 4125 return 0; 4126} 4127EXPORT_SYMBOL_GPL(devlink_dpipe_headers_register); 4128 4129/** 4130 * devlink_dpipe_headers_unregister - unregister dpipe headers 4131 * 4132 * @devlink: devlink 4133 * 4134 * Unregister the headers supported by hardware. 4135 */ 4136void devlink_dpipe_headers_unregister(struct devlink *devlink) 4137{ 4138 mutex_lock(&devlink->lock); 4139 devlink->dpipe_headers = NULL; 4140 mutex_unlock(&devlink->lock); 4141} 4142EXPORT_SYMBOL_GPL(devlink_dpipe_headers_unregister); 4143 4144/** 4145 * devlink_dpipe_table_counter_enabled - check if counter allocation 4146 * required 4147 * @devlink: devlink 4148 * @table_name: tables name 4149 * 4150 * Used by driver to check if counter allocation is required. 4151 * After counter allocation is turned on the table entries 4152 * are updated to include counter statistics. 4153 * 4154 * After that point on the driver must respect the counter 4155 * state so that each entry added to the table is added 4156 * with a counter. 4157 */ 4158bool devlink_dpipe_table_counter_enabled(struct devlink *devlink, 4159 const char *table_name) 4160{ 4161 struct devlink_dpipe_table *table; 4162 bool enabled; 4163 4164 rcu_read_lock(); 4165 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 4166 table_name); 4167 enabled = false; 4168 if (table) 4169 enabled = table->counters_enabled; 4170 rcu_read_unlock(); 4171 return enabled; 4172} 4173EXPORT_SYMBOL_GPL(devlink_dpipe_table_counter_enabled); 4174 4175/** 4176 * devlink_dpipe_table_register - register dpipe table 4177 * 4178 * @devlink: devlink 4179 * @table_name: table name 4180 * @table_ops: table ops 4181 * @priv: priv 4182 * @counter_control_extern: external control for counters 4183 */ 4184int devlink_dpipe_table_register(struct devlink *devlink, 4185 const char *table_name, 4186 struct devlink_dpipe_table_ops *table_ops, 4187 void *priv, bool counter_control_extern) 4188{ 4189 struct devlink_dpipe_table *table; 4190 4191 if (devlink_dpipe_table_find(&devlink->dpipe_table_list, table_name)) 4192 return -EEXIST; 4193 4194 if (WARN_ON(!table_ops->size_get)) 4195 return -EINVAL; 4196 4197 table = kzalloc(sizeof(*table), GFP_KERNEL); 4198 if (!table) 4199 return -ENOMEM; 4200 4201 table->name = table_name; 4202 table->table_ops = table_ops; 4203 table->priv = priv; 4204 table->counter_control_extern = counter_control_extern; 4205 4206 mutex_lock(&devlink->lock); 4207 list_add_tail_rcu(&table->list, &devlink->dpipe_table_list); 4208 mutex_unlock(&devlink->lock); 4209 return 0; 4210} 4211EXPORT_SYMBOL_GPL(devlink_dpipe_table_register); 4212 4213/** 4214 * devlink_dpipe_table_unregister - unregister dpipe table 4215 * 4216 * @devlink: devlink 4217 * @table_name: table name 4218 */ 4219void devlink_dpipe_table_unregister(struct devlink *devlink, 4220 const char *table_name) 4221{ 4222 struct devlink_dpipe_table *table; 4223 4224 mutex_lock(&devlink->lock); 4225 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 4226 table_name); 4227 if (!table) 4228 goto unlock; 4229 list_del_rcu(&table->list); 4230 mutex_unlock(&devlink->lock); 4231 kfree_rcu(table, rcu); 4232 return; 4233unlock: 4234 mutex_unlock(&devlink->lock); 4235} 4236EXPORT_SYMBOL_GPL(devlink_dpipe_table_unregister); 4237 4238/** 4239 * devlink_resource_register - devlink resource register 4240 * 4241 * @devlink: devlink 4242 * @resource_name: resource's name 4243 * @top_hierarchy: top hierarchy 4244 * @reload_required: reload is required for new configuration to 4245 * apply 4246 * @resource_size: resource's size 4247 * @resource_id: resource's id 4248 * @parent_reosurce_id: resource's parent id 4249 * @size params: size parameters 4250 */ 4251int devlink_resource_register(struct devlink *devlink, 4252 const char *resource_name, 4253 u64 resource_size, 4254 u64 resource_id, 4255 u64 parent_resource_id, 4256 const struct devlink_resource_size_params *size_params) 4257{ 4258 struct devlink_resource *resource; 4259 struct list_head *resource_list; 4260 bool top_hierarchy; 4261 int err = 0; 4262 4263 top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP; 4264 4265 mutex_lock(&devlink->lock); 4266 resource = devlink_resource_find(devlink, NULL, resource_id); 4267 if (resource) { 4268 err = -EINVAL; 4269 goto out; 4270 } 4271 4272 resource = kzalloc(sizeof(*resource), GFP_KERNEL); 4273 if (!resource) { 4274 err = -ENOMEM; 4275 goto out; 4276 } 4277 4278 if (top_hierarchy) { 4279 resource_list = &devlink->resource_list; 4280 } else { 4281 struct devlink_resource *parent_resource; 4282 4283 parent_resource = devlink_resource_find(devlink, NULL, 4284 parent_resource_id); 4285 if (parent_resource) { 4286 resource_list = &parent_resource->resource_list; 4287 resource->parent = parent_resource; 4288 } else { 4289 kfree(resource); 4290 err = -EINVAL; 4291 goto out; 4292 } 4293 } 4294 4295 resource->name = resource_name; 4296 resource->size = resource_size; 4297 resource->size_new = resource_size; 4298 resource->id = resource_id; 4299 resource->size_valid = true; 4300 memcpy(&resource->size_params, size_params, 4301 sizeof(resource->size_params)); 4302 INIT_LIST_HEAD(&resource->resource_list); 4303 list_add_tail(&resource->list, resource_list); 4304out: 4305 mutex_unlock(&devlink->lock); 4306 return err; 4307} 4308EXPORT_SYMBOL_GPL(devlink_resource_register); 4309 4310/** 4311 * devlink_resources_unregister - free all resources 4312 * 4313 * @devlink: devlink 4314 * @resource: resource 4315 */ 4316void devlink_resources_unregister(struct devlink *devlink, 4317 struct devlink_resource *resource) 4318{ 4319 struct devlink_resource *tmp, *child_resource; 4320 struct list_head *resource_list; 4321 4322 if (resource) 4323 resource_list = &resource->resource_list; 4324 else 4325 resource_list = &devlink->resource_list; 4326 4327 if (!resource) 4328 mutex_lock(&devlink->lock); 4329 4330 list_for_each_entry_safe(child_resource, tmp, resource_list, list) { 4331 devlink_resources_unregister(devlink, child_resource); 4332 list_del(&child_resource->list); 4333 kfree(child_resource); 4334 } 4335 4336 if (!resource) 4337 mutex_unlock(&devlink->lock); 4338} 4339EXPORT_SYMBOL_GPL(devlink_resources_unregister); 4340 4341/** 4342 * devlink_resource_size_get - get and update size 4343 * 4344 * @devlink: devlink 4345 * @resource_id: the requested resource id 4346 * @p_resource_size: ptr to update 4347 */ 4348int devlink_resource_size_get(struct devlink *devlink, 4349 u64 resource_id, 4350 u64 *p_resource_size) 4351{ 4352 struct devlink_resource *resource; 4353 int err = 0; 4354 4355 mutex_lock(&devlink->lock); 4356 resource = devlink_resource_find(devlink, NULL, resource_id); 4357 if (!resource) { 4358 err = -EINVAL; 4359 goto out; 4360 } 4361 *p_resource_size = resource->size_new; 4362 resource->size = resource->size_new; 4363out: 4364 mutex_unlock(&devlink->lock); 4365 return err; 4366} 4367EXPORT_SYMBOL_GPL(devlink_resource_size_get); 4368 4369/** 4370 * devlink_dpipe_table_resource_set - set the resource id 4371 * 4372 * @devlink: devlink 4373 * @table_name: table name 4374 * @resource_id: resource id 4375 * @resource_units: number of resource's units consumed per table's entry 4376 */ 4377int devlink_dpipe_table_resource_set(struct devlink *devlink, 4378 const char *table_name, u64 resource_id, 4379 u64 resource_units) 4380{ 4381 struct devlink_dpipe_table *table; 4382 int err = 0; 4383 4384 mutex_lock(&devlink->lock); 4385 table = devlink_dpipe_table_find(&devlink->dpipe_table_list, 4386 table_name); 4387 if (!table) { 4388 err = -EINVAL; 4389 goto out; 4390 } 4391 table->resource_id = resource_id; 4392 table->resource_units = resource_units; 4393 table->resource_valid = true; 4394out: 4395 mutex_unlock(&devlink->lock); 4396 return err; 4397} 4398EXPORT_SYMBOL_GPL(devlink_dpipe_table_resource_set); 4399 4400/** 4401 * devlink_resource_occ_get_register - register occupancy getter 4402 * 4403 * @devlink: devlink 4404 * @resource_id: resource id 4405 * @occ_get: occupancy getter callback 4406 * @occ_get_priv: occupancy getter callback priv 4407 */ 4408void devlink_resource_occ_get_register(struct devlink *devlink, 4409 u64 resource_id, 4410 devlink_resource_occ_get_t *occ_get, 4411 void *occ_get_priv) 4412{ 4413 struct devlink_resource *resource; 4414 4415 mutex_lock(&devlink->lock); 4416 resource = devlink_resource_find(devlink, NULL, resource_id); 4417 if (WARN_ON(!resource)) 4418 goto out; 4419 WARN_ON(resource->occ_get); 4420 4421 resource->occ_get = occ_get; 4422 resource->occ_get_priv = occ_get_priv; 4423out: 4424 mutex_unlock(&devlink->lock); 4425} 4426EXPORT_SYMBOL_GPL(devlink_resource_occ_get_register); 4427 4428/** 4429 * devlink_resource_occ_get_unregister - unregister occupancy getter 4430 * 4431 * @devlink: devlink 4432 * @resource_id: resource id 4433 */ 4434void devlink_resource_occ_get_unregister(struct devlink *devlink, 4435 u64 resource_id) 4436{ 4437 struct devlink_resource *resource; 4438 4439 mutex_lock(&devlink->lock); 4440 resource = devlink_resource_find(devlink, NULL, resource_id); 4441 if (WARN_ON(!resource)) 4442 goto out; 4443 WARN_ON(!resource->occ_get); 4444 4445 resource->occ_get = NULL; 4446 resource->occ_get_priv = NULL; 4447out: 4448 mutex_unlock(&devlink->lock); 4449} 4450EXPORT_SYMBOL_GPL(devlink_resource_occ_get_unregister); 4451 4452/** 4453 * devlink_params_register - register configuration parameters 4454 * 4455 * @devlink: devlink 4456 * @params: configuration parameters array 4457 * @params_count: number of parameters provided 4458 * 4459 * Register the configuration parameters supported by the driver. 4460 */ 4461int devlink_params_register(struct devlink *devlink, 4462 const struct devlink_param *params, 4463 size_t params_count) 4464{ 4465 const struct devlink_param *param = params; 4466 int i; 4467 int err; 4468 4469 mutex_lock(&devlink->lock); 4470 for (i = 0; i < params_count; i++, param++) { 4471 if (!param || !param->name || !param->supported_cmodes) { 4472 err = -EINVAL; 4473 goto rollback; 4474 } 4475 if (param->generic) { 4476 err = devlink_param_generic_verify(param); 4477 if (err) 4478 goto rollback; 4479 } else { 4480 err = devlink_param_driver_verify(param); 4481 if (err) 4482 goto rollback; 4483 } 4484 err = devlink_param_register_one(devlink, param); 4485 if (err) 4486 goto rollback; 4487 } 4488 4489 mutex_unlock(&devlink->lock); 4490 return 0; 4491 4492rollback: 4493 if (!i) 4494 goto unlock; 4495 for (param--; i > 0; i--, param--) 4496 devlink_param_unregister_one(devlink, param); 4497unlock: 4498 mutex_unlock(&devlink->lock); 4499 return err; 4500} 4501EXPORT_SYMBOL_GPL(devlink_params_register); 4502 4503/** 4504 * devlink_params_unregister - unregister configuration parameters 4505 * @devlink: devlink 4506 * @params: configuration parameters to unregister 4507 * @params_count: number of parameters provided 4508 */ 4509void devlink_params_unregister(struct devlink *devlink, 4510 const struct devlink_param *params, 4511 size_t params_count) 4512{ 4513 const struct devlink_param *param = params; 4514 int i; 4515 4516 mutex_lock(&devlink->lock); 4517 for (i = 0; i < params_count; i++, param++) 4518 devlink_param_unregister_one(devlink, param); 4519 mutex_unlock(&devlink->lock); 4520} 4521EXPORT_SYMBOL_GPL(devlink_params_unregister); 4522 4523/** 4524 * devlink_param_driverinit_value_get - get configuration parameter 4525 * value for driver initializing 4526 * 4527 * @devlink: devlink 4528 * @param_id: parameter ID 4529 * @init_val: value of parameter in driverinit configuration mode 4530 * 4531 * This function should be used by the driver to get driverinit 4532 * configuration for initialization after reload command. 4533 */ 4534int devlink_param_driverinit_value_get(struct devlink *devlink, u32 param_id, 4535 union devlink_param_value *init_val) 4536{ 4537 struct devlink_param_item *param_item; 4538 4539 if (!devlink->ops || !devlink->ops->reload) 4540 return -EOPNOTSUPP; 4541 4542 param_item = devlink_param_find_by_id(&devlink->param_list, param_id); 4543 if (!param_item) 4544 return -EINVAL; 4545 4546 if (!param_item->driverinit_value_valid || 4547 !devlink_param_cmode_is_supported(param_item->param, 4548 DEVLINK_PARAM_CMODE_DRIVERINIT)) 4549 return -EOPNOTSUPP; 4550 4551 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING) 4552 strcpy(init_val->vstr, param_item->driverinit_value.vstr); 4553 else 4554 *init_val = param_item->driverinit_value; 4555 4556 return 0; 4557} 4558EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_get); 4559 4560/** 4561 * devlink_param_driverinit_value_set - set value of configuration 4562 * parameter for driverinit 4563 * configuration mode 4564 * 4565 * @devlink: devlink 4566 * @param_id: parameter ID 4567 * @init_val: value of parameter to set for driverinit configuration mode 4568 * 4569 * This function should be used by the driver to set driverinit 4570 * configuration mode default value. 4571 */ 4572int devlink_param_driverinit_value_set(struct devlink *devlink, u32 param_id, 4573 union devlink_param_value init_val) 4574{ 4575 struct devlink_param_item *param_item; 4576 4577 param_item = devlink_param_find_by_id(&devlink->param_list, param_id); 4578 if (!param_item) 4579 return -EINVAL; 4580 4581 if (!devlink_param_cmode_is_supported(param_item->param, 4582 DEVLINK_PARAM_CMODE_DRIVERINIT)) 4583 return -EOPNOTSUPP; 4584 4585 if (param_item->param->type == DEVLINK_PARAM_TYPE_STRING) 4586 strcpy(param_item->driverinit_value.vstr, init_val.vstr); 4587 else 4588 param_item->driverinit_value = init_val; 4589 param_item->driverinit_value_valid = true; 4590 4591 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW); 4592 return 0; 4593} 4594EXPORT_SYMBOL_GPL(devlink_param_driverinit_value_set); 4595 4596/** 4597 * devlink_param_value_changed - notify devlink on a parameter's value 4598 * change. Should be called by the driver 4599 * right after the change. 4600 * 4601 * @devlink: devlink 4602 * @param_id: parameter ID 4603 * 4604 * This function should be used by the driver to notify devlink on value 4605 * change, excluding driverinit configuration mode. 4606 * For driverinit configuration mode driver should use the function 4607 * devlink_param_driverinit_value_set() instead. 4608 */ 4609void devlink_param_value_changed(struct devlink *devlink, u32 param_id) 4610{ 4611 struct devlink_param_item *param_item; 4612 4613 param_item = devlink_param_find_by_id(&devlink->param_list, param_id); 4614 WARN_ON(!param_item); 4615 4616 devlink_param_notify(devlink, param_item, DEVLINK_CMD_PARAM_NEW); 4617} 4618EXPORT_SYMBOL_GPL(devlink_param_value_changed); 4619 4620/** 4621 * devlink_param_value_str_fill - Safely fill-up the string preventing 4622 * from overflow of the preallocated buffer 4623 * 4624 * @dst_val: destination devlink_param_value 4625 * @src: source buffer 4626 */ 4627void devlink_param_value_str_fill(union devlink_param_value *dst_val, 4628 const char *src) 4629{ 4630 size_t len; 4631 4632 len = strlcpy(dst_val->vstr, src, __DEVLINK_PARAM_MAX_STRING_VALUE); 4633 WARN_ON(len >= __DEVLINK_PARAM_MAX_STRING_VALUE); 4634} 4635EXPORT_SYMBOL_GPL(devlink_param_value_str_fill); 4636 4637/** 4638 * devlink_region_create - create a new address region 4639 * 4640 * @devlink: devlink 4641 * @region_name: region name 4642 * @region_max_snapshots: Maximum supported number of snapshots for region 4643 * @region_size: size of region 4644 */ 4645struct devlink_region *devlink_region_create(struct devlink *devlink, 4646 const char *region_name, 4647 u32 region_max_snapshots, 4648 u64 region_size) 4649{ 4650 struct devlink_region *region; 4651 int err = 0; 4652 4653 mutex_lock(&devlink->lock); 4654 4655 if (devlink_region_get_by_name(devlink, region_name)) { 4656 err = -EEXIST; 4657 goto unlock; 4658 } 4659 4660 region = kzalloc(sizeof(*region), GFP_KERNEL); 4661 if (!region) { 4662 err = -ENOMEM; 4663 goto unlock; 4664 } 4665 4666 region->devlink = devlink; 4667 region->max_snapshots = region_max_snapshots; 4668 region->name = region_name; 4669 region->size = region_size; 4670 INIT_LIST_HEAD(&region->snapshot_list); 4671 list_add_tail(&region->list, &devlink->region_list); 4672 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_NEW); 4673 4674 mutex_unlock(&devlink->lock); 4675 return region; 4676 4677unlock: 4678 mutex_unlock(&devlink->lock); 4679 return ERR_PTR(err); 4680} 4681EXPORT_SYMBOL_GPL(devlink_region_create); 4682 4683/** 4684 * devlink_region_destroy - destroy address region 4685 * 4686 * @region: devlink region to destroy 4687 */ 4688void devlink_region_destroy(struct devlink_region *region) 4689{ 4690 struct devlink *devlink = region->devlink; 4691 struct devlink_snapshot *snapshot, *ts; 4692 4693 mutex_lock(&devlink->lock); 4694 4695 /* Free all snapshots of region */ 4696 list_for_each_entry_safe(snapshot, ts, &region->snapshot_list, list) 4697 devlink_region_snapshot_del(snapshot); 4698 4699 list_del(&region->list); 4700 4701 devlink_nl_region_notify(region, NULL, DEVLINK_CMD_REGION_DEL); 4702 mutex_unlock(&devlink->lock); 4703 kfree(region); 4704} 4705EXPORT_SYMBOL_GPL(devlink_region_destroy); 4706 4707/** 4708 * devlink_region_shapshot_id_get - get snapshot ID 4709 * 4710 * This callback should be called when adding a new snapshot, 4711 * Driver should use the same id for multiple snapshots taken 4712 * on multiple regions at the same time/by the same trigger. 4713 * 4714 * @devlink: devlink 4715 */ 4716u32 devlink_region_shapshot_id_get(struct devlink *devlink) 4717{ 4718 u32 id; 4719 4720 mutex_lock(&devlink->lock); 4721 id = ++devlink->snapshot_id; 4722 mutex_unlock(&devlink->lock); 4723 4724 return id; 4725} 4726EXPORT_SYMBOL_GPL(devlink_region_shapshot_id_get); 4727 4728/** 4729 * devlink_region_snapshot_create - create a new snapshot 4730 * This will add a new snapshot of a region. The snapshot 4731 * will be stored on the region struct and can be accessed 4732 * from devlink. This is useful for future analyses of snapshots. 4733 * Multiple snapshots can be created on a region. 4734 * The @snapshot_id should be obtained using the getter function. 4735 * 4736 * @devlink_region: devlink region of the snapshot 4737 * @data_len: size of snapshot data 4738 * @data: snapshot data 4739 * @snapshot_id: snapshot id to be created 4740 * @data_destructor: pointer to destructor function to free data 4741 */ 4742int devlink_region_snapshot_create(struct devlink_region *region, u64 data_len, 4743 u8 *data, u32 snapshot_id, 4744 devlink_snapshot_data_dest_t *data_destructor) 4745{ 4746 struct devlink *devlink = region->devlink; 4747 struct devlink_snapshot *snapshot; 4748 int err; 4749 4750 mutex_lock(&devlink->lock); 4751 4752 /* check if region can hold one more snapshot */ 4753 if (region->cur_snapshots == region->max_snapshots) { 4754 err = -ENOMEM; 4755 goto unlock; 4756 } 4757 4758 if (devlink_region_snapshot_get_by_id(region, snapshot_id)) { 4759 err = -EEXIST; 4760 goto unlock; 4761 } 4762 4763 snapshot = kzalloc(sizeof(*snapshot), GFP_KERNEL); 4764 if (!snapshot) { 4765 err = -ENOMEM; 4766 goto unlock; 4767 } 4768 4769 snapshot->id = snapshot_id; 4770 snapshot->region = region; 4771 snapshot->data = data; 4772 snapshot->data_len = data_len; 4773 snapshot->data_destructor = data_destructor; 4774 4775 list_add_tail(&snapshot->list, &region->snapshot_list); 4776 4777 region->cur_snapshots++; 4778 4779 devlink_nl_region_notify(region, snapshot, DEVLINK_CMD_REGION_NEW); 4780 mutex_unlock(&devlink->lock); 4781 return 0; 4782 4783unlock: 4784 mutex_unlock(&devlink->lock); 4785 return err; 4786} 4787EXPORT_SYMBOL_GPL(devlink_region_snapshot_create); 4788 4789static int __init devlink_module_init(void) 4790{ 4791 return genl_register_family(&devlink_nl_family); 4792} 4793 4794static void __exit devlink_module_exit(void) 4795{ 4796 genl_unregister_family(&devlink_nl_family); 4797} 4798 4799module_init(devlink_module_init); 4800module_exit(devlink_module_exit); 4801 4802MODULE_LICENSE("GPL v2"); 4803MODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>"); 4804MODULE_DESCRIPTION("Network physical device Netlink interface"); 4805MODULE_ALIAS_GENL_FAMILY(DEVLINK_GENL_NAME);