aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
authorVenkatraman S <svenkatr@ti.com>2012-05-08 07:35:33 -0400
committerChris Ball <cjb@laptop.org>2012-05-17 08:25:41 -0400
commitb01a4f1ce2cde9acd97ce5c06e35bc9c1eacded7 (patch)
treef08a976d181d0c47d3ae16028e6ef09081700ecb /drivers/mmc
parentf6f44590f231cdf914ce740f3a53a6b815bf4767 (diff)
mmc: omap: convert to per instance workqueue
Currently, a global mmc_omap_wq is created for all instances of omap hosts, which can lead to races and doesn't lend itself to unload the module cleanly. Instead, create per instance workqueue and remove the common workqueue. Signed-off-by: Venkatraman S <svenkatr@ti.com> Acked-by: Balaji T K <balajitk@ti.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/host/omap.c29
1 files changed, 12 insertions, 17 deletions
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 887c0e598cf3..2d7628eee3d3 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -169,11 +169,11 @@ struct mmc_omap_host {
169 struct timer_list clk_timer; 169 struct timer_list clk_timer;
170 spinlock_t clk_lock; /* for changing enabled state */ 170 spinlock_t clk_lock; /* for changing enabled state */
171 unsigned int fclk_enabled:1; 171 unsigned int fclk_enabled:1;
172 struct workqueue_struct *mmc_omap_wq;
172 173
173 struct omap_mmc_platform_data *pdata; 174 struct omap_mmc_platform_data *pdata;
174}; 175};
175 176
176static struct workqueue_struct *mmc_omap_wq;
177 177
178static void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot) 178static void mmc_omap_fclk_offdelay(struct mmc_omap_slot *slot)
179{ 179{
@@ -291,7 +291,7 @@ static void mmc_omap_release_slot(struct mmc_omap_slot *slot, int clk_enabled)
291 host->next_slot = new_slot; 291 host->next_slot = new_slot;
292 host->mmc = new_slot->mmc; 292 host->mmc = new_slot->mmc;
293 spin_unlock_irqrestore(&host->slot_lock, flags); 293 spin_unlock_irqrestore(&host->slot_lock, flags);
294 queue_work(mmc_omap_wq, &host->slot_release_work); 294 queue_work(host->mmc_omap_wq, &host->slot_release_work);
295 return; 295 return;
296 } 296 }
297 297
@@ -459,7 +459,7 @@ mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data)
459 } 459 }
460 460
461 host->stop_data = data; 461 host->stop_data = data;
462 queue_work(mmc_omap_wq, &host->send_stop_work); 462 queue_work(host->mmc_omap_wq, &host->send_stop_work);
463} 463}
464 464
465static void 465static void
@@ -639,7 +639,7 @@ mmc_omap_cmd_timer(unsigned long data)
639 OMAP_MMC_WRITE(host, IE, 0); 639 OMAP_MMC_WRITE(host, IE, 0);
640 disable_irq(host->irq); 640 disable_irq(host->irq);
641 host->abort = 1; 641 host->abort = 1;
642 queue_work(mmc_omap_wq, &host->cmd_abort_work); 642 queue_work(host->mmc_omap_wq, &host->cmd_abort_work);
643 } 643 }
644 spin_unlock_irqrestore(&host->slot_lock, flags); 644 spin_unlock_irqrestore(&host->slot_lock, flags);
645} 645}
@@ -828,7 +828,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id)
828 host->abort = 1; 828 host->abort = 1;
829 OMAP_MMC_WRITE(host, IE, 0); 829 OMAP_MMC_WRITE(host, IE, 0);
830 disable_irq_nosync(host->irq); 830 disable_irq_nosync(host->irq);
831 queue_work(mmc_omap_wq, &host->cmd_abort_work); 831 queue_work(host->mmc_omap_wq, &host->cmd_abort_work);
832 return IRQ_HANDLED; 832 return IRQ_HANDLED;
833 } 833 }
834 834
@@ -1389,7 +1389,7 @@ static void mmc_omap_remove_slot(struct mmc_omap_slot *slot)
1389 1389
1390 tasklet_kill(&slot->cover_tasklet); 1390 tasklet_kill(&slot->cover_tasklet);
1391 del_timer_sync(&slot->cover_timer); 1391 del_timer_sync(&slot->cover_timer);
1392 flush_workqueue(mmc_omap_wq); 1392 flush_workqueue(slot->host->mmc_omap_wq);
1393 1393
1394 mmc_remove_host(mmc); 1394 mmc_remove_host(mmc);
1395 mmc_free_host(mmc); 1395 mmc_free_host(mmc);
@@ -1497,6 +1497,10 @@ static int __init mmc_omap_probe(struct platform_device *pdev)
1497 1497
1498 host->reg_shift = (cpu_is_omap7xx() ? 1 : 2); 1498 host->reg_shift = (cpu_is_omap7xx() ? 1 : 2);
1499 1499
1500 host->mmc_omap_wq = alloc_workqueue("mmc_omap", 0, 0);
1501 if (!host->mmc_omap_wq)
1502 goto err_plat_cleanup;
1503
1500 return 0; 1504 return 0;
1501 1505
1502err_plat_cleanup: 1506err_plat_cleanup:
@@ -1542,6 +1546,7 @@ static int mmc_omap_remove(struct platform_device *pdev)
1542 iounmap(host->virt_base); 1546 iounmap(host->virt_base);
1543 release_mem_region(pdev->resource[0].start, 1547 release_mem_region(pdev->resource[0].start,
1544 pdev->resource[0].end - pdev->resource[0].start + 1); 1548 pdev->resource[0].end - pdev->resource[0].start + 1);
1549 destroy_workqueue(host->mmc_omap_wq);
1545 1550
1546 kfree(host); 1551 kfree(host);
1547 1552
@@ -1610,22 +1615,12 @@ static struct platform_driver mmc_omap_driver = {
1610 1615
1611static int __init mmc_omap_init(void) 1616static int __init mmc_omap_init(void)
1612{ 1617{
1613 int ret; 1618 return platform_driver_probe(&mmc_omap_driver, mmc_omap_probe);
1614
1615 mmc_omap_wq = alloc_workqueue("mmc_omap", 0, 0);
1616 if (!mmc_omap_wq)
1617 return -ENOMEM;
1618
1619 ret = platform_driver_probe(&mmc_omap_driver, mmc_omap_probe);
1620 if (ret)
1621 destroy_workqueue(mmc_omap_wq);
1622 return ret;
1623} 1619}
1624 1620
1625static void __exit mmc_omap_exit(void) 1621static void __exit mmc_omap_exit(void)
1626{ 1622{
1627 platform_driver_unregister(&mmc_omap_driver); 1623 platform_driver_unregister(&mmc_omap_driver);
1628 destroy_workqueue(mmc_omap_wq);
1629} 1624}
1630 1625
1631module_init(mmc_omap_init); 1626module_init(mmc_omap_init);