diff options
author | Geert Uytterhoeven <geert@linux-m68k.org> | 2013-10-29 05:03:04 -0400 |
---|---|---|
committer | Lee Jones <lee.jones@linaro.org> | 2013-11-11 06:22:15 -0500 |
commit | 03e361b25ee8dfb1fd9b890072c23c4aae01c6c7 (patch) | |
tree | 6adc9cb64eb9c7e7b84cb24880786aa0b9094d5a /drivers/mfd | |
parent | 24f76f37aab7cfd97e17976b41182817e887f0e1 (diff) |
mfd: Stop setting refcounting pointers in original mfd_cell arrays
Commit 1e29af62f2b285bd18685da93c3ce8c33ca2d1db ("mfd: Add refcounting
support to mfd_cells") had to drop the "const" keyword on the "cell"
parameter of mfd_add_devices(), as it added the refcounting pointers
to the objects of the passed mfd_cell array itself.
However, the mfd core code operates on copies of the mfd_cell objects,
so there's no need to modify the originally passed objects.
Hence, move the setting of the refcounting pointers from mfd_add_devices()
to mfd_platform_add_cell(), where the copy of the mfd_cell objects is made.
mfd_clone_cell() can just pass (a copy of) the original usage_count
pointer.
This allows to make the "cell" parameter of mfd_add_devices() "const"
again, and avoids future race conditions when registering multiple
instances of the same device in parallel.
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/mfd-core.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index f421586f29fb..8736f4539bc0 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c | |||
@@ -63,7 +63,8 @@ int mfd_cell_disable(struct platform_device *pdev) | |||
63 | EXPORT_SYMBOL(mfd_cell_disable); | 63 | EXPORT_SYMBOL(mfd_cell_disable); |
64 | 64 | ||
65 | static int mfd_platform_add_cell(struct platform_device *pdev, | 65 | static int mfd_platform_add_cell(struct platform_device *pdev, |
66 | const struct mfd_cell *cell) | 66 | const struct mfd_cell *cell, |
67 | atomic_t *usage_count) | ||
67 | { | 68 | { |
68 | if (!cell) | 69 | if (!cell) |
69 | return 0; | 70 | return 0; |
@@ -72,11 +73,12 @@ static int mfd_platform_add_cell(struct platform_device *pdev, | |||
72 | if (!pdev->mfd_cell) | 73 | if (!pdev->mfd_cell) |
73 | return -ENOMEM; | 74 | return -ENOMEM; |
74 | 75 | ||
76 | pdev->mfd_cell->usage_count = usage_count; | ||
75 | return 0; | 77 | return 0; |
76 | } | 78 | } |
77 | 79 | ||
78 | static int mfd_add_device(struct device *parent, int id, | 80 | static int mfd_add_device(struct device *parent, int id, |
79 | const struct mfd_cell *cell, | 81 | const struct mfd_cell *cell, atomic_t *usage_count, |
80 | struct resource *mem_base, | 82 | struct resource *mem_base, |
81 | int irq_base, struct irq_domain *domain) | 83 | int irq_base, struct irq_domain *domain) |
82 | { | 84 | { |
@@ -115,7 +117,7 @@ static int mfd_add_device(struct device *parent, int id, | |||
115 | goto fail_res; | 117 | goto fail_res; |
116 | } | 118 | } |
117 | 119 | ||
118 | ret = mfd_platform_add_cell(pdev, cell); | 120 | ret = mfd_platform_add_cell(pdev, cell, usage_count); |
119 | if (ret) | 121 | if (ret) |
120 | goto fail_res; | 122 | goto fail_res; |
121 | 123 | ||
@@ -180,7 +182,7 @@ fail_alloc: | |||
180 | } | 182 | } |
181 | 183 | ||
182 | int mfd_add_devices(struct device *parent, int id, | 184 | int mfd_add_devices(struct device *parent, int id, |
183 | struct mfd_cell *cells, int n_devs, | 185 | const struct mfd_cell *cells, int n_devs, |
184 | struct resource *mem_base, | 186 | struct resource *mem_base, |
185 | int irq_base, struct irq_domain *domain) | 187 | int irq_base, struct irq_domain *domain) |
186 | { | 188 | { |
@@ -195,8 +197,7 @@ int mfd_add_devices(struct device *parent, int id, | |||
195 | 197 | ||
196 | for (i = 0; i < n_devs; i++) { | 198 | for (i = 0; i < n_devs; i++) { |
197 | atomic_set(&cnts[i], 0); | 199 | atomic_set(&cnts[i], 0); |
198 | cells[i].usage_count = &cnts[i]; | 200 | ret = mfd_add_device(parent, id, cells + i, cnts + i, mem_base, |
199 | ret = mfd_add_device(parent, id, cells + i, mem_base, | ||
200 | irq_base, domain); | 201 | irq_base, domain); |
201 | if (ret) | 202 | if (ret) |
202 | break; | 203 | break; |
@@ -259,8 +260,8 @@ int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones) | |||
259 | for (i = 0; i < n_clones; i++) { | 260 | for (i = 0; i < n_clones; i++) { |
260 | cell_entry.name = clones[i]; | 261 | cell_entry.name = clones[i]; |
261 | /* don't give up if a single call fails; just report error */ | 262 | /* don't give up if a single call fails; just report error */ |
262 | if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0, | 263 | if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, |
263 | NULL)) | 264 | cell_entry.usage_count, NULL, 0, NULL)) |
264 | dev_err(dev, "failed to create platform device '%s'\n", | 265 | dev_err(dev, "failed to create platform device '%s'\n", |
265 | clones[i]); | 266 | clones[i]); |
266 | } | 267 | } |