aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc/sdhci.c
diff options
context:
space:
mode:
authorPierre Ossman <drzeus@drzeus.cx>2006-06-30 05:22:23 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-07-02 11:02:02 -0400
commit7cb2c76fa2251474e42d55b75163c9d7ed11741e (patch)
tree65354e6d46ae68915481a7a3f86fbcbb92c4d803 /drivers/mmc/sdhci.c
parent146ad66eac836c0b976c98f428d73e1f6a75270d (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.c29
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)
371static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) 371static 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);