Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fc6f41ba authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull MMC host fix from Ulf Hansson:
 "mmci: Fix hang while waiting for busy-end interrupt"

* tag 'mmc-v4.10-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/mmc:
  mmc: mmci: avoid clearing ST Micro busy end interrupt mistakenly
parents 1f369d16 5cad24d8
Loading
Loading
Loading
Loading
+25 −7
Original line number Diff line number Diff line
@@ -1023,7 +1023,12 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
		if (!host->busy_status && busy_resp &&
		    !(status & (MCI_CMDCRCFAIL|MCI_CMDTIMEOUT)) &&
		    (readl(base + MMCISTATUS) & host->variant->busy_detect_flag)) {
			/* Unmask the busy IRQ */

			/* Clear the busy start IRQ */
			writel(host->variant->busy_detect_mask,
			       host->base + MMCICLEAR);

			/* Unmask the busy end IRQ */
			writel(readl(base + MMCIMASK0) |
			       host->variant->busy_detect_mask,
			       base + MMCIMASK0);
@@ -1038,10 +1043,14 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,

		/*
		 * At this point we are not busy with a command, we have
		 * not received a new busy request, mask the busy IRQ and
		 * fall through to process the IRQ.
		 * not received a new busy request, clear and mask the busy
		 * end IRQ and fall through to process the IRQ.
		 */
		if (host->busy_status) {

			writel(host->variant->busy_detect_mask,
			       host->base + MMCICLEAR);

			writel(readl(base + MMCIMASK0) &
			       ~host->variant->busy_detect_mask,
			       base + MMCIMASK0);
@@ -1283,11 +1292,20 @@ static irqreturn_t mmci_irq(int irq, void *dev_id)
		}

		/*
		 * We intentionally clear the MCI_ST_CARDBUSY IRQ here (if it's
		 * enabled) since the HW seems to be triggering the IRQ on both
		 * edges while monitoring DAT0 for busy completion.
		 * We intentionally clear the MCI_ST_CARDBUSY IRQ (if it's
		 * enabled) in mmci_cmd_irq() function where ST Micro busy
		 * detection variant is handled. Considering the HW seems to be
		 * triggering the IRQ on both edges while monitoring DAT0 for
		 * busy completion and that same status bit is used to monitor
		 * start and end of busy detection, special care must be taken
		 * to make sure that both start and end interrupts are always
		 * cleared one after the other.
		 */
		status &= readl(host->base + MMCIMASK0);
		if (host->variant->busy_detect)
			writel(status & ~host->variant->busy_detect_mask,
			       host->base + MMCICLEAR);
		else
			writel(status, host->base + MMCICLEAR);

		dev_dbg(mmc_dev(host->mmc), "irq0 (data+cmd) %08x\n", status);