--- linux-2.6.38/drivers/mmc/host/sdhci.c 2011-05-28 18:52:02.799702610 -0400 +++ linux-2.6.38/drivers/mmc/host/sdhci.c 2011-05-28 18:46:55.356409956 -0400 @@ -602,15 +602,19 @@ * longer to time out, but that's much better than having a too-short * timeout value. */ +#ifndef CONFIG_SDHCI_STUDY_TIMEOUTS if (host->quirks & SDHCI_QUIRK_BROKEN_TIMEOUT_VAL) return 0xE; +#endif /* timeout in us */ target_timeout = data->timeout_ns / 1000 + (data->timeout_clks * 1000) / (host->clock / 1000); +#ifndef CONFIG_SDHCI_STUDY_TIMEOUTS if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) host->timeout_clk = host->clock / 1000; +#endif /* * Figure out needed cycles. @@ -671,6 +675,14 @@ host->data_early = 0; count = sdhci_calc_timeout(host, data); +#ifdef CONFIG_SDHCI_STUDY_TIMEOUTS + { + struct timespec now = CURRENT_TIME; + host->start_time = timespec_to_ns(&now); + host->expected_timeout = (u64)(1 << (13+count)) * 1000000 / host->timeout_clk; + host->timeout_counter = count; + } +#endif sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) @@ -1522,7 +1534,17 @@ if ((intmask & SDHCI_INT_DATA_TIMEOUT) && !(intmask & SDHCI_INT_DATA_END)) + { +#ifdef CONFIG_SDHCI_STUDY_TIMEOUTS + struct timespec now = CURRENT_TIME; + u64 actual_timeout = timespec_to_ns(&now) - host->start_time; + printk(KERN_WARNING "sdhci: timeout, requested %lldns actual %lldns, TMCLK configured %d estimated %lld\n", + (long long)host->expected_timeout, (long long)actual_timeout, + host->timeout_clk, + (long long)((u64)(1 << (13+host->timeout_counter)) * 1000000 / actual_timeout)); +#endif host->data->error = -ETIMEDOUT; + } else if (intmask & SDHCI_INT_DATA_END_BIT) host->data->error = -EILSEQ; else if ((intmask & SDHCI_INT_DATA_CRC) && --- linux-2.6.38/include/linux/mmc/sdhci.h 2011-03-14 21:20:32.000000000 -0400 +++ linux-2.6.38/include/linux/mmc/sdhci.h 2011-05-28 18:02:12.632367830 -0400 @@ -17,6 +17,8 @@ #include #include +#define CONFIG_SDHCI_STUDY_TIMEOUTS + struct sdhci_host { /* Data set by hardware interface driver */ const char *hw_name; /* Hardware bus name */ @@ -145,6 +147,11 @@ unsigned int ocr_avail_sd; unsigned int ocr_avail_mmc; +#ifdef CONFIG_SDHCI_STUDY_TIMEOUTS + u64 expected_timeout, start_time; + u8 timeout_counter; +#endif + unsigned long private[0] ____cacheline_aligned; }; #endif /* __SDHCI_H */