sdhci: fix the fake timeout bug
PATCH 1/1 sdhci: fix the fake timeout bug
Quoted 1 line
From
b893df3a1a937bd5fe22d39ceae93454a2e5e0e4Mon Sep 17 00:00:00 2001
From: Alek Du <[email protected]>
Date: Fri, 30 Nov 2018 14:02:28 +0800
Subject: [PATCH] sdhci: fix the fake timeout bug
We observed some fake timeouts on some devices, the log is like this:
[ 7586.290201] mmc1: Timeout waiting for hardware cmd interrupt. [ 7586.290420] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== ... [ 7586.291774] mmc1: sdhci: Wake-up: 0x00000000 | Clock: 0x00000203
Quoted 1 line
From the clock control register dump, we are pretty sure the clock was
stabilized.
In other cases, we also observed:
[ 7596.530171] mmc1: Timeout waiting for hardware cmd interrupt.
and
[ 1956.534634] mmc1: Reset 0x2 never completed.
But we are pretty sure the mmc controller is working perfectly under low system load.
After checking the sdhci code, we found the timeout check actually has a little window that the CPU can be scheduled out and when it comes back, the original time set or check is not valid.
--- drivers/mmc/host/sdhci.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
drivers/mmc/host/sdhci.c +16 -3
@@ -218,12 +218,17 @@ void sdhci_reset(struct sdhci_host *host, u8 mask)/* hw clears the bit when it's done */ while (sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask) {if (ktime_after (ktime_get (), timeout)) { +/* check it again, since there is a window between +bit check and time check */ +if (!(sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask)) +break ;pr_err ("%s: Reset 0x%x never completed.\n" ,mmc_hostname (host->mmc), (int )mask);sdhci_dumpregs (host);return ; + }else { +udelay (10 ); } -udelay (10 ); } }EXPORT_SYMBOL_GPL (sdhci_reset);
@@ -1395,9 +1400,10 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) timeout +=DIV_ROUND_UP (cmd->busy_timeout,1000 ) *HZ +HZ ; else timeout += 10 * HZ; -sdhci_mod_timer (host, cmd->mrq, timeout);sdhci_writew (host,SDHCI_MAKE_CMD (cmd->opcode, flags),SDHCI_COMMAND ); +/* setup timer after command to avoid fake timeout */ +sdhci_mod_timer (host, cmd->mrq, timeout); }EXPORT_SYMBOL_GPL (sdhci_send_command);
@@ -1611,12 +1617,19 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk)while (!((clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL )) &SDHCI_CLOCK_INT_STABLE )) {if (ktime_after (ktime_get (), timeout)) { +/* check it again since there is a window between +status check and time check */ +if ((clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL )) + &SDHCI_CLOCK_INT_STABLE ) +break ;pr_err ("%s: Internal clock never stabilised.\n" ,mmc_hostname (host->mmc));sdhci_dumpregs (host);return ; } -udelay (10 ); +else { +udelay (10 ); + } } clk |=SDHCI_CLOCK_CARD_EN ;
Signature · 1 line
2.17.1
Adrian Hunter
maintainerQuoted 21 lines · Alek
Quoted 1 line
From
b893df3a1a937bd5fe22d39ceae93454a2e5e0e4Mon Sep 17 00:00:00 2001From: Alek Du <[email protected]>
Date: Fri, 30 Nov 2018 14:02:28 +0800
Subject: [PATCH] sdhci: fix the fake timeout bugWe observed some fake timeouts on some devices, the log is like this:
[ 7586.290201] mmc1: Timeout waiting for hardware cmd interrupt. [ 7586.290420] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== ... [ 7586.291774] mmc1: sdhci: Wake-up: 0x00000000 | Clock: 0x00000203Quoted 1 line
From the clock control register dump, we are pretty sure the clock was
stabilized.
In other cases, we also observed:
[ 7596.530171] mmc1: Timeout waiting for hardware cmd interrupt.and
Quoted 8 lines
[ 1956.534634] mmc1: Reset 0x2 never completed.But we are pretty sure the mmc controller is working perfectly under low system load.
After checking the sdhci code, we found the timeout check actually has a little window that the CPU can be scheduled out and when it comes back, the original time set or check is not valid.
Commands and resets are under spin lock, so no possibility for preemption, and certainly a few microseconds isn't going to make any difference to these timeouts, so I don't see how this patch could help.
I recently sent a patch for GLK laptops that had BIOS issues:
https://marc.info/?l=linux-mmc&m=154270005901609
And also some improvements to error handling:
https://marc.info/?l=linux-mmc&m=154229013900437
If those don't help, please share more details of the actual problem.
Quoted 63 lines
Signed-off-by Alek Du <[email protected]>--- drivers/mmc/host/sdhci.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)drivers/mmc/host/sdhci.c +16
-3@@ -218,12 +218,17 @@ void sdhci_reset(struct sdhci_host *host, u8 mask)/* hw clears the bit when it's done */ while (sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask) {if (ktime_after (ktime_get (), timeout)) { +/* check it again, since there is a window between +bit check and time check */ +if (!(sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask)) +break ;pr_err ("%s: Reset 0x%x never completed.\n" ,mmc_hostname (host->mmc), (int )mask);sdhci_dumpregs (host);return ; + }else { +udelay (10 ); } -udelay (10 ); } }EXPORT_SYMBOL_GPL (sdhci_reset);@@ -1395,9 +1400,10 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) timeout +=DIV_ROUND_UP (cmd->busy_timeout,1000 ) *HZ +HZ ; else timeout += 10 * HZ; -sdhci_mod_timer (host, cmd->mrq, timeout);sdhci_writew (host,SDHCI_MAKE_CMD (cmd->opcode, flags),SDHCI_COMMAND ); +/* setup timer after command to avoid fake timeout */ +sdhci_mod_timer (host, cmd->mrq, timeout); }EXPORT_SYMBOL_GPL (sdhci_send_command);@@ -1611,12 +1617,19 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk)while (!((clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL )) &SDHCI_CLOCK_INT_STABLE )) {if (ktime_after (ktime_get (), timeout)) { +/* check it again since there is a window between +status check and time check */ +if ((clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL )) + &SDHCI_CLOCK_INT_STABLE ) +break ;pr_err ("%s: Internal clock never stabilised.\n" ,mmc_hostname (host->mmc));sdhci_dumpregs (host);return ; } -udelay (10 ); +else { +udelay (10 ); + } } clk |=SDHCI_CLOCK_CARD_EN ;
Quoted 4 lines · On Fri, 30 Nov 2018 11:19:03 +0200 Adrian Hunter <[email protected]>…
Commands and resets are under spin lock, so no possibility for preemption, and certainly a few microseconds isn't going to make any difference to these timeouts, so I don't see how this patch could help.
Thanks for your review.
I believe my case the scheduling out delay sometime can reach 10~20 milliseconds... This may be due to the hypervisor...
Please look at the sdhci_enable_clk() below, there is a window in clock stabilization check. The first check is to check status register, the second check is to check if time passed. That's why I can capture a case that after time passed, the actually clock control register indicated that clock is stable. So the error handling is wrong...
Also the sdhci_send_command commands is not in spin lock There is a windows between mod_timer and real command send...
Thanks,
Alek
Quoted 10 lines
I recently sent a patch for GLK laptops that had BIOS issues:
https://marc.info/?l=linux-mmc&m=154270005901609And also some improvements to error handling:
https://marc.info/?l=linux-mmc&m=154229013900437If those don't help, please share more details of the actual problem.
Sorry, I can't see how this patches could fix my problem.
Quoted 70 lines
Quoted 69 lines
Signed-off-by Alek Du <[email protected]>--- drivers/mmc/host/sdhci.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)drivers/mmc/host/sdhci.c +0
-0@@ -218,12 +218,17 @@ void sdhci_reset(struct sdhci_host *host, u8mask) /* hw clears the bit when it's done */
drivers/mmc/host/sdhci.c +1
-0while (sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask) {if (ktime_after (ktime_get (), timeout)) { +/* check it again, since there is a window between
drivers/mmc/host/sdhci.c +2
-0+bit check and time check */ + if (!(sdhci_readb(host,
SDHCI_SOFTWARE_RESET) & mask))drivers/mmc/host/sdhci.c +1
-0+break ; pr_err("%s: Reset 0x%x never completed.\n", mmc_hostname(host->mmc),(int)mask);
sdhci_dumpregs(host);drivers/mmc/host/sdhci.c +2
-1return ; + }else { +udelay (10 ); } -udelay (10 ); } }EXPORT_SYMBOL_GPL (sdhci_reset);@@ -1395,9 +1400,10 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) timeout +=
DIV_ROUND_UP(cmd->busy_timeout, 1000)* HZ + HZ; elsedrivers/mmc/host/sdhci.c +0
-1timeout +=10 *HZ ; -sdhci_mod_timer (host, cmd->mrq, timeout); sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags),
SDHCI_COMMAND);drivers/mmc/host/sdhci.c +3
-0+/* setup timer after command to avoid fake timeout */ +sdhci_mod_timer (host, cmd->mrq, timeout); }EXPORT_SYMBOL_GPL (sdhci_send_command);@@ -1611,12 +1617,19 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk) while (!((clk = sdhci_readw(host,SDHCI_CLOCK_CONTROL )) &SDHCI_CLOCK_INT_STABLE )) {if (ktime_after (ktime_get (), timeout)) { +/* check it again since there is a window between
drivers/mmc/host/sdhci.c +2
-0+status check and time check */ + if ((clk = sdhci_readw(host,
SDHCI_CLOCK_CONTROL))drivers/mmc/host/sdhci.c +2
-0+ & SDHCI_CLOCK_INT_STABLE) +break ; pr_err("%s: Internal clock neverstabilised.\n",
mmc_hostname(host->mmc));drivers/mmc/host/sdhci.c +3
-1sdhci_dumpregs (host);return ; } -udelay (10 ); +else { +udelay (10 ); + } } clk |=SDHCI_CLOCK_CARD_EN ;
Adrian Hunter
maintainerQuoted 8 lines · Alek
Quoted 4 lines · On Fri, 30 Nov 2018 11:19:03 +0200 Adrian Hunter <[email protected]>…
Commands and resets are under spin lock, so no possibility for preemption, and certainly a few microseconds isn't going to make any difference to these timeouts, so I don't see how this patch could help.
Quoted 4 lines
Thanks for your review.
I believe my case the scheduling out delay sometime can reach 10~20 milliseconds... This may be due to the hypervisor...
So you are saying this only happens under virtualization?
Quoted 6 lines
Please look at the
sdhci_enable_clk()below, there is a window in clock stabilization check. The first check is to check status register, the second check is to check if time passed. That's why I can capture a case that after time passed, the actually clock control register indicated that clock is stable. So the error handling is wrong...
Sure, but "Internal clock never stabilised." is not one of the errors you listed.
Quoted 3 lines
Also the
sdhci_send_commandcommands is not in spin lock There is a windows betweenmod_timerand real command send...
What code path does not have a spin lock?
Quoted 91 lines
Thanks,
AlekQuoted 10 lines
I recently sent a patch for GLK laptops that had BIOS issues:
https://marc.info/?l=linux-mmc&m=154270005901609And also some improvements to error handling:
https://marc.info/?l=linux-mmc&m=154229013900437If those don't help, please share more details of the actual problem.
Sorry, I can't see how this patches could fix my problem.
Quoted 70 lines
Quoted 69 lines
Signed-off-by Alek Du <[email protected]>--- drivers/mmc/host/sdhci.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)drivers/mmc/host/sdhci.c +0
-0@@ -218,12 +218,17 @@ void sdhci_reset(struct sdhci_host *host, u8mask) /* hw clears the bit when it's done */
drivers/mmc/host/sdhci.c +1
-0while (sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask) {if (ktime_after (ktime_get (), timeout)) { +/* check it again, since there is a window between
drivers/mmc/host/sdhci.c +2
-0+bit check and time check */ + if (!(sdhci_readb(host,
SDHCI_SOFTWARE_RESET) & mask))drivers/mmc/host/sdhci.c +1
-0+break ; pr_err("%s: Reset 0x%x never completed.\n", mmc_hostname(host->mmc),(int)mask);
sdhci_dumpregs(host);drivers/mmc/host/sdhci.c +2
-1return ; + }else { +udelay (10 ); } -udelay (10 ); } }EXPORT_SYMBOL_GPL (sdhci_reset);@@ -1395,9 +1400,10 @@ void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) timeout +=
DIV_ROUND_UP(cmd->busy_timeout, 1000)* HZ + HZ; elsedrivers/mmc/host/sdhci.c +0
-1timeout +=10 *HZ ; -sdhci_mod_timer (host, cmd->mrq, timeout); sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags),
SDHCI_COMMAND);drivers/mmc/host/sdhci.c +3
-0+/* setup timer after command to avoid fake timeout */ +sdhci_mod_timer (host, cmd->mrq, timeout); }EXPORT_SYMBOL_GPL (sdhci_send_command);@@ -1611,12 +1617,19 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk) while (!((clk = sdhci_readw(host,SDHCI_CLOCK_CONTROL )) &SDHCI_CLOCK_INT_STABLE )) {if (ktime_after (ktime_get (), timeout)) { +/* check it again since there is a window between
drivers/mmc/host/sdhci.c +2
-0+status check and time check */ + if ((clk = sdhci_readw(host,
SDHCI_CLOCK_CONTROL))drivers/mmc/host/sdhci.c +2
-0+ & SDHCI_CLOCK_INT_STABLE) +break ; pr_err("%s: Internal clock neverstabilised.\n",
mmc_hostname(host->mmc));drivers/mmc/host/sdhci.c +3
-1sdhci_dumpregs (host);return ; } -udelay (10 ); +else { +udelay (10 ); + } } clk |=SDHCI_CLOCK_CARD_EN ;
Quoted 2 lines · On Fri, 30 Nov 2018 16:40:04 +0200 Adrian Hunter <[email protected]>…
So you are saying this only happens under virtualization?
Yes, I saw the issue under ACRN virtualization Service OS (4.19 kernel). But theoretically it can happen in other case when scheduling is not that good. (due to bad driver or other high priority task)
Quoted 10 lines
Quoted 7 lines
Please look at the
sdhci_enable_clk()below, there is a window in clock stabilization check. The first check is to check status register, the second check is to check if time passed. That's why I can capture a case that after time passed, the actually clock control register indicated that clock is stable. So the error handling is wrong...Sure, but "Internal clock never stabilised." is not one of the errors you listed.
Sorry my bad not listing all the error log:
Case 1. clock stabilization timeout: (the below clock control dump shows clock is good)
[159525.255629] mmc1: Internal clock never stabilised. [159525.255818] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== [159525.256049] mmc1: sdhci: Sys addr: 0x00000000 | Version: 0x00001002 [159525.256277] mmc1: sdhci: Blk size: 0x00000000 | Blk cnt: 0x00000000 [159525.256523] mmc1: sdhci: Argument: 0x00000000 | Trn mode: 0x00000000 [159525.256752] mmc1: sdhci: Present: 0x1fff0000 | Host ctl: 0x00000000 [159525.256979] mmc1: sdhci: Power: 0x0000000b | Blk gap: 0x00000080 [159525.257205] mmc1: sdhci: Wake-up: 0x00000000 | Clock: 0x0000fa03
Case 2. Reset timeout: (the same check window in sdhci_reset())
[ 7639.968613] mmc1: Reset 0x4 never completed.
Case 3. Hardware interrupt timeout
[ 1049.561728] mmc1: Timeout waiting for hardware interrupt.
Quoted 6 lines
Quoted 4 lines
Also the
sdhci_send_commandcommands is not in spin lock There is a windows betweenmod_timerand real command send...What code path does not have a spin lock?
Ouch my bad, the sdhci_send_command are called either from spinlock or IRQ handler, so this part is good ...
I'll send a new patch to cover case 1 and case 2 if you agree.
Thanks,
Alek
PATCH v2 1/1 sdhci: fix the timeout check window for clock and reset
Quoted 1 line
From
87692fc090978bde8fe872f02d0023a57af6b492Mon Sep 17 00:00:00 2001
From: Alek Du <[email protected]>
Date: Fri, 30 Nov 2018 14:02:28 +0800
Subject: [PATCH] sdhci: fix the timeout check window for clock and reset
We observed some fake timeouts on some devices, the log is like this:
case 1:
[159525.255629] mmc1: Internal clock never stabilised. [159525.255818] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== [159525.256049] mmc1: sdhci: Sys addr: 0x00000000 | Version: 0x00001002 [159525.256277] mmc1: sdhci: Blk size: 0x00000000 | Blk cnt: 0x00000000 [159525.256523] mmc1: sdhci: Argument: 0x00000000 | Trn mode: 0x00000000 [159525.256752] mmc1: sdhci: Present: 0x1fff0000 | Host ctl: 0x00000000 [159525.256979] mmc1: sdhci: Power: 0x0000000b | Blk gap: 0x00000080 [159525.257205] mmc1: sdhci: Wake-up: 0x00000000 | Clock: 0x0000fa03
Quoted 1 line
From the clock control register dump, we are pretty sure the clock was
stablized.
case 2:
[ 914.550127] mmc1: Reset 0x2 never completed. [ 914.550321] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== [ 914.550608] mmc1: sdhci: Sys addr: 0x00000010 | Version: 0x00001002
After checking the sdhci code, we found the timeout check actually has a little window that the CPU can be scheduled out and when it comes back, the original time set or check is not valid.
--- drivers/mmc/host/sdhci.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
drivers/mmc/host/sdhci.c +14 -2
@@ -218,12 +218,17 @@ void sdhci_reset(struct sdhci_host *host, u8 mask)/* hw clears the bit when it's done */ while (sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask) {if (ktime_after (ktime_get (), timeout)) { +/* check it again, since there is a window between +bit check and time check */ +if (!(sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask)) +break ;pr_err ("%s: Reset 0x%x never completed.\n" ,mmc_hostname (host->mmc), (int )mask);sdhci_dumpregs (host);return ; + }else { +udelay (10 ); } -udelay (10 ); } }EXPORT_SYMBOL_GPL (sdhci_reset);
@@ -1611,12 +1616,19 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk)while (!((clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL )) &SDHCI_CLOCK_INT_STABLE )) {if (ktime_after (ktime_get (), timeout)) { +/* check it again since there is a window between +status check and time check */ +if ((clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL )) + &SDHCI_CLOCK_INT_STABLE ) +break ;pr_err ("%s: Internal clock never stabilised.\n" ,mmc_hostname (host->mmc));sdhci_dumpregs (host);return ; } -udelay (10 ); +else { +udelay (10 ); + } } clk |=SDHCI_CLOCK_CARD_EN ;
Signature · 1 line
2.17.1
Adrian Hunter
maintainerRe: [PATCH V2] sdhci: fix the timeout check window for clock and reset
Quoted 6 lines · Alek
Quoted 1 line
From
87692fc090978bde8fe872f02d0023a57af6b492Mon Sep 17 00:00:00 2001From: Alek Du <[email protected]>
Date: Fri, 30 Nov 2018 14:02:28 +0800
Subject: [PATCH] sdhci: fix the timeout check window for clock and resetWe observed some fake timeouts on some devices, the log is like this:
Please change "fake timeouts" to "premature timeouts". Also I think it is worth mentioning that this was with a virtualized environment.
Quoted 18 lines
case 1:
[159525.255629] mmc1: Internal clock never stabilised. [159525.255818] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== [159525.256049] mmc1: sdhci: Sys addr: 0x00000000 | Version: 0x00001002 [159525.256277] mmc1: sdhci: Blk size: 0x00000000 | Blk cnt: 0x00000000 [159525.256523] mmc1: sdhci: Argument: 0x00000000 | Trn mode: 0x00000000 [159525.256752] mmc1: sdhci: Present: 0x1fff0000 | Host ctl: 0x00000000 [159525.256979] mmc1: sdhci: Power: 0x0000000b | Blk gap: 0x00000080 [159525.257205] mmc1: sdhci: Wake-up: 0x00000000 | Clock: 0x0000fa03Quoted 1 line
From the clock control register dump, we are pretty sure the clock was
stablized.
case 2:
[ 914.550127] mmc1: Reset 0x2 never completed. [ 914.550321] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== [ 914.550608] mmc1: sdhci: Sys addr: 0x00000010 | Version: 0x00001002
Quoted 5 lines
After checking the sdhci code, we found the timeout check actually has a little window that the CPU can be scheduled out and when it comes back, the original time set or check is not valid.
Signed-off-by Alek Du <[email protected]>
Please add fixes tag:
And also a stable tag:
Quoted 9 lines
--- drivers/mmc/host/sdhci.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)drivers/mmc/host/sdhci.c +0
-0
drivers/mmc/host/sdhci.c void sdhci_reset(struct sdhci_host *host, u8 mask) · line 224
Quoted 7 lines
drivers/mmc/host/sdhci.c +4
-0@@ -218,12 +218,17 @@ void sdhci_reset(struct sdhci_host *host, u8 mask)/* hw clears the bit when it's done */ while (sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask) {if (ktime_after (ktime_get (), timeout)) { +/* check it again, since there is a window between +bit check and time check */ +if (!(sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask)) +break ;
It would be neater like:
while (1) {
bool timedout = ktime_after(ktime_get(), timeout);
if (!(sdhci_readb(host, SDHCI_SOFTWARE_RESET) & mask))
break;
if (timedout) {drivers/mmc/host/sdhci.c void sdhci_reset(struct sdhci_host *host, u8 mask) · line 229
Quoted 5 lines
drivers/mmc/host/sdhci.c +1
-0pr_err ("%s: Reset 0x%x never completed.\n" ,mmc_hostname (host->mmc), (int )mask);sdhci_dumpregs (host);return ; + }else {
The if-clause does a 'return', so the 'else' is not needed
Quoted 7 lines
drivers/mmc/host/sdhci.c +1
-1+udelay (10 ); } -udelay (10 ); } }EXPORT_SYMBOL_GPL (sdhci_reset);
drivers/mmc/host/sdhci.c void sdhci_enable_clk(struct sdhci_host *host, u16 clk) · line 1623
Quoted 8 lines
drivers/mmc/host/sdhci.c +5
-0@@ -1611,12 +1616,19 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk)while (!((clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL )) &SDHCI_CLOCK_INT_STABLE )) {if (ktime_after (ktime_get (), timeout)) { +/* check it again since there is a window between +status check and time check */ +if ((clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL )) + &SDHCI_CLOCK_INT_STABLE ) +break ;
Similarly:
while (1) {
bool timedout = ktime_after(ktime_get(), timeout);
clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL);
if (clk & SDHCI_CLOCK_INT_STABLE)
break;
if (timedout) {drivers/mmc/host/sdhci.c void sdhci_enable_clk(struct sdhci_host *host, u16 clk) · line 1629
Quoted 7 lines
drivers/mmc/host/sdhci.c +1
-1pr_err ("%s: Internal clock never stabilised.\n" ,mmc_hostname (host->mmc));sdhci_dumpregs (host);return ; } -udelay (10 ); +else {
The if-clause does a 'return', so the 'else' is not needed
Quoted 6 lines
drivers/mmc/host/sdhci.c +2
-0+udelay (10 ); + } } clk |=SDHCI_CLOCK_CARD_EN ;
PATCH v3 1/1 sdhci: fix the timeout check window for clock and reset
Quoted 1 line
From
bcb38577961823b4f8f2cc0aec7dd450a81b6ddcMon Sep 17 00:00:00 2001
From: Alek Du <[email protected]>
Date: Fri, 30 Nov 2018 14:02:28 +0800
Subject: [PATCH] sdhci: fix the timeout check window for clock and reset
We observed some premature timeouts on a virtualization platform, the log is like this:
case 1:
[159525.255629] mmc1: Internal clock never stabilised. [159525.255818] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== [159525.256049] mmc1: sdhci: Sys addr: 0x00000000 | Version: 0x00001002 ... [159525.257205] mmc1: sdhci: Wake-up: 0x00000000 | Clock: 0x0000fa03
Quoted 1 line
From the clock control register dump, we are pretty sure the clock was
stablized.
case 2:
[ 914.550127] mmc1: Reset 0x2 never completed. [ 914.550321] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== [ 914.550608] mmc1: sdhci: Sys addr: 0x00000010 | Version: 0x00001002
After checking the sdhci code, we found the timeout check actually has a little window that the CPU can be scheduled out and when it comes back, the original time set or check is not valid.
--- drivers/mmc/host/sdhci.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)
drivers/mmc/host/sdhci.c +13 -5
@@ -216,8 +216,12 @@ void sdhci_reset(struct sdhci_host *host, u8 mask) timeout =ktime_add_ms (ktime_get (),100 );/* hw clears the bit when it's done */ -while (sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask) { -if (ktime_after (ktime_get (), timeout)) { +while (1 ) { +bool timedout =ktime_after (ktime_get (), timeout); + +if (!(sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask)) +break ; +if (timedout) {pr_err ("%s: Reset 0x%x never completed.\n" ,mmc_hostname (host->mmc), (int )mask);sdhci_dumpregs (host);
@@ -1608,9 +1612,13 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk)/* Wait max 20 ms */ timeout =ktime_add_ms (ktime_get (),20 ); -while (!((clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL )) - &SDHCI_CLOCK_INT_STABLE )) { -if (ktime_after (ktime_get (), timeout)) { +while (1 ) { +bool timedout =ktime_after (ktime_get (), timeout); + + clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL ); +if (clk &SDHCI_CLOCK_INT_STABLE ) +break ; +if (timedout) {pr_err ("%s: Internal clock never stabilised.\n" ,mmc_hostname (host->mmc));sdhci_dumpregs (host);
Signature · 1 line
2.17.1
Re: [PATCH V3] sdhci: fix the timeout check window for clock and reset
Quoted 22 lines · Alek
Quoted 1 line
From
bcb38577961823b4f8f2cc0aec7dd450a81b6ddcMon Sep 17 00:00:00 2001From: Alek Du <[email protected]>
Date: Fri, 30 Nov 2018 14:02:28 +0800
Subject: [PATCH] sdhci: fix the timeout check window for clock and resetWe observed some premature timeouts on a virtualization platform, the log is like this:
case 1:
[159525.255629] mmc1: Internal clock never stabilised. [159525.255818] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== [159525.256049] mmc1: sdhci: Sys addr: 0x00000000 | Version: 0x00001002 ... [159525.257205] mmc1: sdhci: Wake-up: 0x00000000 | Clock: 0x0000fa03Quoted 1 line
From the clock control register dump, we are pretty sure the clock was
stablized.
case 2:
[ 914.550127] mmc1: Reset 0x2 never completed. [ 914.550321] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== [ 914.550608] mmc1: sdhci: Sys addr: 0x00000010 | Version: 0x00001002
Quoted 7 lines
After checking the sdhci code, we found the timeout check actually has a little window that the CPU can be scheduled out and when it comes back, the original time set or check is not valid.
Fixes 5a436cc0af62 ("mmc: sdhci: Optimize delay loops")Signed-off-by Alek Du <[email protected]>Cc [email protected] # v4.12+
Quoted 41 lines
--- drivers/mmc/host/sdhci.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)drivers/mmc/host/sdhci.c +13
-5@@ -216,8 +216,12 @@ void sdhci_reset(struct sdhci_host *host, u8 mask) timeout =ktime_add_ms (ktime_get (),100 );/* hw clears the bit when it's done */ -while (sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask) { -if (ktime_after (ktime_get (), timeout)) { +while (1 ) { +bool timedout =ktime_after (ktime_get (), timeout); + +if (!(sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask)) +break ; +if (timedout) {pr_err ("%s: Reset 0x%x never completed.\n" ,mmc_hostname (host->mmc), (int )mask);sdhci_dumpregs (host);@@ -1608,9 +1612,13 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk)/* Wait max 20 ms */ timeout =ktime_add_ms (ktime_get (),20 ); -while (!((clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL )) - &SDHCI_CLOCK_INT_STABLE )) { -if (ktime_after (ktime_get (), timeout)) { +while (1 ) { +bool timedout =ktime_after (ktime_get (), timeout); + + clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL ); +if (clk &SDHCI_CLOCK_INT_STABLE ) +break ; +if (timedout) {pr_err ("%s: Internal clock never stabilised.\n" ,mmc_hostname (host->mmc));sdhci_dumpregs (host);
Re: [PATCH V3] sdhci: fix the timeout check window for clock and reset
In reply to Du, AlekQuoted 5 lines · Alek
From
bcb38577961823b4f8f2cc0aec7dd450a81b6ddcMon Sep 17 00:00:00 2001
From: Alek Du <[email protected]>
Date: Fri, 30 Nov 2018 14:02:28 +0800
Subject: [PATCH] sdhci: fix the timeout check window for clock and reset
Please change the prefix to: "mmc: sdhci".
Quoted 18 lines
We observed some premature timeouts on a virtualization platform, the log is like this:
case 1:
[159525.255629] mmc1: Internal clock never stabilised. [159525.255818] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== [159525.256049] mmc1: sdhci: Sys addr: 0x00000000 | Version: 0x00001002 ... [159525.257205] mmc1: sdhci: Wake-up: 0x00000000 | Clock: 0x0000fa03From the clock control register dump, we are pretty sure the clock was stablized.
case 2:
[ 914.550127] mmc1: Reset 0x2 never completed. [ 914.550321] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== [ 914.550608] mmc1: sdhci: Sys addr: 0x00000010 | Version: 0x00001002
Quoted 7 lines
After checking the sdhci code, we found the timeout check actually has a little window that the CPU can be scheduled out and when it comes back, the original time set or check is not valid.
Fixes 5a436cc0af62 ("mmc: sdhci: Optimize delay loops")Signed-off-by Alek Du <[email protected]>Cc [email protected] # v4.12+
I intended to queue this up as fix, but couldn't apply it. Can you please re-base this on top of v4.20-rc5 or later?
Kind regards
Uffe
Quoted 42 lines
--- drivers/mmc/host/sdhci.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)drivers/mmc/host/sdhci.c +13
-6@@ -216,8 +216,12 @@ void sdhci_reset(struct sdhci_host *host, u8 mask) timeout =ktime_add_ms (ktime_get (),100 );/* hw clears the bit when it's done */ -while (sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask) { -if (ktime_after (ktime_get (), timeout)) { +while (1 ) { +bool timedout =ktime_after (ktime_get (), timeout); + +if (!(sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask)) +break ; +if (timedout) {pr_err ("%s: Reset 0x%x never completed.\n" ,mmc_hostname (host->mmc), (int )mask);sdhci_dumpregs (host);@@ -1608,9 +1612,13 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk)/* Wait max 20 ms */ timeout =ktime_add_ms (ktime_get (),20 ); -while (!((clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL )) - &SDHCI_CLOCK_INT_STABLE )) { -if (ktime_after (ktime_get (), timeout)) { +while (1 ) { +bool timedout =ktime_after (ktime_get (), timeout); + + clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL ); +if (clk &SDHCI_CLOCK_INT_STABLE ) +break ; +if (timedout) {pr_err ("%s: Internal clock never stabilised.\n" ,mmc_hostname (host->mmc));sdhci_dumpregs (host); --2.17.1
PATCH v3 1/1 mmc: sdhci: fix the timeout check window for clock and reset
Quoted 1 line
From
a081e783383adf1179c71bc37b4e199d087af643Mon Sep 17 00:00:00 2001
From: Alek Du <[email protected]>
Date: Fri, 30 Nov 2018 14:02:28 +0800
Subject: [PATCH] mmc: sdhci: fix the timeout check window for clock and reset
We observed some premature timeouts on a virtualization platform, the log is like this:
case 1:
[159525.255629] mmc1: Internal clock never stabilised. [159525.255818] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== [159525.256049] mmc1: sdhci: Sys addr: 0x00000000 | Version: 0x00001002 ... [159525.257205] mmc1: sdhci: Wake-up: 0x00000000 | Clock: 0x0000fa03
Quoted 1 line
From the clock control register dump, we are pretty sure the clock was
stablized.
case 2:
[ 914.550127] mmc1: Reset 0x2 never completed. [ 914.550321] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== [ 914.550608] mmc1: sdhci: Sys addr: 0x00000010 | Version: 0x00001002
After checking the sdhci code, we found the timeout check actually has a little window that the CPU can be scheduled out and when it comes back, the original time set or check is not valid.
--- drivers/mmc/host/sdhci.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)
drivers/mmc/host/sdhci.c +13 -5
@@ -216,8 +216,12 @@ void sdhci_reset(struct sdhci_host *host, u8 mask) timeout =ktime_add_ms (ktime_get (),100 );/* hw clears the bit when it's done */ -while (sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask) { -if (ktime_after (ktime_get (), timeout)) { +while (1 ) { +bool timedout =ktime_after (ktime_get (), timeout); + +if (!(sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask)) +break ; +if (timedout) {pr_err ("%s: Reset 0x%x never completed.\n" ,mmc_hostname (host->mmc), (int )mask);sdhci_dumpregs (host);
@@ -1608,9 +1612,13 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk)/* Wait max 20 ms */ timeout =ktime_add_ms (ktime_get (),20 ); -while (!((clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL )) - &SDHCI_CLOCK_INT_STABLE )) { -if (ktime_after (ktime_get (), timeout)) { +while (1 ) { +bool timedout =ktime_after (ktime_get (), timeout); + + clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL ); +if (clk &SDHCI_CLOCK_INT_STABLE ) +break ; +if (timedout) {pr_err ("%s: Internal clock never stabilised.\n" ,mmc_hostname (host->mmc));sdhci_dumpregs (host);
Signature · 1 line
2.17.1
Re: [PATCH V3 rebase] mmc: sdhci: fix the timeout check window for clock and reset
Quoted 23 lines · Alek
From
a081e783383adf1179c71bc37b4e199d087af643Mon Sep 17 00:00:00 2001
From: Alek Du <[email protected]>
Date: Fri, 30 Nov 2018 14:02:28 +0800
Subject: [PATCH] mmc: sdhci: fix the timeout check window for clock and resetWe observed some premature timeouts on a virtualization platform, the log is like this:
case 1:
[159525.255629] mmc1: Internal clock never stabilised. [159525.255818] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== [159525.256049] mmc1: sdhci: Sys addr: 0x00000000 | Version: 0x00001002 ... [159525.257205] mmc1: sdhci: Wake-up: 0x00000000 | Clock: 0x0000fa03From the clock control register dump, we are pretty sure the clock was stablized.
case 2:
[ 914.550127] mmc1: Reset 0x2 never completed. [ 914.550321] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== [ 914.550608] mmc1: sdhci: Sys addr: 0x00000010 | Version: 0x00001002
Quoted 7 lines
After checking the sdhci code, we found the timeout check actually has a little window that the CPU can be scheduled out and when it comes back, the original time set or check is not valid.
Fixes 5a436cc0af62 ("mmc: sdhci: Optimize delay loops")Cc [email protected] # v4.12+Signed-off-by Alek Du <[email protected]>
I am still not able to apply this, however the reason is not that a rebase is needed.
Instead it seems like the patch is malformed, exactly why I don't know. I am using patchwork to fetch the patch, but I even tried fetching it directly via my gmail client, no luck. In both case it can't be applied and checkpatch is also complaining.
Could you check at your side and see what can be wrong? If there is too much hazzle I can manually fixup the patch next week, as one time thing.
Kind regards
Uffe
Quoted 42 lines
--- drivers/mmc/host/sdhci.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)drivers/mmc/host/sdhci.c +13
-6@@ -216,8 +216,12 @@ void sdhci_reset(struct sdhci_host *host, u8 mask) timeout =ktime_add_ms (ktime_get (),100 );/* hw clears the bit when it's done */ -while (sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask) { -if (ktime_after (ktime_get (), timeout)) { +while (1 ) { +bool timedout =ktime_after (ktime_get (), timeout); + +if (!(sdhci_readb (host,SDHCI_SOFTWARE_RESET ) & mask)) +break ; +if (timedout) {pr_err ("%s: Reset 0x%x never completed.\n" ,mmc_hostname (host->mmc), (int )mask);sdhci_dumpregs (host);@@ -1608,9 +1612,13 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk)/* Wait max 20 ms */ timeout =ktime_add_ms (ktime_get (),20 ); -while (!((clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL )) - &SDHCI_CLOCK_INT_STABLE )) { -if (ktime_after (ktime_get (), timeout)) { +while (1 ) { +bool timedout =ktime_after (ktime_get (), timeout); + + clk =sdhci_readw (host,SDHCI_CLOCK_CONTROL ); +if (clk &SDHCI_CLOCK_INT_STABLE ) +break ; +if (timedout) {pr_err ("%s: Internal clock never stabilised.\n" ,mmc_hostname (host->mmc));sdhci_dumpregs (host); --2.17.1
Re: [PATCH V3 rebase] mmc: sdhci: fix the timeout check window for clock and reset
Quoted 3 lines · On Thu, 6 Dec 2018 08:55:04 +0100 Ulf Hansson <[email protected]> wrote:
Could you check at your side and see what can be wrong? If there is too much hazzle I can manually fixup the patch next week, as one time thing.
Sorry for the confusion, I just resent with git send-email to avoid any thing unexpected. Please try again.
Quoted 4 lines
Kind regards
Uffe
Adrian Hunter
maintainerQuoted 42 lines · Alek
Quoted 2 lines · On Fri, 30 Nov 2018 16:40:04 +0200 Adrian Hunter <[email protected]>…
So you are saying this only happens under virtualization?
Yes, I saw the issue under ACRN virtualization Service OS (4.19 kernel). But theoretically it can happen in other case when scheduling is not that good. (due to bad driver or other high priority task)
Quoted 10 lines
Quoted 7 lines
Please look at the
sdhci_enable_clk()below, there is a window in clock stabilization check. The first check is to check status register, the second check is to check if time passed. That's why I can capture a case that after time passed, the actually clock control register indicated that clock is stable. So the error handling is wrong...Sure, but "Internal clock never stabilised." is not one of the errors you listed.
Sorry my bad not listing all the error log:
Case 1. clock stabilization timeout: (the below clock control dump shows clock is good)
[159525.255629] mmc1: Internal clock never stabilised. [159525.255818] mmc1: sdhci: ============ SDHCI REGISTER DUMP =========== [159525.256049] mmc1: sdhci: Sys addr: 0x00000000 | Version: 0x00001002 [159525.256277] mmc1: sdhci: Blk size: 0x00000000 | Blk cnt: 0x00000000 [159525.256523] mmc1: sdhci: Argument: 0x00000000 | Trn mode: 0x00000000 [159525.256752] mmc1: sdhci: Present: 0x1fff0000 | Host ctl: 0x00000000 [159525.256979] mmc1: sdhci: Power: 0x0000000b | Blk gap: 0x00000080 [159525.257205] mmc1: sdhci: Wake-up: 0x00000000 | Clock: 0x0000fa03Case 2. Reset timeout: (the same check window in
sdhci_reset())[ 7639.968613] mmc1: Reset 0x4 never completed.Case 3. Hardware interrupt timeout
[ 1049.561728] mmc1: Timeout waiting for hardware interrupt.Quoted 2 lines
Quoted 2 lines
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
Also the
sdhci_send_commandcommands is not in spin lock There is a windows betweenmod_timerand real command send...What code path does not have a spin lock?
Ouch my bad, the
sdhci_send_commandare called either from spinlock or IRQ handler, so this part is good ...I'll send a new patch to cover case 1 and case 2 if you agree.
Please do the mod_timer case also, but please make it a separate patch. Prior to v4.18 it was essentially a 10-second timer, without a preemptible gap afterwards, so extremely unlikely to timeout prematurely, hence: