Re: sdhci can turn off irq up to 200 ms

From: Matthieu CASTET
Date: Thu Jul 09 2009 - 06:28:25 EST


Matthieu CASTET a écrit :
> Hi,
>
> sdhci code got tasklets (sdhci_tasklet_card and sdhci_tasklet_finish),
> that does :
> {
> spin_lock_irqsave
>
> if (cond) {
> sdhci_reset
> sdhci_reset
> }
>
> spin_unlock_irqrestore
> }
>
> The problem is that sdhci_reset [1] does busy pooling on a register up
> to a timeout of 100 ms.
> That's not low latency friendly.
>
> On our system, we saw that sdhci_reset take 1 ms. That should be because
> we enter in mdelay, even if the hardware clears the bit faster.
> I wonder why there is an mdelay(1). Using cpu_relax and
> time_is_after_jiffies should make sdhci_reset faster.
>
In case somebody cares, here a patch that reduce on our hardware
sdhci_reset from 1 ms to 30 us.


Matthieu
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 6779b4e..3e199b6 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -156,18 +156,17 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask)
host->clock = 0;

/* Wait max 100 ms */
- timeout = 100;
+ timeout = jiffies + msecs_to_jiffies(100);

/* hw clears the bit when it's done */
while (sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask) {
- if (timeout == 0) {
+ if (time_is_before_jiffies(timeout)) {
printk(KERN_ERR "%s: Reset 0x%x never completed.\n",
mmc_hostname(host->mmc), (int)mask);
sdhci_dumpregs(host);
return;
}
- timeout--;
- mdelay(1);
+ cpu_relax();
}

if (host->quirks & SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)