diff options
author | Philippe Langlais <philippe.langlais@linaro.org> | 2011-05-05 14:33:40 +0200 |
---|---|---|
committer | Henrik Aberg <henrik.aberg@stericsson.com> | 2011-05-18 09:39:49 +0200 |
commit | 5046283c72a700f938b378a90632627371ee0e82 (patch) | |
tree | 502936687a4c623a760bb15e3dec2db3752ac71e /drivers/mmc | |
parent | 1a306c067df48dd91ad8f5889f656f68f7d96a20 (diff) |
MMCI: Fixup handling of MCI_SDIOIT irq mask
Make sure the MCI_SDIOIT irq mask is never accessed and
modified without holding the host spinlock. As well
re-order some actions in the enable and disable functions
to handle SDIO irq wakeups event sequence correctly.
Change-Id: Ia24fa162ee13ac767828bcca19c1ccd31cc7f695
Signed-off-by: Ulf Hansson <ulf.hansson@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/16948
Reviewed-by: Sebastian RASMUSSEN <sebastian.rasmussen@stericsson.com>
Conflicts:
drivers/mmc/host/mmci.c
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/host/mmci.c | 29 |
1 files changed, 14 insertions, 15 deletions
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 389f5e3194c..f85927eaa0c 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c @@ -934,6 +934,7 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) { struct mmci_host *host = dev_id; u32 status; + int sdio_irq = 0; int ret = 0; spin_lock(&host->lock); @@ -957,7 +958,7 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status); if (status & MCI_ST_SDIOIT) - mmc_signal_sdio_irq(host->mmc); + sdio_irq = 1; data = host->data; if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN| @@ -973,6 +974,9 @@ static irqreturn_t mmci_irq(int irq, void *dev_id) spin_unlock(&host->lock); + if (sdio_irq) + mmc_signal_sdio_irq(host->mmc); + return IRQ_RETVAL(ret); } @@ -1122,24 +1126,19 @@ static irqreturn_t mmci_cd_irq(int irq, void *dev_id) static void mmci_enable_sdio_irq(struct mmc_host *mmc, int enable) { unsigned long flags; + unsigned int mask0; struct mmci_host *host = mmc_priv(mmc); - if (enable) { - /* - * Since the host is not claimed when doing enable - * we must handle it here. - */ - spin_lock_irqsave(&host->lock, flags); + spin_lock_irqsave(&host->lock, flags); - writel((readl(host->base + MMCIMASK0) | MCI_ST_SDIOIT), - (host->base + MMCIMASK0)); + mask0 = readl(host->base + MMCIMASK0); + if (enable) + mask0 |= MCI_ST_SDIOIT; + else + mask0 &= ~MCI_ST_SDIOIT; + writel(mask0, host->base + MMCIMASK0); - spin_unlock_irqrestore(&host->lock, flags); - } else { - /* We assumes the host is claimed when doing disable. */ - writel((readl(host->base + MMCIMASK0) & ~MCI_ST_SDIOIT), - (host->base + MMCIMASK0)); - } + spin_unlock_irqrestore(&host->lock, flags); } static const struct mmc_host_ops mmci_ops = { |