diff options
author | Adrian Hunter <adrian.hunter@nokia.com> | 2009-09-22 19:44:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-23 10:39:34 -0400 |
commit | a6b2240da2b090874095832afc7eb9ed2968b27f (patch) | |
tree | a26deef8395722ca795c9abfdd5227402576c785 /drivers/mmc/host/omap_hsmmc.c | |
parent | abb28e731a751f0b6c293a67b3e564eb0e336d53 (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.c | 50 |
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; |