Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mmc: sdhci: SD tuning is broken for some controllers

The SD Host Controller spec states that the SD Host Controller can
request that the driver send up to 40 CMD19's while doing tuning
and that the total time the card spends responding must be < 150ms.
The sdhci_execute_tuning() function in sdhci.c that loops through
sending the CMD19's has multiple bugs. First it sets a "timeout"
variable to 150 and a loop counter variable to 40. It then decrements
both variables by 1 at the end of each loop. It tries to handle
violations of the count and time by doing a break when BOTH variables
are equal to zero, which can never happen because they we set to
different values and decremented by 1 at the same time. The timeout
variable is not based on time at all and is totally useless.
The routine also considers a loop counter of zero to be an error
which means that any controller that requests the max of 40 CMD19s
will cause tuning to fail and be disabled.

I've fixed these issues by allowing up to 40 CMD19's and I've removed
any attempt to handle the 150ms time limit. Removing timeout checking
seems safe here because each CMD19 is timeout protected and the max
loop counters insures we don't loop forever. Adding timeout checking
would not be as simple as snapping the time at the loop start and
checking for 150ms to pass because the loop queues the CMD19's and
uses events to wait for completion so the time would include
all the normal scheduler latencies.

Signed-off-by: Al Cooper <alcooperx@gmail.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Signed-off-by: Chris Ball <chris@printf.net>

authored by

Al Cooper and committed by
Chris Ball
7ce45e95 69f5bf38

+9 -15
+9 -15
drivers/mmc/host/sdhci.c
··· 1823 1823 struct sdhci_host *host = mmc_priv(mmc); 1824 1824 u16 ctrl; 1825 1825 int tuning_loop_counter = MAX_TUNING_LOOP; 1826 - unsigned long timeout; 1827 1826 int err = 0; 1828 1827 unsigned long flags; 1829 1828 ··· 1881 1882 * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number 1882 1883 * of loops reaches 40 times or a timeout of 150ms occurs. 1883 1884 */ 1884 - timeout = 150; 1885 1885 do { 1886 1886 struct mmc_command cmd = {0}; 1887 1887 struct mmc_request mrq = {NULL}; 1888 - 1889 - if (!tuning_loop_counter && !timeout) 1890 - break; 1891 1888 1892 1889 cmd.opcode = opcode; 1893 1890 cmd.arg = 0; ··· 1891 1896 cmd.retries = 0; 1892 1897 cmd.data = NULL; 1893 1898 cmd.error = 0; 1899 + 1900 + if (tuning_loop_counter-- == 0) 1901 + break; 1894 1902 1895 1903 mrq.cmd = &cmd; 1896 1904 host->mrq = &mrq; ··· 1952 1954 host->tuning_done = 0; 1953 1955 1954 1956 ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); 1955 - tuning_loop_counter--; 1956 - timeout--; 1957 1957 1958 1958 /* eMMC spec does not require a delay between tuning cycles */ 1959 1959 if (opcode == MMC_SEND_TUNING_BLOCK) ··· 1962 1966 * The Host Driver has exhausted the maximum number of loops allowed, 1963 1967 * so use fixed sampling frequency. 1964 1968 */ 1965 - if (!tuning_loop_counter || !timeout) { 1969 + if (tuning_loop_counter < 0) { 1966 1970 ctrl &= ~SDHCI_CTRL_TUNED_CLK; 1967 1971 sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); 1972 + } 1973 + if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) { 1974 + pr_info(DRIVER_NAME ": Tuning procedure" 1975 + " failed, falling back to fixed sampling" 1976 + " clock\n"); 1968 1977 err = -EIO; 1969 - } else { 1970 - if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) { 1971 - pr_info(DRIVER_NAME ": Tuning procedure" 1972 - " failed, falling back to fixed sampling" 1973 - " clock\n"); 1974 - err = -EIO; 1975 - } 1976 1978 } 1977 1979 1978 1980 out: