aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mmc/host/sdhci.c62
-rw-r--r--include/linux/mmc/sdhci.h2
2 files changed, 41 insertions, 23 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 4b6cca2130bc..4a0622d52ae5 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2428,10 +2428,10 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
2428 2428
2429static irqreturn_t sdhci_irq(int irq, void *dev_id) 2429static irqreturn_t sdhci_irq(int irq, void *dev_id)
2430{ 2430{
2431 irqreturn_t result; 2431 irqreturn_t result = IRQ_NONE;
2432 struct sdhci_host *host = dev_id; 2432 struct sdhci_host *host = dev_id;
2433 u32 intmask, mask, unexpected = 0; 2433 u32 intmask, mask, unexpected = 0;
2434 int cardint = 0, max_loops = 16; 2434 int max_loops = 16;
2435 2435
2436 spin_lock(&host->lock); 2436 spin_lock(&host->lock);
2437 2437
@@ -2490,8 +2490,11 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
2490 pr_err("%s: Card is consuming too much power!\n", 2490 pr_err("%s: Card is consuming too much power!\n",
2491 mmc_hostname(host->mmc)); 2491 mmc_hostname(host->mmc));
2492 2492
2493 if (intmask & SDHCI_INT_CARD_INT) 2493 if (intmask & SDHCI_INT_CARD_INT) {
2494 cardint = 1; 2494 sdhci_enable_sdio_irq_nolock(host, false);
2495 host->thread_isr |= SDHCI_INT_CARD_INT;
2496 result = IRQ_WAKE_THREAD;
2497 }
2495 2498
2496 intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE | 2499 intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE |
2497 SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK | 2500 SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK |
@@ -2503,17 +2506,10 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
2503 sdhci_writel(host, intmask, SDHCI_INT_STATUS); 2506 sdhci_writel(host, intmask, SDHCI_INT_STATUS);
2504 } 2507 }
2505 2508
2506 result = IRQ_HANDLED; 2509 if (result == IRQ_NONE)
2510 result = IRQ_HANDLED;
2507 2511
2508 intmask = sdhci_readl(host, SDHCI_INT_STATUS); 2512 intmask = sdhci_readl(host, SDHCI_INT_STATUS);
2509
2510 /*
2511 * If we know we'll call the driver to signal SDIO IRQ,
2512 * disregard further indications of Card Interrupt in
2513 * the status to avoid a needless loop.
2514 */
2515 if (cardint)
2516 intmask &= ~SDHCI_INT_CARD_INT;
2517 } while (intmask && --max_loops); 2513 } while (intmask && --max_loops);
2518out: 2514out:
2519 spin_unlock(&host->lock); 2515 spin_unlock(&host->lock);
@@ -2523,15 +2519,33 @@ out:
2523 mmc_hostname(host->mmc), unexpected); 2519 mmc_hostname(host->mmc), unexpected);
2524 sdhci_dumpregs(host); 2520 sdhci_dumpregs(host);
2525 } 2521 }
2526 /*
2527 * We have to delay this as it calls back into the driver.
2528 */
2529 if (cardint)
2530 mmc_signal_sdio_irq(host->mmc);
2531 2522
2532 return result; 2523 return result;
2533} 2524}
2534 2525
2526static irqreturn_t sdhci_thread_irq(int irq, void *dev_id)
2527{
2528 struct sdhci_host *host = dev_id;
2529 unsigned long flags;
2530 u32 isr;
2531
2532 spin_lock_irqsave(&host->lock, flags);
2533 isr = host->thread_isr;
2534 host->thread_isr = 0;
2535 spin_unlock_irqrestore(&host->lock, flags);
2536
2537 if (isr & SDHCI_INT_CARD_INT) {
2538 sdio_run_irqs(host->mmc);
2539
2540 spin_lock_irqsave(&host->lock, flags);
2541 if (host->flags & SDHCI_SDIO_IRQ_ENABLED)
2542 sdhci_enable_sdio_irq_nolock(host, true);
2543 spin_unlock_irqrestore(&host->lock, flags);
2544 }
2545
2546 return isr ? IRQ_HANDLED : IRQ_NONE;
2547}
2548
2535/*****************************************************************************\ 2549/*****************************************************************************\
2536 * * 2550 * *
2537 * Suspend/resume * 2551 * Suspend/resume *
@@ -2601,8 +2615,9 @@ int sdhci_resume_host(struct sdhci_host *host)
2601 } 2615 }
2602 2616
2603 if (!device_may_wakeup(mmc_dev(host->mmc))) { 2617 if (!device_may_wakeup(mmc_dev(host->mmc))) {
2604 ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, 2618 ret = request_threaded_irq(host->irq, sdhci_irq,
2605 mmc_hostname(host->mmc), host); 2619 sdhci_thread_irq, IRQF_SHARED,
2620 mmc_hostname(host->mmc), host);
2606 if (ret) 2621 if (ret)
2607 return ret; 2622 return ret;
2608 } else { 2623 } else {
@@ -2681,7 +2696,7 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
2681 sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK); 2696 sdhci_mask_irqs(host, SDHCI_INT_ALL_MASK);
2682 spin_unlock_irqrestore(&host->lock, flags); 2697 spin_unlock_irqrestore(&host->lock, flags);
2683 2698
2684 synchronize_irq(host->irq); 2699 synchronize_hardirq(host->irq);
2685 2700
2686 spin_lock_irqsave(&host->lock, flags); 2701 spin_lock_irqsave(&host->lock, flags);
2687 host->runtime_suspended = true; 2702 host->runtime_suspended = true;
@@ -2937,6 +2952,7 @@ int sdhci_add_host(struct sdhci_host *host)
2937 mmc->max_busy_timeout = (1 << 27) / host->timeout_clk; 2952 mmc->max_busy_timeout = (1 << 27) / host->timeout_clk;
2938 2953
2939 mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23; 2954 mmc->caps |= MMC_CAP_SDIO_IRQ | MMC_CAP_ERASE | MMC_CAP_CMD23;
2955 mmc->caps2 |= MMC_CAP2_SDIO_IRQ_NOTHREAD;
2940 2956
2941 if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12) 2957 if (host->quirks & SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12)
2942 host->flags |= SDHCI_AUTO_CMD12; 2958 host->flags |= SDHCI_AUTO_CMD12;
@@ -3226,8 +3242,8 @@ int sdhci_add_host(struct sdhci_host *host)
3226 3242
3227 sdhci_init(host, 0); 3243 sdhci_init(host, 0);
3228 3244
3229 ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, 3245 ret = request_threaded_irq(host->irq, sdhci_irq, sdhci_thread_irq,
3230 mmc_hostname(mmc), host); 3246 IRQF_SHARED, mmc_hostname(mmc), host);
3231 if (ret) { 3247 if (ret) {
3232 pr_err("%s: Failed to request IRQ %d: %d\n", 3248 pr_err("%s: Failed to request IRQ %d: %d\n",
3233 mmc_hostname(mmc), host->irq, ret); 3249 mmc_hostname(mmc), host->irq, ret);
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 7be12b883485..d1aa97b77dd9 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -177,6 +177,8 @@ struct sdhci_host {
177 unsigned int ocr_avail_mmc; 177 unsigned int ocr_avail_mmc;
178 u32 ocr_mask; /* available voltages */ 178 u32 ocr_mask; /* available voltages */
179 179
180 u32 thread_isr;
181
180 wait_queue_head_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */ 182 wait_queue_head_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */
181 unsigned int tuning_done; /* Condition flag set when CMD19 succeeds */ 183 unsigned int tuning_done; /* Condition flag set when CMD19 succeeds */
182 184