aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2012-01-20 17:51:07 -0500
committerRussell King <rmk+kernel@arm.linux.org.uk>2012-02-03 12:37:48 -0500
commit30816ac0495cb4f33fc8d748f64ac3cc880cb3c1 (patch)
tree689f82c11f0a1097bbd0e715178f94aa345fcebf /drivers
parent0af5e4c36e70cfd4ae96d3704a425c414f530f2a (diff)
MFD: mcp-core: sanitize host creation/removal
host_unregister() gives us no chance between removing the device and the mcp data structure being freed to access the data inbetween, which drivers may need to do if they need to iounmap() pointers in their private data structures. Therefore, re-jig the interfaces, which are now, on creation: mcp = mcp_host_alloc() if (mcp) { ret = mcp_host_add(mcp, data); if (!ret) mcp_host_free(mcp); } and on removal: mcp_host_del(mcp); ... access mcp ... mcp_host_free(mcp); The free does the final put_device() on the struct device as one would expect. Acked-by: Jochen Friedrich <jochen@scram.de> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mfd/mcp-core.c19
-rw-r--r--drivers/mfd/mcp-sa11x0.c6
2 files changed, 17 insertions, 8 deletions
diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c
index 86cc3f7841cd..cc7643177841 100644
--- a/drivers/mfd/mcp-core.c
+++ b/drivers/mfd/mcp-core.c
@@ -208,6 +208,7 @@ struct mcp *mcp_host_alloc(struct device *parent, size_t size)
208 mcp = kzalloc(sizeof(struct mcp) + size, GFP_KERNEL); 208 mcp = kzalloc(sizeof(struct mcp) + size, GFP_KERNEL);
209 if (mcp) { 209 if (mcp) {
210 spin_lock_init(&mcp->lock); 210 spin_lock_init(&mcp->lock);
211 device_initialize(&mcp->attached_device);
211 mcp->attached_device.parent = parent; 212 mcp->attached_device.parent = parent;
212 mcp->attached_device.bus = &mcp_bus_type; 213 mcp->attached_device.bus = &mcp_bus_type;
213 mcp->attached_device.dma_mask = parent->dma_mask; 214 mcp->attached_device.dma_mask = parent->dma_mask;
@@ -217,18 +218,24 @@ struct mcp *mcp_host_alloc(struct device *parent, size_t size)
217} 218}
218EXPORT_SYMBOL(mcp_host_alloc); 219EXPORT_SYMBOL(mcp_host_alloc);
219 220
220int mcp_host_register(struct mcp *mcp) 221int mcp_host_add(struct mcp *mcp)
221{ 222{
222 dev_set_name(&mcp->attached_device, "mcp0"); 223 dev_set_name(&mcp->attached_device, "mcp0");
223 return device_register(&mcp->attached_device); 224 return device_add(&mcp->attached_device);
224} 225}
225EXPORT_SYMBOL(mcp_host_register); 226EXPORT_SYMBOL(mcp_host_add);
226 227
227void mcp_host_unregister(struct mcp *mcp) 228void mcp_host_del(struct mcp *mcp)
228{ 229{
229 device_unregister(&mcp->attached_device); 230 device_del(&mcp->attached_device);
230} 231}
231EXPORT_SYMBOL(mcp_host_unregister); 232EXPORT_SYMBOL(mcp_host_del);
233
234void mcp_host_free(struct mcp *mcp)
235{
236 put_device(&mcp->attached_device);
237}
238EXPORT_SYMBOL(mcp_host_free);
232 239
233int mcp_driver_register(struct mcp_driver *mcpdrv) 240int mcp_driver_register(struct mcp_driver *mcpdrv)
234{ 241{
diff --git a/drivers/mfd/mcp-sa11x0.c b/drivers/mfd/mcp-sa11x0.c
index 02c53a0766c4..33cadc0ec121 100644
--- a/drivers/mfd/mcp-sa11x0.c
+++ b/drivers/mfd/mcp-sa11x0.c
@@ -195,10 +195,11 @@ static int mcp_sa11x0_probe(struct platform_device *pdev)
195 mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) / 195 mcp->rw_timeout = (64 * 3 * 1000000 + mcp->sclk_rate - 1) /
196 mcp->sclk_rate; 196 mcp->sclk_rate;
197 197
198 ret = mcp_host_register(mcp); 198 ret = mcp_host_add(mcp);
199 if (ret == 0) 199 if (ret == 0)
200 goto out; 200 goto out;
201 201
202 mcp_host_free(mcp);
202 release: 203 release:
203 release_mem_region(0x80060000, 0x60); 204 release_mem_region(0x80060000, 0x60);
204 platform_set_drvdata(pdev, NULL); 205 platform_set_drvdata(pdev, NULL);
@@ -212,7 +213,8 @@ static int mcp_sa11x0_remove(struct platform_device *dev)
212 struct mcp *mcp = platform_get_drvdata(dev); 213 struct mcp *mcp = platform_get_drvdata(dev);
213 214
214 platform_set_drvdata(dev, NULL); 215 platform_set_drvdata(dev, NULL);
215 mcp_host_unregister(mcp); 216 mcp_host_del(mcp);
217 mcp_host_free(mcp);
216 release_mem_region(0x80060000, 0x60); 218 release_mem_region(0x80060000, 0x60);
217 219
218 return 0; 220 return 0;