Re: [PATCH] mmc: mmci: Send a CMD12 to clear the DPSM at errors

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



hi Ulf

One comment below in mmci_cmd_irq function

when I rebase my next serie about "busy detect" I've a kernel panic
null pointer, could you give me some time to investigate this issue
before apply this patch.


On 1/29/19 3:35 PM, Ulf Hansson wrote:
The current approach with sending a CMD12 (STOP_TRANSMISSION) to complete a
data transfer request, either because of using the open-ended transmission
type or because of receiving an error during a pre-defined data transfer,
isn't sufficient for the STM32 sdmmc variant. More precisely, this variant
needs to clear the DPSM ("Data Path State Machine") by sending a CMD12, for
all failing ADTC commands.

Support this, by adding a struct mmc_command inside the struct mmci_host
and initialize it to a CMD12 during ->probe(). Let's also add checks for
the new conditions, to enable mmci_data_irq() and mmci_cmd_irq() to
postpone the calls to mmci_request_end(), but instead send the CMD12.

Cc: Ludovic Barre <ludovic.barre@xxxxxx>
Signed-off-by: Ulf Hansson <ulf.hansson@xxxxxxxxxx>
---
  drivers/mmc/host/mmci.c | 25 +++++++++++++++++++++++--
  drivers/mmc/host/mmci.h |  1 +
  2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index e352f5ad5801..45b97b41601c 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -1127,6 +1127,12 @@ mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c)
  	writel(c, base + MMCICOMMAND);
  }
+static void mmci_stop_command(struct mmci_host *host)
+{
+	host->stop_abort.error = 0;
+	mmci_start_command(host, &host->stop_abort, 0);
+}
+
  static void
  mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
  	      unsigned int status)
@@ -1196,10 +1202,16 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
  			/* The error clause is handled above, success! */
  			data->bytes_xfered = data->blksz * data->blocks;
- if (!data->stop || (host->mrq->sbc && !data->error))
+		if (!data->stop) {
+			if (host->variant->cmdreg_stop && data->error)
+				mmci_stop_command(host);
+			else
+				mmci_request_end(host, data->mrq);
+		} else if (host->mrq->sbc && !data->error) {
  			mmci_request_end(host, data->mrq);
-		else
+		} else {
  			mmci_start_command(host, data->stop, 0);
+		}
  	}
  }
@@ -1298,6 +1310,10 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command *cmd,
  			mmci_dma_error(host);
mmci_stop_data(host);
+			if (host->variant->cmdreg_stop && cmd->error) {
+				mmci_stop_command(host);
+				return;
+			}

  		}

In fact a cmd without host->data could fail with DPSM enabled.
example:
sent a cmd12 with MMC_RSP_BUSY flag (R1B command) and so no data.
In sdmmc variant the MMCIDATATIMER is used to busy timeout.
The DPSM is used to sample D0 line and is activated.
the DTIMEOUT flag is set after when no end of busy received before the timeout. (DPSM stays in BUSY and wait for Abort)

So The mmci_stop_command may be sent when there are cmd->error and status & MCI_DATATIMEOUT


  		mmci_request_end(host, host->mrq);
  	} else if (sbc) {
@@ -1956,6 +1972,11 @@ static int mmci_probe(struct amba_device *dev,
  		mmc->max_busy_timeout = 0;
  	}
+ /* Prepare a CMD12 - needed to clear the DPSM on some variants. */
+	host->stop_abort.opcode = MMC_STOP_TRANSMISSION;
+	host->stop_abort.arg = 0;
+	host->stop_abort.flags = MMC_RSP_R1B | MMC_CMD_AC;
+
  	mmc->ops = &mmci_ops;
/* We support these PM capabilities. */
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 24229097d05c..14df81054438 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -377,6 +377,7 @@ struct mmci_host {
  	void __iomem		*base;
  	struct mmc_request	*mrq;
  	struct mmc_command	*cmd;
+	struct mmc_command	stop_abort;
  	struct mmc_data		*data;
  	struct mmc_host		*mmc;
  	struct clk		*clk;




[Index of Archives]     [Linux Memonry Technology]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux