aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/host/omap_hsmmc.c
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@nokia.com>2009-09-22 19:44:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-23 10:39:34 -0400
commita6b2240da2b090874095832afc7eb9ed2968b27f (patch)
treea26deef8395722ca795c9abfdd5227402576c785 /drivers/mmc/host/omap_hsmmc.c
parentabb28e731a751f0b6c293a67b3e564eb0e336d53 (diff)
omap_hsmmc: ensure workqueues are empty before suspend
Signed-off-by: Adrian Hunter <adrian.hunter@nokia.com> Acked-by: Matt Fleming <matt@console-pimps.org> Cc: Ian Molton <ian@mnementh.co.uk> Cc: "Roberto A. Foglietta" <roberto.foglietta@gmail.com> Cc: Jarkko Lavinen <jarkko.lavinen@nokia.com> Cc: Denis Karpov <ext-denis.2.karpov@nokia.com> Cc: Pierre Ossman <pierre@ossman.eu> Cc: Philip Langdale <philipl@overt.org> Cc: "Madhusudhan" <madhu.cr@ti.com> Cc: <linux-mmc@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/mmc/host/omap_hsmmc.c')
-rw-r--r--drivers/mmc/host/omap_hsmmc.c50
1 files changed, 34 insertions, 16 deletions
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 59f001090332..9599dd126ac8 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -151,7 +151,6 @@ struct mmc_omap_host {
151 u32 bytesleft; 151 u32 bytesleft;
152 int suspended; 152 int suspended;
153 int irq; 153 int irq;
154 int carddetect;
155 int use_dma, dma_ch; 154 int use_dma, dma_ch;
156 int dma_line_tx, dma_line_rx; 155 int dma_line_tx, dma_line_rx;
157 int slot_id; 156 int slot_id;
@@ -761,14 +760,19 @@ static void mmc_omap_detect(struct work_struct *work)
761 struct mmc_omap_host *host = container_of(work, struct mmc_omap_host, 760 struct mmc_omap_host *host = container_of(work, struct mmc_omap_host,
762 mmc_carddetect_work); 761 mmc_carddetect_work);
763 struct omap_mmc_slot_data *slot = &mmc_slot(host); 762 struct omap_mmc_slot_data *slot = &mmc_slot(host);
763 int carddetect;
764
765 if (host->suspended)
766 return;
767
768 sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch");
764 769
765 if (mmc_slot(host).card_detect) 770 if (mmc_slot(host).card_detect)
766 host->carddetect = slot->card_detect(slot->card_detect_irq); 771 carddetect = slot->card_detect(slot->card_detect_irq);
767 else 772 else
768 host->carddetect = -ENOSYS; 773 carddetect = -ENOSYS;
769 774
770 sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); 775 if (carddetect) {
771 if (host->carddetect) {
772 mmc_detect_change(host->mmc, (HZ * 200) / 1000); 776 mmc_detect_change(host->mmc, (HZ * 200) / 1000);
773 } else { 777 } else {
774 mmc_host_enable(host->mmc); 778 mmc_host_enable(host->mmc);
@@ -785,6 +789,8 @@ static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id)
785{ 789{
786 struct mmc_omap_host *host = (struct mmc_omap_host *)dev_id; 790 struct mmc_omap_host *host = (struct mmc_omap_host *)dev_id;
787 791
792 if (host->suspended)
793 return IRQ_HANDLED;
788 schedule_work(&host->mmc_carddetect_work); 794 schedule_work(&host->mmc_carddetect_work);
789 795
790 return IRQ_HANDLED; 796 return IRQ_HANDLED;
@@ -1524,30 +1530,42 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state)
1524 return 0; 1530 return 0;
1525 1531
1526 if (host) { 1532 if (host) {
1533 host->suspended = 1;
1534 if (host->pdata->suspend) {
1535 ret = host->pdata->suspend(&pdev->dev,
1536 host->slot_id);
1537 if (ret) {
1538 dev_dbg(mmc_dev(host->mmc),
1539 "Unable to handle MMC board"
1540 " level suspend\n");
1541 host->suspended = 0;
1542 return ret;
1543 }
1544 }
1545 cancel_work_sync(&host->mmc_carddetect_work);
1527 mmc_host_enable(host->mmc); 1546 mmc_host_enable(host->mmc);
1528 ret = mmc_suspend_host(host->mmc, state); 1547 ret = mmc_suspend_host(host->mmc, state);
1529 if (ret == 0) { 1548 if (ret == 0) {
1530 host->suspended = 1;
1531
1532 OMAP_HSMMC_WRITE(host->base, ISE, 0); 1549 OMAP_HSMMC_WRITE(host->base, ISE, 0);
1533 OMAP_HSMMC_WRITE(host->base, IE, 0); 1550 OMAP_HSMMC_WRITE(host->base, IE, 0);
1534 1551
1535 if (host->pdata->suspend) {
1536 ret = host->pdata->suspend(&pdev->dev,
1537 host->slot_id);
1538 if (ret)
1539 dev_dbg(mmc_dev(host->mmc),
1540 "Unable to handle MMC board"
1541 " level suspend\n");
1542 }
1543 1552
1544 OMAP_HSMMC_WRITE(host->base, HCTL, 1553 OMAP_HSMMC_WRITE(host->base, HCTL,
1545 OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); 1554 OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
1546 mmc_host_disable(host->mmc); 1555 mmc_host_disable(host->mmc);
1547 clk_disable(host->iclk); 1556 clk_disable(host->iclk);
1548 clk_disable(host->dbclk); 1557 clk_disable(host->dbclk);
1549 } else 1558 } else {
1559 host->suspended = 0;
1560 if (host->pdata->resume) {
1561 ret = host->pdata->resume(&pdev->dev,
1562 host->slot_id);
1563 if (ret)
1564 dev_dbg(mmc_dev(host->mmc),
1565 "Unmask interrupt failed\n");
1566 }
1550 mmc_host_disable(host->mmc); 1567 mmc_host_disable(host->mmc);
1568 }
1551 1569
1552 } 1570 }
1553 return ret; 1571 return ret;