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 | |
| 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>
| -rw-r--r-- | drivers/mfd/mfd-core.c | 17 | ||||
| -rw-r--r-- | include/linux/mfd/core.h | 2 |
2 files changed, 10 insertions, 9 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 | } |
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h index cebe97ee98b8..60ced604664f 100644 --- a/include/linux/mfd/core.h +++ b/include/linux/mfd/core.h | |||
| @@ -98,7 +98,7 @@ static inline const struct mfd_cell *mfd_get_cell(struct platform_device *pdev) | |||
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | extern int mfd_add_devices(struct device *parent, int id, | 100 | extern int mfd_add_devices(struct device *parent, int id, |
| 101 | struct mfd_cell *cells, int n_devs, | 101 | const struct mfd_cell *cells, int n_devs, |
| 102 | struct resource *mem_base, | 102 | struct resource *mem_base, |
| 103 | int irq_base, struct irq_domain *irq_domain); | 103 | int irq_base, struct irq_domain *irq_domain); |
| 104 | 104 | ||
