devres: Make locking straight forward in release_nodes()
It seems for the sake of saving stack memory of couple of pointers, the locking in release_nodes() callers becomes interesting. Replace this logic with a straight forward locking and unlocking scheme. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://lore.kernel.org/r/20210517122946.53161-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
d826e03651
Коммит
bbc8f3e79e
|
@ -503,28 +503,18 @@ static int remove_nodes(struct device *dev,
|
||||||
return cnt;
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int release_nodes(struct device *dev, struct list_head *first,
|
static void release_nodes(struct device *dev, struct list_head *todo)
|
||||||
struct list_head *end, unsigned long flags)
|
|
||||||
__releases(&dev->devres_lock)
|
|
||||||
{
|
{
|
||||||
LIST_HEAD(todo);
|
|
||||||
int cnt;
|
|
||||||
struct devres *dr, *tmp;
|
struct devres *dr, *tmp;
|
||||||
|
|
||||||
cnt = remove_nodes(dev, first, end, &todo);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&dev->devres_lock, flags);
|
|
||||||
|
|
||||||
/* Release. Note that both devres and devres_group are
|
/* Release. Note that both devres and devres_group are
|
||||||
* handled as devres in the following loop. This is safe.
|
* handled as devres in the following loop. This is safe.
|
||||||
*/
|
*/
|
||||||
list_for_each_entry_safe_reverse(dr, tmp, &todo, node.entry) {
|
list_for_each_entry_safe_reverse(dr, tmp, todo, node.entry) {
|
||||||
devres_log(dev, &dr->node, "REL");
|
devres_log(dev, &dr->node, "REL");
|
||||||
dr->node.release(dev, dr->data);
|
dr->node.release(dev, dr->data);
|
||||||
kfree(dr);
|
kfree(dr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return cnt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -537,13 +527,19 @@ static int release_nodes(struct device *dev, struct list_head *first,
|
||||||
int devres_release_all(struct device *dev)
|
int devres_release_all(struct device *dev)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
LIST_HEAD(todo);
|
||||||
|
int cnt;
|
||||||
|
|
||||||
/* Looks like an uninitialized device structure */
|
/* Looks like an uninitialized device structure */
|
||||||
if (WARN_ON(dev->devres_head.next == NULL))
|
if (WARN_ON(dev->devres_head.next == NULL))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
spin_lock_irqsave(&dev->devres_lock, flags);
|
spin_lock_irqsave(&dev->devres_lock, flags);
|
||||||
return release_nodes(dev, dev->devres_head.next, &dev->devres_head,
|
cnt = remove_nodes(dev, dev->devres_head.next, &dev->devres_head, &todo);
|
||||||
flags);
|
spin_unlock_irqrestore(&dev->devres_lock, flags);
|
||||||
|
|
||||||
|
release_nodes(dev, &todo);
|
||||||
|
return cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -679,6 +675,7 @@ int devres_release_group(struct device *dev, void *id)
|
||||||
{
|
{
|
||||||
struct devres_group *grp;
|
struct devres_group *grp;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
LIST_HEAD(todo);
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
|
||||||
spin_lock_irqsave(&dev->devres_lock, flags);
|
spin_lock_irqsave(&dev->devres_lock, flags);
|
||||||
|
@ -691,7 +688,10 @@ int devres_release_group(struct device *dev, void *id)
|
||||||
if (!list_empty(&grp->node[1].entry))
|
if (!list_empty(&grp->node[1].entry))
|
||||||
end = grp->node[1].entry.next;
|
end = grp->node[1].entry.next;
|
||||||
|
|
||||||
cnt = release_nodes(dev, first, end, flags);
|
cnt = remove_nodes(dev, first, end, &todo);
|
||||||
|
spin_unlock_irqrestore(&dev->devres_lock, flags);
|
||||||
|
|
||||||
|
release_nodes(dev, &todo);
|
||||||
} else {
|
} else {
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
spin_unlock_irqrestore(&dev->devres_lock, flags);
|
spin_unlock_irqrestore(&dev->devres_lock, flags);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче