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 /**
10 * struct devlink_resource - devlink resource
11 * @name: name of the resource
12 * @id: id, per devlink instance
13 * @size: size of the resource
14 * @size_new: updated size of the resource, reload is needed
15 * @size_valid: valid in case the total size of the resource is valid
16 * including its children
17 * @parent: parent resource
18 * @size_params: size parameters
19 * @list: parent list
20 * @resource_list: list of child resources
21 * @occ_get: occupancy getter callback
22 * @occ_get_priv: occupancy getter callback priv
23 */
24 struct devlink_resource {
25 const char *name;
26 u64 id;
27 u64 size;
28 u64 size_new;
29 bool size_valid;
30 struct devlink_resource *parent;
31 struct devlink_resource_size_params size_params;
32 struct list_head list;
33 struct list_head resource_list;
34 devlink_resource_occ_get_t *occ_get;
35 void *occ_get_priv;
36 };
37
38 static struct devlink_resource *
__devlink_resource_find(struct list_head * resource_list_head,struct devlink_resource * resource,u64 resource_id)39 __devlink_resource_find(struct list_head *resource_list_head,
40 struct devlink_resource *resource,
41 u64 resource_id)
42 {
43 struct list_head *resource_list;
44
45 if (resource)
46 resource_list = &resource->resource_list;
47 else
48 resource_list = resource_list_head;
49
50 list_for_each_entry(resource, resource_list, list) {
51 struct devlink_resource *child_resource;
52
53 if (resource->id == resource_id)
54 return resource;
55
56 child_resource = __devlink_resource_find(resource_list_head,
57 resource,
58 resource_id);
59 if (child_resource)
60 return child_resource;
61 }
62 return NULL;
63 }
64
65 static struct devlink_resource *
devlink_resource_find(struct devlink * devlink,struct devlink_resource * resource,u64 resource_id)66 devlink_resource_find(struct devlink *devlink,
67 struct devlink_resource *resource, u64 resource_id)
68 {
69 return __devlink_resource_find(&devlink->resource_list,
70 resource, resource_id);
71 }
72
73 static void
devlink_resource_validate_children(struct devlink_resource * resource)74 devlink_resource_validate_children(struct devlink_resource *resource)
75 {
76 struct devlink_resource *child_resource;
77 bool size_valid = true;
78 u64 parts_size = 0;
79
80 if (list_empty(&resource->resource_list))
81 goto out;
82
83 list_for_each_entry(child_resource, &resource->resource_list, list)
84 parts_size += child_resource->size_new;
85
86 if (parts_size > resource->size_new)
87 size_valid = false;
88 out:
89 resource->size_valid = size_valid;
90 }
91
92 static int
devlink_resource_validate_size(struct devlink_resource * resource,u64 size,struct netlink_ext_ack * extack)93 devlink_resource_validate_size(struct devlink_resource *resource, u64 size,
94 struct netlink_ext_ack *extack)
95 {
96 u64 reminder;
97 int err = 0;
98
99 if (size > resource->size_params.size_max) {
100 NL_SET_ERR_MSG(extack, "Size larger than maximum");
101 err = -EINVAL;
102 }
103
104 if (size < resource->size_params.size_min) {
105 NL_SET_ERR_MSG(extack, "Size smaller than minimum");
106 err = -EINVAL;
107 }
108
109 div64_u64_rem(size, resource->size_params.size_granularity, &reminder);
110 if (reminder) {
111 NL_SET_ERR_MSG(extack, "Wrong granularity");
112 err = -EINVAL;
113 }
114
115 return err;
116 }
117
devlink_nl_resource_set_doit(struct sk_buff * skb,struct genl_info * info)118 int devlink_nl_resource_set_doit(struct sk_buff *skb, struct genl_info *info)
119 {
120 struct devlink *devlink = devlink_nl_ctx(info)->devlink;
121 struct devlink_resource *resource;
122 u64 resource_id;
123 u64 size;
124 int err;
125
126 if (GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_RESOURCE_ID) ||
127 GENL_REQ_ATTR_CHECK(info, DEVLINK_ATTR_RESOURCE_SIZE))
128 return -EINVAL;
129 resource_id = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_ID]);
130
131 resource = devlink_resource_find(devlink, NULL, resource_id);
132 if (!resource)
133 return -EINVAL;
134
135 size = nla_get_u64(info->attrs[DEVLINK_ATTR_RESOURCE_SIZE]);
136 err = devlink_resource_validate_size(resource, size, info->extack);
137 if (err)
138 return err;
139
140 resource->size_new = size;
141 devlink_resource_validate_children(resource);
142 if (resource->parent)
143 devlink_resource_validate_children(resource->parent);
144 return 0;
145 }
146
147 static int
devlink_resource_size_params_put(struct devlink_resource * resource,struct sk_buff * skb)148 devlink_resource_size_params_put(struct devlink_resource *resource,
149 struct sk_buff *skb)
150 {
151 struct devlink_resource_size_params *size_params;
152
153 size_params = &resource->size_params;
154 if (devlink_nl_put_u64(skb, DEVLINK_ATTR_RESOURCE_SIZE_GRAN,
155 size_params->size_granularity) ||
156 devlink_nl_put_u64(skb, DEVLINK_ATTR_RESOURCE_SIZE_MAX,
157 size_params->size_max) ||
158 devlink_nl_put_u64(skb, DEVLINK_ATTR_RESOURCE_SIZE_MIN,
159 size_params->size_min) ||
160 nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_UNIT, size_params->unit))
161 return -EMSGSIZE;
162 return 0;
163 }
164
devlink_resource_occ_put(struct devlink_resource * resource,struct sk_buff * skb)165 static int devlink_resource_occ_put(struct devlink_resource *resource,
166 struct sk_buff *skb)
167 {
168 if (!resource->occ_get)
169 return 0;
170 return devlink_nl_put_u64(skb, DEVLINK_ATTR_RESOURCE_OCC,
171 resource->occ_get(resource->occ_get_priv));
172 }
173
devlink_resource_put(struct devlink * devlink,struct sk_buff * skb,struct devlink_resource * resource)174 static int devlink_resource_put(struct devlink *devlink, struct sk_buff *skb,
175 struct devlink_resource *resource)
176 {
177 struct devlink_resource *child_resource;
178 struct nlattr *child_resource_attr;
179 struct nlattr *resource_attr;
180
181 resource_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_RESOURCE);
182 if (!resource_attr)
183 return -EMSGSIZE;
184
185 if (nla_put_string(skb, DEVLINK_ATTR_RESOURCE_NAME, resource->name) ||
186 devlink_nl_put_u64(skb, DEVLINK_ATTR_RESOURCE_SIZE, resource->size) ||
187 devlink_nl_put_u64(skb, DEVLINK_ATTR_RESOURCE_ID, resource->id))
188 goto nla_put_failure;
189 if (resource->size != resource->size_new &&
190 devlink_nl_put_u64(skb, DEVLINK_ATTR_RESOURCE_SIZE_NEW,
191 resource->size_new))
192 goto nla_put_failure;
193 if (devlink_resource_occ_put(resource, skb))
194 goto nla_put_failure;
195 if (devlink_resource_size_params_put(resource, skb))
196 goto nla_put_failure;
197 if (list_empty(&resource->resource_list))
198 goto out;
199
200 if (nla_put_u8(skb, DEVLINK_ATTR_RESOURCE_SIZE_VALID,
201 resource->size_valid))
202 goto nla_put_failure;
203
204 child_resource_attr = nla_nest_start_noflag(skb,
205 DEVLINK_ATTR_RESOURCE_LIST);
206 if (!child_resource_attr)
207 goto nla_put_failure;
208
209 list_for_each_entry(child_resource, &resource->resource_list, list) {
210 if (devlink_resource_put(devlink, skb, child_resource))
211 goto resource_put_failure;
212 }
213
214 nla_nest_end(skb, child_resource_attr);
215 out:
216 nla_nest_end(skb, resource_attr);
217 return 0;
218
219 resource_put_failure:
220 nla_nest_cancel(skb, child_resource_attr);
221 nla_put_failure:
222 nla_nest_cancel(skb, resource_attr);
223 return -EMSGSIZE;
224 }
225
devlink_resource_list_fill(struct sk_buff * skb,struct devlink * devlink,struct list_head * resource_list_head,int * idx)226 static int devlink_resource_list_fill(struct sk_buff *skb,
227 struct devlink *devlink,
228 struct list_head *resource_list_head,
229 int *idx)
230 {
231 struct devlink_resource *resource;
232 int i = 0;
233 int err;
234
235 list_for_each_entry(resource, resource_list_head, list) {
236 if (i < *idx) {
237 i++;
238 continue;
239 }
240 err = devlink_resource_put(devlink, skb, resource);
241 if (err) {
242 *idx = i;
243 return err;
244 }
245 i++;
246 }
247 *idx = 0;
248 return 0;
249 }
250
devlink_resource_fill(struct genl_info * info,enum devlink_command cmd,int flags)251 static int devlink_resource_fill(struct genl_info *info,
252 enum devlink_command cmd, int flags)
253 {
254 struct devlink_nl_ctx *ctx = devlink_nl_ctx(info);
255 struct devlink *devlink = ctx->devlink;
256 struct devlink_port *devlink_port;
257 struct devlink_resource *resource;
258 struct list_head *resource_list;
259 struct nlattr *resources_attr;
260 struct sk_buff *skb = NULL;
261 struct nlmsghdr *nlh;
262 bool incomplete;
263 void *hdr;
264 int i;
265 int err;
266
267 devlink_port = ctx->devlink_port;
268 resource_list = devlink_port ?
269 &devlink_port->resource_list : &devlink->resource_list;
270 resource = list_first_entry(resource_list,
271 struct devlink_resource, list);
272 start_again:
273 err = devlink_nl_msg_reply_and_new(&skb, info);
274 if (err)
275 return err;
276
277 hdr = genlmsg_put(skb, info->snd_portid, info->snd_seq,
278 &devlink_nl_family, NLM_F_MULTI, cmd);
279 if (!hdr) {
280 nlmsg_free(skb);
281 return -EMSGSIZE;
282 }
283
284 if (devlink_nl_put_handle(skb, devlink))
285 goto nla_put_failure;
286 if (devlink_port &&
287 nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
288 goto nla_put_failure;
289
290 resources_attr = nla_nest_start_noflag(skb,
291 DEVLINK_ATTR_RESOURCE_LIST);
292 if (!resources_attr)
293 goto nla_put_failure;
294
295 incomplete = false;
296 i = 0;
297 list_for_each_entry_from(resource, resource_list, list) {
298 err = devlink_resource_put(devlink, skb, resource);
299 if (err) {
300 if (!i)
301 goto err_resource_put;
302 incomplete = true;
303 break;
304 }
305 i++;
306 }
307 nla_nest_end(skb, resources_attr);
308 genlmsg_end(skb, hdr);
309 if (incomplete)
310 goto start_again;
311 send_done:
312 nlh = nlmsg_put(skb, info->snd_portid, info->snd_seq,
313 NLMSG_DONE, 0, flags | NLM_F_MULTI);
314 if (!nlh) {
315 err = devlink_nl_msg_reply_and_new(&skb, info);
316 if (err)
317 return err;
318 goto send_done;
319 }
320 return genlmsg_reply(skb, info);
321
322 nla_put_failure:
323 err = -EMSGSIZE;
324 err_resource_put:
325 nlmsg_free(skb);
326 return err;
327 }
328
devlink_nl_resource_dump_doit(struct sk_buff * skb,struct genl_info * info)329 int devlink_nl_resource_dump_doit(struct sk_buff *skb, struct genl_info *info)
330 {
331 struct devlink_nl_ctx *ctx = devlink_nl_ctx(info);
332 struct devlink *devlink = ctx->devlink;
333 struct devlink_port *devlink_port;
334 struct list_head *resource_list;
335
336 devlink_port = ctx->devlink_port;
337 if (info->attrs[DEVLINK_ATTR_PORT_INDEX] && !devlink_port)
338 return -ENODEV;
339
340 resource_list = devlink_port ?
341 &devlink_port->resource_list : &devlink->resource_list;
342 if (list_empty(resource_list))
343 return -EOPNOTSUPP;
344
345 return devlink_resource_fill(info, DEVLINK_CMD_RESOURCE_DUMP, 0);
346 }
347
348 static int
devlink_resource_dump_fill_one(struct sk_buff * skb,struct devlink * devlink,struct devlink_port * devlink_port,struct netlink_callback * cb,int flags,int * idx)349 devlink_resource_dump_fill_one(struct sk_buff *skb, struct devlink *devlink,
350 struct devlink_port *devlink_port,
351 struct netlink_callback *cb, int flags, int *idx)
352 {
353 struct list_head *resource_list;
354 struct nlattr *resources_attr;
355 int start_idx = *idx;
356 void *hdr;
357 int err;
358
359 resource_list = devlink_port ?
360 &devlink_port->resource_list : &devlink->resource_list;
361
362 if (list_empty(resource_list))
363 return 0;
364
365 err = -EMSGSIZE;
366 hdr = genlmsg_put(skb, NETLINK_CB(cb->skb).portid, cb->nlh->nlmsg_seq,
367 &devlink_nl_family, flags, DEVLINK_CMD_RESOURCE_DUMP);
368 if (!hdr)
369 return err;
370
371 if (devlink_nl_put_handle(skb, devlink))
372 goto nla_put_failure;
373 if (devlink_port &&
374 nla_put_u32(skb, DEVLINK_ATTR_PORT_INDEX, devlink_port->index))
375 goto nla_put_failure;
376
377 resources_attr = nla_nest_start_noflag(skb, DEVLINK_ATTR_RESOURCE_LIST);
378 if (!resources_attr)
379 goto nla_put_failure;
380
381 err = devlink_resource_list_fill(skb, devlink, resource_list, idx);
382 if (err) {
383 if (*idx == start_idx)
384 goto resource_list_cancel;
385 nla_nest_end(skb, resources_attr);
386 genlmsg_end(skb, hdr);
387 return err;
388 }
389 nla_nest_end(skb, resources_attr);
390 genlmsg_end(skb, hdr);
391 return 0;
392
393 resource_list_cancel:
394 nla_nest_cancel(skb, resources_attr);
395 nla_put_failure:
396 genlmsg_cancel(skb, hdr);
397 return err;
398 }
399
400 static int
devlink_nl_resource_dump_one(struct sk_buff * skb,struct devlink * devlink,struct netlink_callback * cb,int flags)401 devlink_nl_resource_dump_one(struct sk_buff *skb, struct devlink *devlink,
402 struct netlink_callback *cb, int flags)
403 {
404 struct devlink_nl_dump_state *state = devlink_dump_state(cb);
405 const struct genl_info *info = genl_info_dump(cb);
406 struct devlink_port *devlink_port;
407 struct nlattr *scope_attr = NULL;
408 unsigned long port_idx;
409 u32 scope = 0;
410 int err;
411
412 if (info->attrs && info->attrs[DEVLINK_ATTR_RESOURCE_SCOPE_MASK]) {
413 scope_attr = info->attrs[DEVLINK_ATTR_RESOURCE_SCOPE_MASK];
414 scope = nla_get_u32(scope_attr);
415 if (!scope) {
416 NL_SET_ERR_MSG_ATTR(info->extack, scope_attr,
417 "empty resource scope selection");
418 return -EINVAL;
419 }
420 }
421
422 if (!state->port_ctx.index_valid &&
423 (!scope || (scope & DEVLINK_RESOURCE_SCOPE_DEV))) {
424 err = devlink_resource_dump_fill_one(skb, devlink, NULL,
425 cb, flags, &state->idx);
426 if (err)
427 return err;
428 state->idx = 0;
429 }
430
431 if (scope && !(scope & DEVLINK_RESOURCE_SCOPE_PORT))
432 goto out;
433 /* Check in case port was removed between dump callbacks. */
434 if (state->port_ctx.index_valid &&
435 !xa_load(&devlink->ports, state->port_ctx.index))
436 state->idx = 0;
437 state->port_ctx.index_valid = true;
438 xa_for_each_start(&devlink->ports, port_idx, devlink_port,
439 state->port_ctx.index) {
440 err = devlink_resource_dump_fill_one(skb, devlink, devlink_port,
441 cb, flags, &state->idx);
442 if (err) {
443 state->port_ctx.index = port_idx;
444 return err;
445 }
446 state->idx = 0;
447 }
448 out:
449 state->port_ctx.index_valid = false;
450 state->port_ctx.index = 0;
451 return 0;
452 }
453
devlink_nl_resource_dump_dumpit(struct sk_buff * skb,struct netlink_callback * cb)454 int devlink_nl_resource_dump_dumpit(struct sk_buff *skb,
455 struct netlink_callback *cb)
456 {
457 return devlink_nl_dumpit(skb, cb, devlink_nl_resource_dump_one);
458 }
459
devlink_resources_validate(struct devlink * devlink,struct devlink_resource * resource,struct genl_info * info)460 int devlink_resources_validate(struct devlink *devlink,
461 struct devlink_resource *resource,
462 struct genl_info *info)
463 {
464 struct list_head *resource_list;
465 int err = 0;
466
467 if (resource)
468 resource_list = &resource->resource_list;
469 else
470 resource_list = &devlink->resource_list;
471
472 list_for_each_entry(resource, resource_list, list) {
473 if (!resource->size_valid)
474 return -EINVAL;
475 err = devlink_resources_validate(devlink, resource, info);
476 if (err)
477 return err;
478 }
479 return err;
480 }
481
482 static int
__devl_resource_register(struct devlink * devlink,struct list_head * resource_list_head,const char * resource_name,u64 resource_size,u64 resource_id,u64 parent_resource_id,const struct devlink_resource_size_params * params)483 __devl_resource_register(struct devlink *devlink,
484 struct list_head *resource_list_head,
485 const char *resource_name, u64 resource_size,
486 u64 resource_id, u64 parent_resource_id,
487 const struct devlink_resource_size_params *params)
488 {
489 struct devlink_resource *resource;
490 struct list_head *resource_list;
491 bool top_hierarchy;
492
493 WARN_ON(resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP);
494
495 lockdep_assert_held(&devlink->lock);
496
497 top_hierarchy = parent_resource_id == DEVLINK_RESOURCE_ID_PARENT_TOP;
498
499 resource = __devlink_resource_find(resource_list_head, NULL,
500 resource_id);
501 if (resource)
502 return -EEXIST;
503
504 resource = kzalloc_obj(*resource);
505 if (!resource)
506 return -ENOMEM;
507
508 if (top_hierarchy) {
509 resource_list = resource_list_head;
510 } else {
511 struct devlink_resource *parent_resource;
512
513 parent_resource = __devlink_resource_find(resource_list_head,
514 NULL,
515 parent_resource_id);
516 if (parent_resource) {
517 resource_list = &parent_resource->resource_list;
518 resource->parent = parent_resource;
519 } else {
520 kfree(resource);
521 return -EINVAL;
522 }
523 }
524
525 resource->name = resource_name;
526 resource->size = resource_size;
527 resource->size_new = resource_size;
528 resource->id = resource_id;
529 resource->size_valid = true;
530 memcpy(&resource->size_params, params, sizeof(resource->size_params));
531 INIT_LIST_HEAD(&resource->resource_list);
532 list_add_tail(&resource->list, resource_list);
533
534 return 0;
535 }
536
537 /**
538 * devl_resource_register - devlink resource register
539 *
540 * @devlink: devlink
541 * @resource_name: resource's name
542 * @resource_size: resource's size
543 * @resource_id: resource's id
544 * @parent_resource_id: resource's parent id
545 * @params: size parameters
546 *
547 * Generic resources should reuse the same names across drivers.
548 * Please see the generic resources list at:
549 * Documentation/networking/devlink/devlink-resource.rst
550 *
551 * Return: 0 on success, negative error code otherwise.
552 */
devl_resource_register(struct devlink * devlink,const char * resource_name,u64 resource_size,u64 resource_id,u64 parent_resource_id,const struct devlink_resource_size_params * params)553 int devl_resource_register(struct devlink *devlink, const char *resource_name,
554 u64 resource_size, u64 resource_id,
555 u64 parent_resource_id,
556 const struct devlink_resource_size_params *params)
557 {
558 return __devl_resource_register(devlink, &devlink->resource_list,
559 resource_name, resource_size,
560 resource_id, parent_resource_id,
561 params);
562 }
563 EXPORT_SYMBOL_GPL(devl_resource_register);
564
devlink_resource_unregister(struct devlink_resource * resource)565 static void devlink_resource_unregister(struct devlink_resource *resource)
566 {
567 struct devlink_resource *tmp, *child_resource;
568
569 list_for_each_entry_safe(child_resource, tmp, &resource->resource_list,
570 list) {
571 devlink_resource_unregister(child_resource);
572 list_del(&child_resource->list);
573 kfree(child_resource);
574 }
575 }
576
577 static void
__devl_resources_unregister(struct devlink * devlink,struct list_head * resource_list_head)578 __devl_resources_unregister(struct devlink *devlink,
579 struct list_head *resource_list_head)
580 {
581 struct devlink_resource *tmp, *child_resource;
582
583 lockdep_assert_held(&devlink->lock);
584
585 list_for_each_entry_safe(child_resource, tmp, resource_list_head,
586 list) {
587 devlink_resource_unregister(child_resource);
588 list_del(&child_resource->list);
589 kfree(child_resource);
590 }
591 }
592
593 /**
594 * devl_resources_unregister - free all resources
595 *
596 * @devlink: devlink
597 */
devl_resources_unregister(struct devlink * devlink)598 void devl_resources_unregister(struct devlink *devlink)
599 {
600 __devl_resources_unregister(devlink, &devlink->resource_list);
601 }
602 EXPORT_SYMBOL_GPL(devl_resources_unregister);
603
604 /**
605 * devlink_resources_unregister - free all resources
606 *
607 * @devlink: devlink
608 *
609 * Context: Takes and release devlink->lock <mutex>.
610 */
devlink_resources_unregister(struct devlink * devlink)611 void devlink_resources_unregister(struct devlink *devlink)
612 {
613 devl_lock(devlink);
614 devl_resources_unregister(devlink);
615 devl_unlock(devlink);
616 }
617 EXPORT_SYMBOL_GPL(devlink_resources_unregister);
618
619 /**
620 * devl_resource_size_get - get and update size
621 *
622 * @devlink: devlink
623 * @resource_id: the requested resource id
624 * @p_resource_size: ptr to update
625 */
devl_resource_size_get(struct devlink * devlink,u64 resource_id,u64 * p_resource_size)626 int devl_resource_size_get(struct devlink *devlink,
627 u64 resource_id,
628 u64 *p_resource_size)
629 {
630 struct devlink_resource *resource;
631
632 lockdep_assert_held(&devlink->lock);
633
634 resource = devlink_resource_find(devlink, NULL, resource_id);
635 if (!resource)
636 return -EINVAL;
637 *p_resource_size = resource->size_new;
638 resource->size = resource->size_new;
639 return 0;
640 }
641 EXPORT_SYMBOL_GPL(devl_resource_size_get);
642
643 /**
644 * devl_resource_occ_get_register - register occupancy getter
645 *
646 * @devlink: devlink
647 * @resource_id: resource id
648 * @occ_get: occupancy getter callback
649 * @occ_get_priv: occupancy getter callback priv
650 */
devl_resource_occ_get_register(struct devlink * devlink,u64 resource_id,devlink_resource_occ_get_t * occ_get,void * occ_get_priv)651 void devl_resource_occ_get_register(struct devlink *devlink,
652 u64 resource_id,
653 devlink_resource_occ_get_t *occ_get,
654 void *occ_get_priv)
655 {
656 struct devlink_resource *resource;
657
658 lockdep_assert_held(&devlink->lock);
659
660 resource = devlink_resource_find(devlink, NULL, resource_id);
661 if (WARN_ON(!resource))
662 return;
663 WARN_ON(resource->occ_get);
664
665 resource->occ_get = occ_get;
666 resource->occ_get_priv = occ_get_priv;
667 }
668 EXPORT_SYMBOL_GPL(devl_resource_occ_get_register);
669
670 /**
671 * devl_resource_occ_get_unregister - unregister occupancy getter
672 *
673 * @devlink: devlink
674 * @resource_id: resource id
675 */
devl_resource_occ_get_unregister(struct devlink * devlink,u64 resource_id)676 void devl_resource_occ_get_unregister(struct devlink *devlink,
677 u64 resource_id)
678 {
679 struct devlink_resource *resource;
680
681 lockdep_assert_held(&devlink->lock);
682
683 resource = devlink_resource_find(devlink, NULL, resource_id);
684 if (WARN_ON(!resource))
685 return;
686 WARN_ON(!resource->occ_get);
687
688 resource->occ_get = NULL;
689 resource->occ_get_priv = NULL;
690 }
691 EXPORT_SYMBOL_GPL(devl_resource_occ_get_unregister);
692
693 /**
694 * devl_port_resource_register - devlink port resource register
695 *
696 * @devlink_port: devlink port
697 * @resource_name: resource's name
698 * @resource_size: resource's size
699 * @resource_id: resource's id
700 * @parent_resource_id: resource's parent id
701 * @params: size parameters
702 *
703 * Generic resources should reuse the same names across drivers.
704 * Please see the generic resources list at:
705 * Documentation/networking/devlink/devlink-resource.rst
706 *
707 * Return: 0 on success, negative error code otherwise.
708 */
709 int
devl_port_resource_register(struct devlink_port * devlink_port,const char * resource_name,u64 resource_size,u64 resource_id,u64 parent_resource_id,const struct devlink_resource_size_params * params)710 devl_port_resource_register(struct devlink_port *devlink_port,
711 const char *resource_name,
712 u64 resource_size, u64 resource_id,
713 u64 parent_resource_id,
714 const struct devlink_resource_size_params *params)
715 {
716 return __devl_resource_register(devlink_port->devlink,
717 &devlink_port->resource_list,
718 resource_name, resource_size,
719 resource_id, parent_resource_id,
720 params);
721 }
722 EXPORT_SYMBOL_GPL(devl_port_resource_register);
723
724 /**
725 * devl_port_resources_unregister - unregister all devlink port resources
726 *
727 * @devlink_port: devlink port
728 */
devl_port_resources_unregister(struct devlink_port * devlink_port)729 void devl_port_resources_unregister(struct devlink_port *devlink_port)
730 {
731 __devl_resources_unregister(devlink_port->devlink,
732 &devlink_port->resource_list);
733 }
734 EXPORT_SYMBOL_GPL(devl_port_resources_unregister);
735