Patchwork mmc: dw_mmc: Don't start commands while busy

login
register
mail settings
Submitter Douglas Anderson
Date Feb. 20, 2015, 6:49 p.m.
Message ID <1424458179-5456-1-git-send-email-dianders@chromium.org>
Download mbox | patch
Permalink /patch/5858221/
State New, archived
Headers show

Comments

Douglas Anderson - Feb. 20, 2015, 6:49 p.m.
We've seen problems on some WiFi modules where we seem to send a CMD53
(which requires the data lines) while the module is asserting busy.
We shouldn't do that.

The Designware Databook says that before issuing a new data transfer
command we should check for busy, so that's what we'll do.

We'll leverage the existing dw_mmc knowledge about whether it should
wait for the previous command to finish to know whether we should
check for busy before sending the command.  This means we won't end up
incorrectly waiting for things like CMD52 (SDIO) or CMD13 (SD) which
don't use the data line.

Signed-off-by: Doug Anderson <dianders@chromium.org>
---
 drivers/mmc/host/dw_mmc.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)
Douglas Anderson - Feb. 20, 2015, 8:31 p.m.
Hi,

On Fri, Feb 20, 2015 at 10:49 AM, Doug Anderson <dianders@chromium.org> wrote:
> We've seen problems on some WiFi modules where we seem to send a CMD53
> (which requires the data lines) while the module is asserting busy.
> We shouldn't do that.
>
> The Designware Databook says that before issuing a new data transfer
> command we should check for busy, so that's what we'll do.
>
> We'll leverage the existing dw_mmc knowledge about whether it should
> wait for the previous command to finish to know whether we should
> check for busy before sending the command.  This means we won't end up
> incorrectly waiting for things like CMD52 (SDIO) or CMD13 (SD) which
> don't use the data line.
>
> Signed-off-by: Doug Anderson <dianders@chromium.org>
> ---
>  drivers/mmc/host/dw_mmc.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)

Sorry for the quick spin.  After I posted this I re-read all the
messages and it looks like Addy has an actual SD card (not SDIO) that
is also asserting busy.  He's seeing it assert busy around the clock
update.

I believe his bug can be fixed by also adding the busy check to
mci_send_cmd(), so I'll shortly post V2 of this patch.  Hopefully Addy
will be able to test all 3 of my patches together and his card will be
totally happy.

-Doug
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 4d2e3c2..a3fcc91 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -102,6 +102,7 @@  struct idmac_desc {
 
 static bool dw_mci_reset(struct dw_mci *host);
 static bool dw_mci_ctrl_reset(struct dw_mci *host, u32 reset);
+static int dw_mci_card_busy(struct mmc_host *mmc);
 
 #if defined(CONFIG_DEBUG_FS)
 static int dw_mci_req_show(struct seq_file *s, void *v)
@@ -335,6 +336,26 @@  static u32 dw_mci_prep_stop_abort(struct dw_mci *host, struct mmc_command *cmd)
 	return cmdr;
 }
 
+static void dw_mci_wait_while_busy(struct dw_mci *host, u32 cmd_flags)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(500);
+
+	/*
+	 * Databook says that before issuing a new data transfer command
+	 * we need to check to see if the card is busy.  Data transfer commands
+	 * all have SDMMC_CMD_PRV_DAT_WAIT set, so we'll key off that.
+	 */
+	if (cmd_flags & SDMMC_CMD_PRV_DAT_WAIT) {
+		while (dw_mci_card_busy(host->cur_slot->mmc)) {
+			if (time_after(jiffies, timeout)) {
+				dev_err(host->dev, "Busy; trying anyway\n");
+				break;
+			}
+			udelay(10);
+		}
+	}
+}
+
 static void dw_mci_start_command(struct dw_mci *host,
 				 struct mmc_command *cmd, u32 cmd_flags)
 {
@@ -345,6 +366,7 @@  static void dw_mci_start_command(struct dw_mci *host,
 
 	mci_writel(host, CMDARG, cmd->arg);
 	wmb();
+	dw_mci_wait_while_busy(host, cmd_flags);
 
 	mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START);
 }