aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlexander Stein <alexander.stein@systec-electronic.com>2012-03-14 04:52:10 -0400
committerChris Ball <cjb@laptop.org>2012-03-27 12:20:13 -0400
commit6379b2375a0c5a6ad437616a4018e6b8fd95e97c (patch)
treef30a7782e36bff0ef4784547e1146d782af1c8b1 /drivers
parente6039832bed9a9b967796d7021f17f25b625b616 (diff)
mmc: sdhci: check interrupt flags in ISR again
When using MSI it is possible that a new MSI is sent while an earlier MSI is currently handled. In this case SDHCI_INT_STATUS only contains SDHCI_INT_RESPONSE and the ISR would not be called again. But at the end of the ISR SDHCI_INT_DATA_END is now also pending which would be ignored. Fix this by rereading the interrupt flags in the ISR until no interrupt we care is pending. Signed-off-by: Alexander Stein <alexander.stein@systec-electronic.com> Acked-by: Adrian Hunter <adrian.hunter@intel.com> Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/sdhci.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 80cc7847c531..8262cadfdab7 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2267,8 +2267,8 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
2267{ 2267{
2268 irqreturn_t result; 2268 irqreturn_t result;
2269 struct sdhci_host *host = dev_id; 2269 struct sdhci_host *host = dev_id;
2270 u32 intmask; 2270 u32 intmask, unexpected = 0;
2271 int cardint = 0; 2271 int cardint = 0, max_loops = 16;
2272 2272
2273 spin_lock(&host->lock); 2273 spin_lock(&host->lock);
2274 2274
@@ -2286,6 +2286,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
2286 goto out; 2286 goto out;
2287 } 2287 }
2288 2288
2289again:
2289 DBG("*** %s got interrupt: 0x%08x\n", 2290 DBG("*** %s got interrupt: 0x%08x\n",
2290 mmc_hostname(host->mmc), intmask); 2291 mmc_hostname(host->mmc), intmask);
2291 2292
@@ -2344,19 +2345,23 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
2344 intmask &= ~SDHCI_INT_CARD_INT; 2345 intmask &= ~SDHCI_INT_CARD_INT;
2345 2346
2346 if (intmask) { 2347 if (intmask) {
2347 pr_err("%s: Unexpected interrupt 0x%08x.\n", 2348 unexpected |= intmask;
2348 mmc_hostname(host->mmc), intmask);
2349 sdhci_dumpregs(host);
2350
2351 sdhci_writel(host, intmask, SDHCI_INT_STATUS); 2349 sdhci_writel(host, intmask, SDHCI_INT_STATUS);
2352 } 2350 }
2353 2351
2354 result = IRQ_HANDLED; 2352 result = IRQ_HANDLED;
2355 2353
2356 mmiowb(); 2354 intmask = sdhci_readl(host, SDHCI_INT_STATUS);
2355 if (intmask && --max_loops)
2356 goto again;
2357out: 2357out:
2358 spin_unlock(&host->lock); 2358 spin_unlock(&host->lock);
2359 2359
2360 if (unexpected) {
2361 pr_err("%s: Unexpected interrupt 0x%08x.\n",
2362 mmc_hostname(host->mmc), unexpected);
2363 sdhci_dumpregs(host);
2364 }
2360 /* 2365 /*
2361 * We have to delay this as it calls back into the driver. 2366 * We have to delay this as it calls back into the driver.
2362 */ 2367 */