1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2016 Mellanox Technologies. All rights reserved. 4 * Copyright (c) 2016 Jiri Pirko <jiri@mellanox.com> 5 */ 6 7 #include "devl_internal.h" 8 9 static inline bool 10 devlink_rate_is_leaf(struct devlink_rate *devlink_rate) 11 { 12 return devlink_rate->type == DEVLINK_RATE_TYPE_LEAF; 13 } 14 15 static inline bool 16 devlink_rate_is_node(struct devlink_rate *devlink_rate) 17 { 18 return devlink_rate->type == DEVLINK_RATE_TYPE_NODE; 19 } 20 21 static struct devlink_rate * 22 devlink_rate_leaf_get_from_info(struct devlink *devlink, struct genl_info *info) 23 { 24 struct devlink_rate *devlink_rate; 25 struct devlink_port *devlink_port; 26 27 devlink_port = devlink_port_get_from_attrs(devlink, info->attrs); 28 if (IS_ERR(devlink_port)) 29 return ERR_CAST(devlink_port); 30 devlink_rate = devlink_port->devlink_rate; 31 return devlink_rate ?: ERR_PTR(-ENODEV); 32 } 33 34 static struct devlink_rate * 35 devlink_rate_node_get_by_name(struct devlink *devlink, const char *node_name) 36 { 37 static struct devlink_rate *devlink_rate; 38 39 list_for_each_entry(devlink_rate, &devlink->rate_list, list) { 40 if (devlink_rate_is_node(devlink_rate) && 41 !strcmp(node_name, devlink_rate->name)) 42 return devlink_rate; 43 } 44 return ERR_PTR(-ENODEV); 45 } 46 47 static struct devlink_rate * 48 devlink_rate_node_get_from_attrs(struct devlink *devlink, struct nlattr **attrs) 49 { 50 const char *rate_node_name; 51 size_t len; 52 53 if (!attrs[DEVLINK_ATTR_RATE_NODE_NAME]) 54 return ERR_PTR(-EINVAL); 55 rate_node_name = nla_data(attrs[DEVLINK_ATTR_RATE_NODE_NAME]); 56 len = strlen(rate_node_name); 57 /* Name cannot be empty or decimal number */ 58 if (!len || strspn(rate_node_name, "0123456789") == len) 59 return ERR_PTR(-EINVAL); 60 61 return devlink_rate_node_get_by_name(devlink, rate_node_name); 62 } 63 64 static struct devlink_rate * 65 devlink_rate_node_get_from_info(struct devlink *devlink, struct genl_info *info) 66 { 67 return devlink_rate_node_get_from_attrs(devlink, info->attrs); 68 } 69 70 static struct devlink_rate * 71 devlink_rate_get_from_info(struct devlink *devlink, struct genl_info *info) 72 { 73 struct nlattr **attrs = info->attrs; 74 75 if (attrs[DEVLINK_ATTR_PORT_INDEX]) 76 return devlink_rate_leaf_get_from_info(devlink, info); 77 else if (attrs[DEVLINK_ATTR_RATE_NODE_NAME]) 78 return devlink_rate_node_get_from_info(devlink, info); 79 else 80 return ERR_PTR(-EINVAL); 81 } 82 83 static int devlink_nl_rate_fill(struct sk_buff *msg, 84 struct devlink_rate *devlink_rate, 85 enum devlink_command cmd, u32 portid, u32 seq, 86 int flags, struct netlink_ext_ack *extack) 87 { 88 struct devlink *devlink = devlink_rate->devlink; 89 void *hdr; 90 91 hdr = genlmsg_put(msg, portid, seq, &devlink_nl_family, flags, cmd); 92 if (!hdr) 93 return -EMSGSIZE; 94 95 if (devlink_nl_put_handle(msg, devlink)) 96 goto nla_put_failure; 97 98 if (nla_put_u16(msg, DEVLINK_ATTR_RATE_TYPE, devlink_rate->type)) 99 goto nla_put_failure; 100 101 if (devlink_rate_is_leaf(devlink_rate)) { 102 if (nla_put_u32(msg, DEVLINK_ATTR_PORT_INDEX, 103 devlink_rate->devlink_port->index)) 104 goto nla_put_failure; 105 } else if (devlink_rate_is_node(devlink_rate)) { 106 if (nla_put_string(msg, DEVLINK_ATTR_RATE_NODE_NAME, 107 devlink_rate->name)) 108 goto nla_put_failure; 109 } 110 111 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_TX_SHARE, 112 devlink_rate->tx_share, DEVLINK_ATTR_PAD)) 113 goto nla_put_failure; 114 115 if (nla_put_u64_64bit(msg, DEVLINK_ATTR_RATE_TX_MAX, 116 devlink_rate->tx_max, DEVLINK_ATTR_PAD)) 117 goto nla_put_failure; 118 119 if (nla_put_u32(msg, DEVLINK_ATTR_RATE_TX_PRIORITY, 120 devlink_rate->tx_priority)) 121 goto nla_put_failure; 122 123 if (nla_put_u32(msg, DEVLINK_ATTR_RATE_TX_WEIGHT, 124 devlink_rate->tx_weight)) 125 goto nla_put_failure; 126 127 if (devlink_rate->parent) 128 if (nla_put_string(msg, DEVLINK_ATTR_RATE_PARENT_NODE_NAME, 129 devlink_rate->parent->name)) 130 goto nla_put_failure; 131 132 genlmsg_end(msg, hdr); 133 return 0; 134 135 nla_put_failure: 136 genlmsg_cancel(msg, hdr); 137 return -EMSGSIZE; 138 } 139 140 static void devlink_rate_notify(struct devlink_rate *devlink_rate, 141 enum devlink_command cmd) 142 { 143 struct devlink *devlink = devlink_rate->devlink; 144 struct sk_buff *msg; 145 int err; 146 147 WARN_ON(cmd != DEVLINK_CMD_RATE_NEW && cmd != DEVLINK_CMD_RATE_DEL); 148 149 if (!xa_get_mark(&devlinks, devlink->index, DEVLINK_REGISTERED)) 150 return; 151 152 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 153 if (!msg) 154 return; 155 156 err = devlink_nl_rate_fill(msg, devlink_rate, cmd, 0, 0, 0, NULL); 157 if (err) { 158 nlmsg_free(msg); 159 return; 160 } 161 162 genlmsg_multicast_netns(&devlink_nl_family, devlink_net(devlink), msg, 163 0, DEVLINK_MCGRP_CONFIG, GFP_KERNEL); 164 } 165 166 void devlink_rates_notify_register(struct devlink *devlink) 167 { 168 struct devlink_rate *rate_node; 169 170 list_for_each_entry(rate_node, &devlink->rate_list, list) 171 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW); 172 } 173 174 void devlink_rates_notify_unregister(struct devlink *devlink) 175 { 176 struct devlink_rate *rate_node; 177 178 list_for_each_entry_reverse(rate_node, &devlink->rate_list, list) 179 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_DEL); 180 } 181 182 static int 183 devlink_nl_rate_get_dump_one(struct sk_buff *msg, struct devlink *devlink, 184 struct netlink_callback *cb, int flags) 185 { 186 struct devlink_nl_dump_state *state = devlink_dump_state(cb); 187 struct devlink_rate *devlink_rate; 188 int idx = 0; 189 int err = 0; 190 191 list_for_each_entry(devlink_rate, &devlink->rate_list, list) { 192 enum devlink_command cmd = DEVLINK_CMD_RATE_NEW; 193 u32 id = NETLINK_CB(cb->skb).portid; 194 195 if (idx < state->idx) { 196 idx++; 197 continue; 198 } 199 err = devlink_nl_rate_fill(msg, devlink_rate, cmd, id, 200 cb->nlh->nlmsg_seq, flags, NULL); 201 if (err) { 202 state->idx = idx; 203 break; 204 } 205 idx++; 206 } 207 208 return err; 209 } 210 211 int devlink_nl_rate_get_dumpit(struct sk_buff *skb, struct netlink_callback *cb) 212 { 213 return devlink_nl_dumpit(skb, cb, devlink_nl_rate_get_dump_one); 214 } 215 216 int devlink_nl_rate_get_doit(struct sk_buff *skb, struct genl_info *info) 217 { 218 struct devlink *devlink = info->user_ptr[0]; 219 struct devlink_rate *devlink_rate; 220 struct sk_buff *msg; 221 int err; 222 223 devlink_rate = devlink_rate_get_from_info(devlink, info); 224 if (IS_ERR(devlink_rate)) 225 return PTR_ERR(devlink_rate); 226 227 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 228 if (!msg) 229 return -ENOMEM; 230 231 err = devlink_nl_rate_fill(msg, devlink_rate, DEVLINK_CMD_RATE_NEW, 232 info->snd_portid, info->snd_seq, 0, 233 info->extack); 234 if (err) { 235 nlmsg_free(msg); 236 return err; 237 } 238 239 return genlmsg_reply(msg, info); 240 } 241 242 static bool 243 devlink_rate_is_parent_node(struct devlink_rate *devlink_rate, 244 struct devlink_rate *parent) 245 { 246 while (parent) { 247 if (parent == devlink_rate) 248 return true; 249 parent = parent->parent; 250 } 251 return false; 252 } 253 254 static int 255 devlink_nl_rate_parent_node_set(struct devlink_rate *devlink_rate, 256 struct genl_info *info, 257 struct nlattr *nla_parent) 258 { 259 struct devlink *devlink = devlink_rate->devlink; 260 const char *parent_name = nla_data(nla_parent); 261 const struct devlink_ops *ops = devlink->ops; 262 size_t len = strlen(parent_name); 263 struct devlink_rate *parent; 264 int err = -EOPNOTSUPP; 265 266 parent = devlink_rate->parent; 267 268 if (parent && !len) { 269 if (devlink_rate_is_leaf(devlink_rate)) 270 err = ops->rate_leaf_parent_set(devlink_rate, NULL, 271 devlink_rate->priv, NULL, 272 info->extack); 273 else if (devlink_rate_is_node(devlink_rate)) 274 err = ops->rate_node_parent_set(devlink_rate, NULL, 275 devlink_rate->priv, NULL, 276 info->extack); 277 if (err) 278 return err; 279 280 refcount_dec(&parent->refcnt); 281 devlink_rate->parent = NULL; 282 } else if (len) { 283 parent = devlink_rate_node_get_by_name(devlink, parent_name); 284 if (IS_ERR(parent)) 285 return -ENODEV; 286 287 if (parent == devlink_rate) { 288 NL_SET_ERR_MSG(info->extack, "Parent to self is not allowed"); 289 return -EINVAL; 290 } 291 292 if (devlink_rate_is_node(devlink_rate) && 293 devlink_rate_is_parent_node(devlink_rate, parent->parent)) { 294 NL_SET_ERR_MSG(info->extack, "Node is already a parent of parent node."); 295 return -EEXIST; 296 } 297 298 if (devlink_rate_is_leaf(devlink_rate)) 299 err = ops->rate_leaf_parent_set(devlink_rate, parent, 300 devlink_rate->priv, parent->priv, 301 info->extack); 302 else if (devlink_rate_is_node(devlink_rate)) 303 err = ops->rate_node_parent_set(devlink_rate, parent, 304 devlink_rate->priv, parent->priv, 305 info->extack); 306 if (err) 307 return err; 308 309 if (devlink_rate->parent) 310 /* we're reassigning to other parent in this case */ 311 refcount_dec(&devlink_rate->parent->refcnt); 312 313 refcount_inc(&parent->refcnt); 314 devlink_rate->parent = parent; 315 } 316 317 return 0; 318 } 319 320 static int devlink_nl_rate_set(struct devlink_rate *devlink_rate, 321 const struct devlink_ops *ops, 322 struct genl_info *info) 323 { 324 struct nlattr *nla_parent, **attrs = info->attrs; 325 int err = -EOPNOTSUPP; 326 u32 priority; 327 u32 weight; 328 u64 rate; 329 330 if (attrs[DEVLINK_ATTR_RATE_TX_SHARE]) { 331 rate = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_SHARE]); 332 if (devlink_rate_is_leaf(devlink_rate)) 333 err = ops->rate_leaf_tx_share_set(devlink_rate, devlink_rate->priv, 334 rate, info->extack); 335 else if (devlink_rate_is_node(devlink_rate)) 336 err = ops->rate_node_tx_share_set(devlink_rate, devlink_rate->priv, 337 rate, info->extack); 338 if (err) 339 return err; 340 devlink_rate->tx_share = rate; 341 } 342 343 if (attrs[DEVLINK_ATTR_RATE_TX_MAX]) { 344 rate = nla_get_u64(attrs[DEVLINK_ATTR_RATE_TX_MAX]); 345 if (devlink_rate_is_leaf(devlink_rate)) 346 err = ops->rate_leaf_tx_max_set(devlink_rate, devlink_rate->priv, 347 rate, info->extack); 348 else if (devlink_rate_is_node(devlink_rate)) 349 err = ops->rate_node_tx_max_set(devlink_rate, devlink_rate->priv, 350 rate, info->extack); 351 if (err) 352 return err; 353 devlink_rate->tx_max = rate; 354 } 355 356 if (attrs[DEVLINK_ATTR_RATE_TX_PRIORITY]) { 357 priority = nla_get_u32(attrs[DEVLINK_ATTR_RATE_TX_PRIORITY]); 358 if (devlink_rate_is_leaf(devlink_rate)) 359 err = ops->rate_leaf_tx_priority_set(devlink_rate, devlink_rate->priv, 360 priority, info->extack); 361 else if (devlink_rate_is_node(devlink_rate)) 362 err = ops->rate_node_tx_priority_set(devlink_rate, devlink_rate->priv, 363 priority, info->extack); 364 365 if (err) 366 return err; 367 devlink_rate->tx_priority = priority; 368 } 369 370 if (attrs[DEVLINK_ATTR_RATE_TX_WEIGHT]) { 371 weight = nla_get_u32(attrs[DEVLINK_ATTR_RATE_TX_WEIGHT]); 372 if (devlink_rate_is_leaf(devlink_rate)) 373 err = ops->rate_leaf_tx_weight_set(devlink_rate, devlink_rate->priv, 374 weight, info->extack); 375 else if (devlink_rate_is_node(devlink_rate)) 376 err = ops->rate_node_tx_weight_set(devlink_rate, devlink_rate->priv, 377 weight, info->extack); 378 379 if (err) 380 return err; 381 devlink_rate->tx_weight = weight; 382 } 383 384 nla_parent = attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME]; 385 if (nla_parent) { 386 err = devlink_nl_rate_parent_node_set(devlink_rate, info, 387 nla_parent); 388 if (err) 389 return err; 390 } 391 392 return 0; 393 } 394 395 static bool devlink_rate_set_ops_supported(const struct devlink_ops *ops, 396 struct genl_info *info, 397 enum devlink_rate_type type) 398 { 399 struct nlattr **attrs = info->attrs; 400 401 if (type == DEVLINK_RATE_TYPE_LEAF) { 402 if (attrs[DEVLINK_ATTR_RATE_TX_SHARE] && !ops->rate_leaf_tx_share_set) { 403 NL_SET_ERR_MSG(info->extack, "TX share set isn't supported for the leafs"); 404 return false; 405 } 406 if (attrs[DEVLINK_ATTR_RATE_TX_MAX] && !ops->rate_leaf_tx_max_set) { 407 NL_SET_ERR_MSG(info->extack, "TX max set isn't supported for the leafs"); 408 return false; 409 } 410 if (attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] && 411 !ops->rate_leaf_parent_set) { 412 NL_SET_ERR_MSG(info->extack, "Parent set isn't supported for the leafs"); 413 return false; 414 } 415 if (attrs[DEVLINK_ATTR_RATE_TX_PRIORITY] && !ops->rate_leaf_tx_priority_set) { 416 NL_SET_ERR_MSG_ATTR(info->extack, 417 attrs[DEVLINK_ATTR_RATE_TX_PRIORITY], 418 "TX priority set isn't supported for the leafs"); 419 return false; 420 } 421 if (attrs[DEVLINK_ATTR_RATE_TX_WEIGHT] && !ops->rate_leaf_tx_weight_set) { 422 NL_SET_ERR_MSG_ATTR(info->extack, 423 attrs[DEVLINK_ATTR_RATE_TX_WEIGHT], 424 "TX weight set isn't supported for the leafs"); 425 return false; 426 } 427 } else if (type == DEVLINK_RATE_TYPE_NODE) { 428 if (attrs[DEVLINK_ATTR_RATE_TX_SHARE] && !ops->rate_node_tx_share_set) { 429 NL_SET_ERR_MSG(info->extack, "TX share set isn't supported for the nodes"); 430 return false; 431 } 432 if (attrs[DEVLINK_ATTR_RATE_TX_MAX] && !ops->rate_node_tx_max_set) { 433 NL_SET_ERR_MSG(info->extack, "TX max set isn't supported for the nodes"); 434 return false; 435 } 436 if (attrs[DEVLINK_ATTR_RATE_PARENT_NODE_NAME] && 437 !ops->rate_node_parent_set) { 438 NL_SET_ERR_MSG(info->extack, "Parent set isn't supported for the nodes"); 439 return false; 440 } 441 if (attrs[DEVLINK_ATTR_RATE_TX_PRIORITY] && !ops->rate_node_tx_priority_set) { 442 NL_SET_ERR_MSG_ATTR(info->extack, 443 attrs[DEVLINK_ATTR_RATE_TX_PRIORITY], 444 "TX priority set isn't supported for the nodes"); 445 return false; 446 } 447 if (attrs[DEVLINK_ATTR_RATE_TX_WEIGHT] && !ops->rate_node_tx_weight_set) { 448 NL_SET_ERR_MSG_ATTR(info->extack, 449 attrs[DEVLINK_ATTR_RATE_TX_WEIGHT], 450 "TX weight set isn't supported for the nodes"); 451 return false; 452 } 453 } else { 454 WARN(1, "Unknown type of rate object"); 455 return false; 456 } 457 458 return true; 459 } 460 461 int devlink_nl_cmd_rate_set_doit(struct sk_buff *skb, struct genl_info *info) 462 { 463 struct devlink *devlink = info->user_ptr[0]; 464 struct devlink_rate *devlink_rate; 465 const struct devlink_ops *ops; 466 int err; 467 468 devlink_rate = devlink_rate_get_from_info(devlink, info); 469 if (IS_ERR(devlink_rate)) 470 return PTR_ERR(devlink_rate); 471 472 ops = devlink->ops; 473 if (!ops || !devlink_rate_set_ops_supported(ops, info, devlink_rate->type)) 474 return -EOPNOTSUPP; 475 476 err = devlink_nl_rate_set(devlink_rate, ops, info); 477 478 if (!err) 479 devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_NEW); 480 return err; 481 } 482 483 int devlink_nl_cmd_rate_new_doit(struct sk_buff *skb, struct genl_info *info) 484 { 485 struct devlink *devlink = info->user_ptr[0]; 486 struct devlink_rate *rate_node; 487 const struct devlink_ops *ops; 488 int err; 489 490 ops = devlink->ops; 491 if (!ops || !ops->rate_node_new || !ops->rate_node_del) { 492 NL_SET_ERR_MSG(info->extack, "Rate nodes aren't supported"); 493 return -EOPNOTSUPP; 494 } 495 496 if (!devlink_rate_set_ops_supported(ops, info, DEVLINK_RATE_TYPE_NODE)) 497 return -EOPNOTSUPP; 498 499 rate_node = devlink_rate_node_get_from_attrs(devlink, info->attrs); 500 if (!IS_ERR(rate_node)) 501 return -EEXIST; 502 else if (rate_node == ERR_PTR(-EINVAL)) 503 return -EINVAL; 504 505 rate_node = kzalloc(sizeof(*rate_node), GFP_KERNEL); 506 if (!rate_node) 507 return -ENOMEM; 508 509 rate_node->devlink = devlink; 510 rate_node->type = DEVLINK_RATE_TYPE_NODE; 511 rate_node->name = nla_strdup(info->attrs[DEVLINK_ATTR_RATE_NODE_NAME], GFP_KERNEL); 512 if (!rate_node->name) { 513 err = -ENOMEM; 514 goto err_strdup; 515 } 516 517 err = ops->rate_node_new(rate_node, &rate_node->priv, info->extack); 518 if (err) 519 goto err_node_new; 520 521 err = devlink_nl_rate_set(rate_node, ops, info); 522 if (err) 523 goto err_rate_set; 524 525 refcount_set(&rate_node->refcnt, 1); 526 list_add(&rate_node->list, &devlink->rate_list); 527 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW); 528 return 0; 529 530 err_rate_set: 531 ops->rate_node_del(rate_node, rate_node->priv, info->extack); 532 err_node_new: 533 kfree(rate_node->name); 534 err_strdup: 535 kfree(rate_node); 536 return err; 537 } 538 539 int devlink_nl_cmd_rate_del_doit(struct sk_buff *skb, struct genl_info *info) 540 { 541 struct devlink *devlink = info->user_ptr[0]; 542 struct devlink_rate *rate_node; 543 int err; 544 545 rate_node = devlink_rate_node_get_from_info(devlink, info); 546 if (IS_ERR(rate_node)) 547 return PTR_ERR(rate_node); 548 549 if (refcount_read(&rate_node->refcnt) > 1) { 550 NL_SET_ERR_MSG(info->extack, "Node has children. Cannot delete node."); 551 return -EBUSY; 552 } 553 554 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_DEL); 555 err = devlink->ops->rate_node_del(rate_node, rate_node->priv, 556 info->extack); 557 if (rate_node->parent) 558 refcount_dec(&rate_node->parent->refcnt); 559 list_del(&rate_node->list); 560 kfree(rate_node->name); 561 kfree(rate_node); 562 return err; 563 } 564 565 int devlink_rate_nodes_check(struct devlink *devlink, u16 mode, 566 struct netlink_ext_ack *extack) 567 { 568 struct devlink_rate *devlink_rate; 569 570 list_for_each_entry(devlink_rate, &devlink->rate_list, list) 571 if (devlink_rate_is_node(devlink_rate)) { 572 NL_SET_ERR_MSG(extack, "Rate node(s) exists."); 573 return -EBUSY; 574 } 575 return 0; 576 } 577 578 /** 579 * devl_rate_node_create - create devlink rate node 580 * @devlink: devlink instance 581 * @priv: driver private data 582 * @node_name: name of the resulting node 583 * @parent: parent devlink_rate struct 584 * 585 * Create devlink rate object of type node 586 */ 587 struct devlink_rate * 588 devl_rate_node_create(struct devlink *devlink, void *priv, char *node_name, 589 struct devlink_rate *parent) 590 { 591 struct devlink_rate *rate_node; 592 593 rate_node = devlink_rate_node_get_by_name(devlink, node_name); 594 if (!IS_ERR(rate_node)) 595 return ERR_PTR(-EEXIST); 596 597 rate_node = kzalloc(sizeof(*rate_node), GFP_KERNEL); 598 if (!rate_node) 599 return ERR_PTR(-ENOMEM); 600 601 if (parent) { 602 rate_node->parent = parent; 603 refcount_inc(&rate_node->parent->refcnt); 604 } 605 606 rate_node->type = DEVLINK_RATE_TYPE_NODE; 607 rate_node->devlink = devlink; 608 rate_node->priv = priv; 609 610 rate_node->name = kstrdup(node_name, GFP_KERNEL); 611 if (!rate_node->name) { 612 kfree(rate_node); 613 return ERR_PTR(-ENOMEM); 614 } 615 616 refcount_set(&rate_node->refcnt, 1); 617 list_add(&rate_node->list, &devlink->rate_list); 618 devlink_rate_notify(rate_node, DEVLINK_CMD_RATE_NEW); 619 return rate_node; 620 } 621 EXPORT_SYMBOL_GPL(devl_rate_node_create); 622 623 /** 624 * devl_rate_leaf_create - create devlink rate leaf 625 * @devlink_port: devlink port object to create rate object on 626 * @priv: driver private data 627 * @parent: parent devlink_rate struct 628 * 629 * Create devlink rate object of type leaf on provided @devlink_port. 630 */ 631 int devl_rate_leaf_create(struct devlink_port *devlink_port, void *priv, 632 struct devlink_rate *parent) 633 { 634 struct devlink *devlink = devlink_port->devlink; 635 struct devlink_rate *devlink_rate; 636 637 devl_assert_locked(devlink_port->devlink); 638 639 if (WARN_ON(devlink_port->devlink_rate)) 640 return -EBUSY; 641 642 devlink_rate = kzalloc(sizeof(*devlink_rate), GFP_KERNEL); 643 if (!devlink_rate) 644 return -ENOMEM; 645 646 if (parent) { 647 devlink_rate->parent = parent; 648 refcount_inc(&devlink_rate->parent->refcnt); 649 } 650 651 devlink_rate->type = DEVLINK_RATE_TYPE_LEAF; 652 devlink_rate->devlink = devlink; 653 devlink_rate->devlink_port = devlink_port; 654 devlink_rate->priv = priv; 655 list_add_tail(&devlink_rate->list, &devlink->rate_list); 656 devlink_port->devlink_rate = devlink_rate; 657 devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_NEW); 658 659 return 0; 660 } 661 EXPORT_SYMBOL_GPL(devl_rate_leaf_create); 662 663 /** 664 * devl_rate_leaf_destroy - destroy devlink rate leaf 665 * 666 * @devlink_port: devlink port linked to the rate object 667 * 668 * Destroy the devlink rate object of type leaf on provided @devlink_port. 669 */ 670 void devl_rate_leaf_destroy(struct devlink_port *devlink_port) 671 { 672 struct devlink_rate *devlink_rate = devlink_port->devlink_rate; 673 674 devl_assert_locked(devlink_port->devlink); 675 if (!devlink_rate) 676 return; 677 678 devlink_rate_notify(devlink_rate, DEVLINK_CMD_RATE_DEL); 679 if (devlink_rate->parent) 680 refcount_dec(&devlink_rate->parent->refcnt); 681 list_del(&devlink_rate->list); 682 devlink_port->devlink_rate = NULL; 683 kfree(devlink_rate); 684 } 685 EXPORT_SYMBOL_GPL(devl_rate_leaf_destroy); 686 687 /** 688 * devl_rate_nodes_destroy - destroy all devlink rate nodes on device 689 * @devlink: devlink instance 690 * 691 * Unset parent for all rate objects and destroy all rate nodes 692 * on specified device. 693 */ 694 void devl_rate_nodes_destroy(struct devlink *devlink) 695 { 696 static struct devlink_rate *devlink_rate, *tmp; 697 const struct devlink_ops *ops = devlink->ops; 698 699 devl_assert_locked(devlink); 700 701 list_for_each_entry(devlink_rate, &devlink->rate_list, list) { 702 if (!devlink_rate->parent) 703 continue; 704 705 refcount_dec(&devlink_rate->parent->refcnt); 706 if (devlink_rate_is_leaf(devlink_rate)) 707 ops->rate_leaf_parent_set(devlink_rate, NULL, devlink_rate->priv, 708 NULL, NULL); 709 else if (devlink_rate_is_node(devlink_rate)) 710 ops->rate_node_parent_set(devlink_rate, NULL, devlink_rate->priv, 711 NULL, NULL); 712 } 713 list_for_each_entry_safe(devlink_rate, tmp, &devlink->rate_list, list) { 714 if (devlink_rate_is_node(devlink_rate)) { 715 ops->rate_node_del(devlink_rate, devlink_rate->priv, NULL); 716 list_del(&devlink_rate->list); 717 kfree(devlink_rate->name); 718 kfree(devlink_rate); 719 } 720 } 721 } 722 EXPORT_SYMBOL_GPL(devl_rate_nodes_destroy); 723