lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1423894668-8886-3-git-send-email-addy.ke@rock-chips.com>
Date:	Sat, 14 Feb 2015 14:17:47 +0800
From:	Addy Ke <addy.ke@...k-chips.com>
To:	jh80.chung@...sung.com, ulf.hansson@...aro.org, olof@...om.net,
	alim.akhtar@...il.com, a.hajda@...sung.com, dianders@...omium.org
Cc:	heiko@...ech.de, cf@...k-chips.com, lintao@...k-chips.com,
	huangtao@...k-chips.com, linux-kernel@...r.kernel.org,
	linux-mmc@...r.kernel.org, linux-arm-kernel@...ts.infradead.org,
	linux-rockchip@...ts.infradead.org,
	Addy Ke <addy.ke@...k-chips.com>
Subject: [PATCH v4 2/3] mmc: dw_mmc: fix bug that cause 'Timeout sending command'

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 <addy.ke@...k-chips.com>
Changes in v4:
- Retry to wait and reset all blocks until data unbusy.
  I have a sd card, which need retry 2 times to change to unbusy state.

---
 drivers/mmc/host/dw_mmc.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 3472f9b..ac21863 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,36 @@ 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)
+{
+	bool ret = true;
+	struct dw_mci *host = slot->host;
+	unsigned long timeout = jiffies + msecs_to_jiffies(500);
+
+	if (host->state == STATE_WAITING_CMD11_DONE)
+		return;
+
+	do {
+		do {
+			if (!dw_mci_card_busy(slot->mmc))
+				return;
+			usleep_range(50, 100);
+		} 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".
+		 */
+		ret = dw_mci_ctrl_reset(host, SDMMC_CTRL_ALL_RESET_FLAGS);
+
+	} while (!ret || 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;
@@ -896,6 +927,8 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit)
 	u32 clk_en_a;
 	u32 sdmmc_cmd_bits = SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT;
 
+	dw_mci_wait_busy(slot);
+
 	/* 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;
-- 
1.8.3.2


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ