Re: [PATCH v2 1/2] mmc: dw_mmc: fix bug that cause 'Timeout sending command'
From: Addy <hidden>
Date: 2015-02-11 02:58:17
Also in:
linux-arm-kernel, linux-mmc, lkml
On 2015/02/10 23:22, Alim Akhtar wrote:
Hi Addy, On Mon, Feb 9, 2015 at 12:55 PM, Addy Ke [off-list ref] wrote:quoted
Because of some uncertain factors, such as worse card or worse hardware, DAT[3:0](the data lines) may be pulled down by card, and mmc controller will be in busy state. This should not happend when mmc controller send command to update card clocks. If this happends, mci_send_cmd will be failed and we will get 'Timeout sending command', and then system will be blocked. To avoid this, we need reset mmc controller. Signed-off-by: Addy Ke <redacted> --- drivers/mmc/host/dw_mmc.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+)diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 4d2e3c2..b0b57e3 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c@@ -100,6 +100,7 @@ struct idmac_desc { }; #endif /* CONFIG_MMC_DW_IDMAC */ +static int dw_mci_card_busy(struct mmc_host *mmc); static bool dw_mci_reset(struct dw_mci *host); static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset);@@ -888,6 +889,31 @@ static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg) cmd, arg, cmd_status); } +static void dw_mci_wait_busy(struct dw_mci_slot *slot) +{ + struct dw_mci *host = slot->host; + unsigned long timeout = jiffies + msecs_to_jiffies(500); +Why 500 msec?
This timeout value is the same as mci_send_cmd:
static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg)
{
struct dw_mci *host = slot->host;
unsigned long timeout = jiffies + msecs_to_jiffies(500);
....
}
I have not clear that which is suitable.
Do you have any suggestion on it?quoted
+ do { + if (!dw_mci_card_busy(slot->mmc)) + return; + cpu_relax(); + } while (time_before(jiffies, timeout)); + + dev_err(host->dev, "Data busy (status %#x)\n", + mci_readl(slot->host, STATUS)); + + /* + * Data busy, this should not happend when mmc controller send command + * to update card clocks in non-volt-switch state. If it happends, we + * should reset controller to avoid getting "Timeout sending command". + */ + dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS); +Why you need to reset all blocks? may be CTRL_RESET is good enough here.
I have tested on rk3288, if only reset ctroller, data busy bit will not be cleaned,and we will still get "Timeout sending command".
quoted
+ /* Fail to reset controller or still data busy, WARN_ON! */ + WARN_ON(dw_mci_card_busy(slot->mmc)); +} + static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) { struct dw_mci *host = slot->host;@@ -899,6 +925,8 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) /* We must continue to set bit 28 in CMD until the change is complete */ if (host->state == STATE_WAITING_CMD11_DONE) sdmmc_cmd_bits |= SDMMC_CMD_VOLT_SWITCH; + else + dw_mci_wait_busy(slot);hmm...I would suggest you to call dw_mci_wait_busy() from inside mci_send_cmd(), seems like dw_mmc hangs while sending update clock cmd in multiple cases.see [1] [1]: http://permalink.gmane.org/gmane.linux.kernel.mmc/31140
I think this patch is more reasonable. So I will resend patches based on this patch. thank you!
quoted
if (!clock) { mci_writel(host, CLKENA, 0); -- 1.8.3.2 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel