summaryrefslogtreecommitdiff
path: root/drivers/mmc
diff options
context:
space:
mode:
authorDong Aisheng <b29396@freescale.com>2012-09-21 18:33:06 +0800
committerXinyu Chen <xinyu.chen@freescale.com>2012-09-29 11:10:08 +0800
commit5378680707d76a364ede24f98ea2cc26c605f5b1 (patch)
treeff6e8315d7507a8d2534c090cacd5334767f08c6 /drivers/mmc
parent41fe8a6f5481ac15d1911e52251d7147f973d24e (diff)
ENGR00225534-2 mmc: sdhci: using cancel_work_sync not cancel_delayed_work
We recently met an rarely happened sychronization issue which can cause mmc timeout during transfer as follows: [ OK ]onfiguring network interfaces... [ OK ]ctivating swap... mmc0: Timeout waiting for hardware interrupt. mmc0: Timeout waiting for hardware interrupt. mmc0: Timeout waiting for hardware interrupt. mmcblk0: error -110 sending status command, retrying mmcblk0: error -110 sending stop command, original cmd response 0x900, card status 0xd00 mmcblk0: error -110 transferring data, sector 9981952, nr 16, cmd response 0x900, card status 0xc00 end_request: I/O error, dev mmcblk0, sector 9981952 The root cause is that host uses cancel_delayed_work to cancel the delayed clock disable work to avoid clock to be disabled if a new cmd transfer request happens. However, the work callback may already be running during the excution of cancel_delayed_work which can not be cancelled and causes the clock probably still to be disabled during cmd transfer, then cmd timeout happens. Using cancel_work_sync instead to wait for the completion of clock disable first then we can make sure the clock can not be disabled during the cmd transfer. BTW, although the original code checks if in interrupt context, however, it's still not interrupt context safe due to the unsafe platform_clk_ctrl, so it's ok to directly use cancel_work_sync here and sdhci_enable_clk is simply not allowed to be called in irq context. Acked-by: Ryan QIAN <b32804@freescale.com> Signed-off-by: Dong Aisheng <b29396@freescale.com>
Diffstat (limited to 'drivers/mmc')
-rwxr-xr-xdrivers/mmc/host/sdhci.c8
1 files changed, 2 insertions, 6 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 6551bd19a8af..cf114c2eda68 100755
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -30,7 +30,7 @@
#include "sdhci.h"
#define DRIVER_NAME "sdhci"
-#define CLK_TIMEOUT (10 * HZ)
+#define CLK_TIMEOUT (10 * HZ)
#define DBG(f, x...) \
pr_debug(DRIVER_NAME " [%s()]: " f, __func__,## x)
@@ -85,11 +85,7 @@ static bool sdhci_can_gate_clk(struct sdhci_host *host)
static void sdhci_enable_clk(struct sdhci_host *host)
{
if (host->clk_mgr_en) {
- if (!in_interrupt())
- cancel_delayed_work(&host->clk_worker);
- else
- __cancel_delayed_work(&host->clk_worker);
-
+ cancel_delayed_work_sync(&host->clk_worker);
if (!host->clk_status && host->ops->platform_clk_ctrl)
host->ops->platform_clk_ctrl(host, true);
}