diff options
author | Andy Shevchenko <andriy.shevchenko@linux.intel.com> | 2021-05-17 15:29:43 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-06-15 17:14:36 +0200 |
commit | bbc8f3e79e9e35469ac87b0b3329729afc715885 (patch) | |
tree | f1b07afb8d1bc9501c1b5fd08e30b3b442c8f14c | |
parent | d826e0365199ccc084d6b757c966f4c8ca83d20b (diff) |
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>
-rw-r--r-- | drivers/base/devres.c | 30 |
1 files changed, 15 insertions, 15 deletions
diff --git a/drivers/base/devres.c b/drivers/base/devres.c index 8746f2212781..7970217191e0 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -503,28 +503,18 @@ static int remove_nodes(struct device *dev, return cnt; } -static int release_nodes(struct device *dev, struct list_head *first, - struct list_head *end, unsigned long flags) - __releases(&dev->devres_lock) +static void release_nodes(struct device *dev, struct list_head *todo) { - LIST_HEAD(todo); - int cnt; 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 * 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"); dr->node.release(dev, dr->data); 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) { unsigned long flags; + LIST_HEAD(todo); + int cnt; /* Looks like an uninitialized device structure */ if (WARN_ON(dev->devres_head.next == NULL)) return -ENODEV; + spin_lock_irqsave(&dev->devres_lock, flags); - return release_nodes(dev, dev->devres_head.next, &dev->devres_head, - flags); + cnt = remove_nodes(dev, dev->devres_head.next, &dev->devres_head, &todo); + 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; unsigned long flags; + LIST_HEAD(todo); int cnt = 0; 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)) 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 { WARN_ON(1); spin_unlock_irqrestore(&dev->devres_lock, flags); |