rate.c 20 KB

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