From a6b2240da2b090874095832afc7eb9ed2968b27f Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 22 Sep 2009 16:44:45 -0700 Subject: omap_hsmmc: ensure workqueues are empty before suspend Signed-off-by: Adrian Hunter Acked-by: Matt Fleming Cc: Ian Molton Cc: "Roberto A. Foglietta" Cc: Jarkko Lavinen Cc: Denis Karpov Cc: Pierre Ossman Cc: Philip Langdale Cc: "Madhusudhan" Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mmc/host/omap_hsmmc.c | 50 +++++++++++++++++++++++++++++-------------- 1 file 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 { u32 bytesleft; int suspended; int irq; - int carddetect; int use_dma, dma_ch; int dma_line_tx, dma_line_rx; int slot_id; @@ -761,14 +760,19 @@ static void mmc_omap_detect(struct work_struct *work) struct mmc_omap_host *host = container_of(work, struct mmc_omap_host, mmc_carddetect_work); struct omap_mmc_slot_data *slot = &mmc_slot(host); + int carddetect; + + if (host->suspended) + return; + + sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); if (mmc_slot(host).card_detect) - host->carddetect = slot->card_detect(slot->card_detect_irq); + carddetect = slot->card_detect(slot->card_detect_irq); else - host->carddetect = -ENOSYS; + carddetect = -ENOSYS; - sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); - if (host->carddetect) { + if (carddetect) { mmc_detect_change(host->mmc, (HZ * 200) / 1000); } else { mmc_host_enable(host->mmc); @@ -785,6 +789,8 @@ static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id) { struct mmc_omap_host *host = (struct mmc_omap_host *)dev_id; + if (host->suspended) + return IRQ_HANDLED; schedule_work(&host->mmc_carddetect_work); return IRQ_HANDLED; @@ -1524,30 +1530,42 @@ static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state) return 0; if (host) { + host->suspended = 1; + if (host->pdata->suspend) { + ret = host->pdata->suspend(&pdev->dev, + host->slot_id); + if (ret) { + dev_dbg(mmc_dev(host->mmc), + "Unable to handle MMC board" + " level suspend\n"); + host->suspended = 0; + return ret; + } + } + cancel_work_sync(&host->mmc_carddetect_work); mmc_host_enable(host->mmc); ret = mmc_suspend_host(host->mmc, state); if (ret == 0) { - host->suspended = 1; - OMAP_HSMMC_WRITE(host->base, ISE, 0); OMAP_HSMMC_WRITE(host->base, IE, 0); - if (host->pdata->suspend) { - ret = host->pdata->suspend(&pdev->dev, - host->slot_id); - if (ret) - dev_dbg(mmc_dev(host->mmc), - "Unable to handle MMC board" - " level suspend\n"); - } OMAP_HSMMC_WRITE(host->base, HCTL, OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); mmc_host_disable(host->mmc); clk_disable(host->iclk); clk_disable(host->dbclk); - } else + } else { + host->suspended = 0; + if (host->pdata->resume) { + ret = host->pdata->resume(&pdev->dev, + host->slot_id); + if (ret) + dev_dbg(mmc_dev(host->mmc), + "Unmask interrupt failed\n"); + } mmc_host_disable(host->mmc); + } } return ret; -- cgit v1.2.1