diff options
author | Pierre Ossman <drzeus@drzeus.cx> | 2006-06-30 05:22:23 -0400 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2006-07-02 11:02:02 -0400 |
commit | 7cb2c76fa2251474e42d55b75163c9d7ed11741e (patch) | |
tree | 65354e6d46ae68915481a7a3f86fbcbb92c4d803 /drivers/mmc/sdhci.c | |
parent | 146ad66eac836c0b976c98f428d73e1f6a75270d (diff) |
[MMC] sdhci: fix timeout loops in sdhci
The current timeout loop assume that jiffies are updated. This might not be
the case depending on locks and if the kernel is compiled without preemption.
Change the system to use a counter and fixed delays.
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'drivers/mmc/sdhci.c')
-rw-r--r-- | drivers/mmc/sdhci.c | 29 |
1 files changed, 16 insertions, 13 deletions
diff --git a/drivers/mmc/sdhci.c b/drivers/mmc/sdhci.c index 74912dcac82f..007e825dcb93 100644 --- a/drivers/mmc/sdhci.c +++ b/drivers/mmc/sdhci.c | |||
@@ -371,17 +371,17 @@ static void sdhci_finish_data(struct sdhci_host *host) | |||
371 | static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | 371 | static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) |
372 | { | 372 | { |
373 | int flags; | 373 | int flags; |
374 | u32 present; | 374 | unsigned long timeout; |
375 | unsigned long max_jiffies; | ||
376 | 375 | ||
377 | WARN_ON(host->cmd); | 376 | WARN_ON(host->cmd); |
378 | 377 | ||
379 | DBG("Sending cmd (%x)\n", cmd->opcode); | 378 | DBG("Sending cmd (%x)\n", cmd->opcode); |
380 | 379 | ||
381 | /* Wait max 10 ms */ | 380 | /* Wait max 10 ms */ |
382 | max_jiffies = jiffies + (HZ + 99)/100; | 381 | timeout = 10; |
383 | do { | 382 | while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & |
384 | if (time_after(jiffies, max_jiffies)) { | 383 | (SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT)) { |
384 | if (timeout == 0) { | ||
385 | printk(KERN_ERR "%s: Controller never released " | 385 | printk(KERN_ERR "%s: Controller never released " |
386 | "inhibit bits. Please report this to " | 386 | "inhibit bits. Please report this to " |
387 | BUGMAIL ".\n", mmc_hostname(host->mmc)); | 387 | BUGMAIL ".\n", mmc_hostname(host->mmc)); |
@@ -390,8 +390,9 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | |||
390 | tasklet_schedule(&host->finish_tasklet); | 390 | tasklet_schedule(&host->finish_tasklet); |
391 | return; | 391 | return; |
392 | } | 392 | } |
393 | present = readl(host->ioaddr + SDHCI_PRESENT_STATE); | 393 | timeout--; |
394 | } while (present & (SDHCI_CMD_INHIBIT | SDHCI_DATA_INHIBIT)); | 394 | mdelay(1); |
395 | } | ||
395 | 396 | ||
396 | mod_timer(&host->timer, jiffies + 10 * HZ); | 397 | mod_timer(&host->timer, jiffies + 10 * HZ); |
397 | 398 | ||
@@ -490,7 +491,7 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) | |||
490 | { | 491 | { |
491 | int div; | 492 | int div; |
492 | u16 clk; | 493 | u16 clk; |
493 | unsigned long max_jiffies; | 494 | unsigned long timeout; |
494 | 495 | ||
495 | if (clock == host->clock) | 496 | if (clock == host->clock) |
496 | return; | 497 | return; |
@@ -511,17 +512,19 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) | |||
511 | writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL); | 512 | writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL); |
512 | 513 | ||
513 | /* Wait max 10 ms */ | 514 | /* Wait max 10 ms */ |
514 | max_jiffies = jiffies + (HZ + 99)/100; | 515 | timeout = 10; |
515 | do { | 516 | while (!((clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL)) |
516 | if (time_after(jiffies, max_jiffies)) { | 517 | & SDHCI_CLOCK_INT_STABLE)) { |
518 | if (timeout == 0) { | ||
517 | printk(KERN_ERR "%s: Internal clock never stabilised. " | 519 | printk(KERN_ERR "%s: Internal clock never stabilised. " |
518 | "Please report this to " BUGMAIL ".\n", | 520 | "Please report this to " BUGMAIL ".\n", |
519 | mmc_hostname(host->mmc)); | 521 | mmc_hostname(host->mmc)); |
520 | sdhci_dumpregs(host); | 522 | sdhci_dumpregs(host); |
521 | return; | 523 | return; |
522 | } | 524 | } |
523 | clk = readw(host->ioaddr + SDHCI_CLOCK_CONTROL); | 525 | timeout--; |
524 | } while (!(clk & SDHCI_CLOCK_INT_STABLE)); | 526 | mdelay(1); |
527 | } | ||
525 | 528 | ||
526 | clk |= SDHCI_CLOCK_CARD_EN; | 529 | clk |= SDHCI_CLOCK_CARD_EN; |
527 | writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL); | 530 | writew(clk, host->ioaddr + SDHCI_CLOCK_CONTROL); |