In the current implementation of set_ios -- spin_lock with interrupts disabled is held when mdelay is called. This is considered bad form. This code changes how set_ios works to mask out interrupts on the sdhci device rather than disable interrupts. This code has been tested on mmp2 - linux-next. The code is posted as a RFC for review since no amount of testing can verify interrupt handling is really correct. I can post a patch if that is desired as well. Philip > > static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) > { > struct sdhci_host *host; > unsigned long flags; > u8 ctrl; > u32 ier; > > host = mmc_priv(mmc); > > if (host->flags & SDHCI_DEVICE_DEAD) > goto out; > > /* > * Reset the chip on each power off. > * Should clear out any weird states. > */ > spin_lock_irqsave(&host->lock, flags); > if (ios->power_mode == MMC_POWER_OFF) { > sdhci_writel(host, 0, SDHCI_SIGNAL_ENABLE); > sdhci_reinit(host); > } > > ier = sdhci_readl(host, SDHCI_INT_ENABLE); > sdhci_mask_irqs(host, ier); > spin_unlock_irqrestore(&host->lock, flags); > > sdhci_set_clock(host, ios->clock); > sdhci_set_ddr(host, ios->ddr); > > if (ios->power_mode == MMC_POWER_OFF) > sdhci_set_power(host, -1); > else > sdhci_set_power(host, ios->vdd); > > if (host->ops->platform_send_init_74_clocks) > host->ops->platform_send_init_74_clocks(host, ios->power_mode); > > #ifdef CONFIG_MMC_CLKGATE > if ((mmc->caps & MMC_CAP_HW_CLOCK_GATING) > && host->ops->platform_hw_clk_gate) > host->ops->platform_hw_clk_gate(host); > #endif > > /* > * If your platform has 8-bit width support but is not a v3 controller, > * or if it requires special setup code, you should implement that in > * platform_8bit_width(). > */ > if (host->ops->platform_8bit_width) > host->ops->platform_8bit_width(host, ios->bus_width); > else { > ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); > if (ios->bus_width == MMC_BUS_WIDTH_8) { > ctrl &= ~SDHCI_CTRL_4BITBUS; > if (host->version >= SDHCI_SPEC_300) > ctrl |= SDHCI_CTRL_8BITBUS; > } else { > if (host->version >= SDHCI_SPEC_300) > ctrl &= ~SDHCI_CTRL_8BITBUS; > if (ios->bus_width == MMC_BUS_WIDTH_4) > ctrl |= SDHCI_CTRL_4BITBUS; > else > ctrl &= ~SDHCI_CTRL_4BITBUS; > } > sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); > } > > ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); > > if ((ios->timing == MMC_TIMING_SD_HS || > ios->timing == MMC_TIMING_MMC_HS) > && !(host->quirks & SDHCI_QUIRK_NO_HISPD_BIT)) > ctrl |= SDHCI_CTRL_HISPD; > else > ctrl &= ~SDHCI_CTRL_HISPD; > > sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); > sdhci_unmask_irqs(host, ier); > > /* > * Some (ENE) controllers go apeshit on some ios operation, > * signalling timeout and CRC errors even on CMD0. Resetting > * it on each ios seems to solve the problem. > */ > if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) { > spin_lock_irqsave(&host->lock, flags); > sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); > spin_unlock_irqrestore(&host->lock, flags); > } > > out: > mmiowb(); > } > <sdhci.c> -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html