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