Lines Matching +full:cpu +full:- +full:release +full:- +full:addr
1 // SPDX-License-Identifier: GPL-2.0
3 * drivers/base/devres.c - device resource management
20 dr_release_t release; member
32 * the alignment of a 64-bit integer.
43 /* -- 8 pointers */
53 node->name = name; in set_node_dbginfo()
54 node->size = size; in set_node_dbginfo()
62 op, node, node->name, (unsigned long)node->size); in devres_log()
70 * Release functions for devres group. These callbacks are used only
85 if (node->release == &group_open_release) in node_to_group()
87 if (node->release == &group_close_release) in node_to_group()
94 /* We must catch any near-SIZE_MAX cases that could overflow. */ in check_dr_size()
102 static __always_inline struct devres * alloc_dr(dr_release_t release, in alloc_dr() argument
117 INIT_LIST_HEAD(&dr->node.entry); in alloc_dr()
118 dr->node.release = release; in alloc_dr()
125 BUG_ON(!list_empty(&node->entry)); in add_dr()
126 list_add_tail(&node->entry, &dev->devres_head); in add_dr()
133 BUG_ON(!list_empty(&new->entry)); in replace_dr()
134 list_replace(&old->entry, &new->entry); in replace_dr()
138 void * __devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, int nid, in __devres_alloc_node() argument
143 dr = alloc_dr(release, size, gfp | __GFP_ZERO, nid); in __devres_alloc_node()
146 set_node_dbginfo(&dr->node, name, size); in __devres_alloc_node()
147 return dr->data; in __devres_alloc_node()
152 * devres_alloc - Allocate device resource data
153 * @release: Release function devres will be associated with
159 * associated with @release. The returned pointer can be passed to
165 void * devres_alloc_node(dr_release_t release, size_t size, gfp_t gfp, int nid) in devres_alloc_node() argument
169 dr = alloc_dr(release, size, gfp | __GFP_ZERO, nid); in devres_alloc_node()
172 return dr->data; in devres_alloc_node()
178 * devres_for_each_res - Resource iterator
180 * @release: Look for resources associated with this release function
186 * Call @fn for each devres of @dev which is associated with @release
192 void devres_for_each_res(struct device *dev, dr_release_t release, in devres_for_each_res() argument
204 spin_lock_irqsave(&dev->devres_lock, flags); in devres_for_each_res()
206 &dev->devres_head, entry) { in devres_for_each_res()
209 if (node->release != release) in devres_for_each_res()
211 if (match && !match(dev, dr->data, match_data)) in devres_for_each_res()
213 fn(dev, dr->data, data); in devres_for_each_res()
215 spin_unlock_irqrestore(&dev->devres_lock, flags); in devres_for_each_res()
220 * devres_free - Free device resource data
230 BUG_ON(!list_empty(&dr->node.entry)); in devres_free()
237 * devres_add - Register device resource
242 * using devres_alloc(). On driver detach, the associated release
250 spin_lock_irqsave(&dev->devres_lock, flags); in devres_add()
251 add_dr(dev, &dr->node); in devres_add()
252 spin_unlock_irqrestore(&dev->devres_lock, flags); in devres_add()
256 static struct devres *find_dr(struct device *dev, dr_release_t release, in find_dr() argument
261 list_for_each_entry_reverse(node, &dev->devres_head, entry) { in find_dr()
264 if (node->release != release) in find_dr()
266 if (match && !match(dev, dr->data, match_data)) in find_dr()
275 * devres_find - Find device resource
277 * @release: Look for resources associated with this release function
281 * Find the latest devres of @dev which is associated with @release
288 void * devres_find(struct device *dev, dr_release_t release, in devres_find() argument
294 spin_lock_irqsave(&dev->devres_lock, flags); in devres_find()
295 dr = find_dr(dev, release, match, match_data); in devres_find()
296 spin_unlock_irqrestore(&dev->devres_lock, flags); in devres_find()
299 return dr->data; in devres_find()
305 * devres_get - Find devres, if non-existent, add one atomically
311 * Find the latest devres of @dev which has the same release function
325 spin_lock_irqsave(&dev->devres_lock, flags); in devres_get()
326 dr = find_dr(dev, new_dr->node.release, match, match_data); in devres_get()
328 add_dr(dev, &new_dr->node); in devres_get()
332 spin_unlock_irqrestore(&dev->devres_lock, flags); in devres_get()
335 return dr->data; in devres_get()
340 * devres_remove - Find a device resource and remove it
342 * @release: Look for resources associated with this release function
346 * Find the latest devres of @dev associated with @release and for
354 void * devres_remove(struct device *dev, dr_release_t release, in devres_remove() argument
360 spin_lock_irqsave(&dev->devres_lock, flags); in devres_remove()
361 dr = find_dr(dev, release, match, match_data); in devres_remove()
363 list_del_init(&dr->node.entry); in devres_remove()
364 devres_log(dev, &dr->node, "REM"); in devres_remove()
366 spin_unlock_irqrestore(&dev->devres_lock, flags); in devres_remove()
369 return dr->data; in devres_remove()
375 * devres_destroy - Find a device resource and destroy it
377 * @release: Look for resources associated with this release function
381 * Find the latest devres of @dev associated with @release and for
385 * Note that the release function for the resource will not be called,
386 * only the devres-allocated data will be freed. The caller becomes
390 * 0 if devres is found and freed, -ENOENT if not found.
392 int devres_destroy(struct device *dev, dr_release_t release, in devres_destroy() argument
397 res = devres_remove(dev, release, match, match_data); in devres_destroy()
399 return -ENOENT; in devres_destroy()
408 * devres_release - Find a device resource and destroy it, calling release
410 * @release: Look for resources associated with this release function
414 * Find the latest devres of @dev associated with @release and for
417 * release function called and the resource freed.
420 * 0 if devres is found and freed, -ENOENT if not found.
422 int devres_release(struct device *dev, dr_release_t release, in devres_release() argument
427 res = devres_remove(dev, release, match, match_data); in devres_release()
429 return -ENOENT; in devres_release()
431 (*release)(dev, res); in devres_release()
444 /* First pass - move normal devres entries to @todo and clear in remove_nodes()
453 cur = cur->next; in remove_nodes()
458 grp->color = 0; in remove_nodes()
462 if (&node->entry == first) in remove_nodes()
463 first = first->next; in remove_nodes()
464 list_move_tail(&node->entry, todo); in remove_nodes()
472 /* Second pass - Scan groups and color them. A group gets in remove_nodes()
484 cur = cur->next; in remove_nodes()
487 BUG_ON(!grp || list_empty(&grp->node[0].entry)); in remove_nodes()
489 grp->color++; in remove_nodes()
490 if (list_empty(&grp->node[1].entry)) in remove_nodes()
491 grp->color++; in remove_nodes()
493 BUG_ON(grp->color <= 0 || grp->color > 2); in remove_nodes()
494 if (grp->color == 2) { in remove_nodes()
498 list_move_tail(&grp->node[0].entry, todo); in remove_nodes()
499 list_del_init(&grp->node[1].entry); in remove_nodes()
508 __releases(&dev->devres_lock) in release_nodes()
516 spin_unlock_irqrestore(&dev->devres_lock, flags); in release_nodes()
518 /* Release. Note that both devres and devres_group are in release_nodes()
522 devres_log(dev, &dr->node, "REL"); in release_nodes()
523 dr->node.release(dev, dr->data); in release_nodes()
531 * devres_release_all - Release all managed resources
532 * @dev: Device to release resources for
534 * Release all resources associated with @dev. This function is
542 if (WARN_ON(dev->devres_head.next == NULL)) in devres_release_all()
543 return -ENODEV; in devres_release_all()
544 spin_lock_irqsave(&dev->devres_lock, flags); in devres_release_all()
545 return release_nodes(dev, dev->devres_head.next, &dev->devres_head, in devres_release_all()
550 * devres_open_group - Open a new devres group
557 * recommended. If @id is NULL, address-wise unique ID is created.
571 grp->node[0].release = &group_open_release; in devres_open_group()
572 grp->node[1].release = &group_close_release; in devres_open_group()
573 INIT_LIST_HEAD(&grp->node[0].entry); in devres_open_group()
574 INIT_LIST_HEAD(&grp->node[1].entry); in devres_open_group()
575 set_node_dbginfo(&grp->node[0], "grp<", 0); in devres_open_group()
576 set_node_dbginfo(&grp->node[1], "grp>", 0); in devres_open_group()
577 grp->id = grp; in devres_open_group()
579 grp->id = id; in devres_open_group()
581 spin_lock_irqsave(&dev->devres_lock, flags); in devres_open_group()
582 add_dr(dev, &grp->node[0]); in devres_open_group()
583 spin_unlock_irqrestore(&dev->devres_lock, flags); in devres_open_group()
584 return grp->id; in devres_open_group()
593 list_for_each_entry_reverse(node, &dev->devres_head, entry) { in find_group()
596 if (node->release != &group_open_release) in find_group()
602 if (grp->id == id) in find_group()
604 } else if (list_empty(&grp->node[1].entry)) in find_group()
612 * devres_close_group - Close a devres group
624 spin_lock_irqsave(&dev->devres_lock, flags); in devres_close_group()
628 add_dr(dev, &grp->node[1]); in devres_close_group()
632 spin_unlock_irqrestore(&dev->devres_lock, flags); in devres_close_group()
637 * devres_remove_group - Remove a devres group
650 spin_lock_irqsave(&dev->devres_lock, flags); in devres_remove_group()
654 list_del_init(&grp->node[0].entry); in devres_remove_group()
655 list_del_init(&grp->node[1].entry); in devres_remove_group()
656 devres_log(dev, &grp->node[0], "REM"); in devres_remove_group()
660 spin_unlock_irqrestore(&dev->devres_lock, flags); in devres_remove_group()
667 * devres_release_group - Release resources in a devres group
668 * @dev: Device to release group for
671 * Release all resources in the group identified by @id. If @id is
676 * The number of released non-group resources.
684 spin_lock_irqsave(&dev->devres_lock, flags); in devres_release_group()
688 struct list_head *first = &grp->node[0].entry; in devres_release_group()
689 struct list_head *end = &dev->devres_head; in devres_release_group()
691 if (!list_empty(&grp->node[1].entry)) in devres_release_group()
692 end = grp->node[1].entry.next; in devres_release_group()
697 spin_unlock_irqrestore(&dev->devres_lock, flags); in devres_release_group()
719 return devres->action == target->action && in devm_action_match()
720 devres->data == target->data; in devm_action_match()
727 devres->action(devres->data); in devm_action_release()
731 * devm_add_action() - add a custom action to list of managed resources
746 return -ENOMEM; in devm_add_action()
748 devres->data = data; in devm_add_action()
749 devres->action = action; in devm_add_action()
757 * devm_remove_action() - removes previously added custom action
778 * devm_release_action() - release previously added custom action
814 * devm_kmalloc - Resource-managed kmalloc
842 set_node_dbginfo(&dr->node, "devm_kzalloc_release", size); in devm_kmalloc()
843 devres_add(dev, dr->data); in devm_kmalloc()
844 return dr->data; in devm_kmalloc()
849 * devm_krealloc - Resource-managed krealloc()
850 * @dev: Device to re-allocate memory for
851 * @ptr: Pointer to the memory chunk to re-allocate
859 * change the order in which the release callback for the re-alloc'ed devres
896 * allocated previously - just return the same pointer. in devm_krealloc()
914 spin_lock_irqsave(&dev->devres_lock, flags); in devm_krealloc()
918 spin_unlock_irqrestore(&dev->devres_lock, flags); in devm_krealloc()
924 replace_dr(dev, &old_dr->node, &new_dr->node); in devm_krealloc()
926 spin_unlock_irqrestore(&dev->devres_lock, flags); in devm_krealloc()
932 memcpy(new_dr->data, old_dr->data, in devm_krealloc()
933 total_old_size - offsetof(struct devres, data)); in devm_krealloc()
935 * Same for releasing the old devres - it's now been removed from the in devm_krealloc()
936 * list. This is also the reason why we must not use devm_kfree() - the in devm_krealloc()
941 return new_dr->data; in devm_krealloc()
946 * devm_kstrdup - Allocate resource managed space and
972 * devm_kstrdup_const - resource managed conditional string duplication
994 * devm_kvasprintf - Allocate resource managed space and format a string
999 * @fmt: The printf()-style format string
1026 * devm_kasprintf - Allocate resource managed space and format a string
1031 * @fmt: The printf()-style format string
1050 * devm_kfree - Resource-managed kfree
1074 * devm_kmemdup - Resource-managed kmemdup
1095 unsigned long addr; member
1104 return devres->addr == target->addr; in devm_pages_match()
1111 free_pages(devres->addr, devres->order); in devm_pages_release()
1115 * devm_get_free_pages - Resource-managed __get_free_pages
1131 unsigned long addr; in devm_get_free_pages() local
1133 addr = __get_free_pages(gfp_mask, order); in devm_get_free_pages()
1135 if (unlikely(!addr)) in devm_get_free_pages()
1141 free_pages(addr, order); in devm_get_free_pages()
1145 devres->addr = addr; in devm_get_free_pages()
1146 devres->order = order; in devm_get_free_pages()
1149 return addr; in devm_get_free_pages()
1154 * devm_free_pages - Resource-managed free_pages
1156 * @addr: Memory to free
1161 void devm_free_pages(struct device *dev, unsigned long addr) in devm_free_pages() argument
1163 struct pages_devres devres = { .addr = addr }; in devm_free_pages()
1182 return *(void **)devr->data == p; in devm_percpu_match()
1186 * __devm_alloc_percpu - Resource-managed alloc_percpu
1187 * @dev: Device to allocate per-cpu memory for
1188 * @size: Size of per-cpu memory to allocate
1189 * @align: Alignment of per-cpu memory to allocate
1191 * Managed alloc_percpu. Per-cpu memory allocated with this function is
1222 * devm_free_percpu - Resource-managed free_percpu
1224 * @pdata: Per-cpu memory to free