Skip to contentSkip to conversation

mmc: dw_mmc: mmc_test related fixes

PATCH Superseded James Hogan 4 participants 9 messages Jun 29, 2011 – Jul 9, 2011

Subsystems (2)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover mmc: dw_mmc: mmc_test related fixes

More improvements and fixes for the Synopsys DesignWare MCI driver so that it passes the mmc_test suite:

[PATCH 1/4] mmc: dw_mmc: fix stop when fallen back to PIO
Fixes a hang after an error/timeout in PIO mode.
[PATCH 2/4] mmc: dw_mmc: remove unnecessary error messages
Removes some dev_err's since an errno is sufficient.
[PATCH 3/4] mmc: dw_mmc: handle "no CRC status" error
Fixes "Correct xfer_size at write" tests.
[PATCH 4/4] mmc: dw_mmc: reset FIFO after an error
Fixes modified "Correct xfer_size at write" tests (3 blocks instead of 2).

 drivers/mmc/host/dw_mmc.c  |   41 +++++++++++++++++++++++++++++++----------
 include/linux/mmc/dw_mmc.h |    2 ++
 2 files changed, 33 insertions(+), 10 deletions(-)
#1 lore raw

PATCH 1/4 mmc: dw_mmc: fix stop when fallen back to PIO

There are several situations when dw_mci_submit_data_dma() decides to fall back to PIO mode instead of using DMA, due to a short (to avoid overhead) or "complex" (e.g. with unaligned buffers) transaction, even though host->use_dma is set. However dw_mci_stop_dma() decides whether to stop DMA or set the EVENT_XFER_COMPLETE event based on host->use_dma. When falling back to PIO mode this results in data timeout errors getting missed and the driver locking up.

Therefore add host->using_dma to indicate whether the current transaction is using dma or not, and adjust dw_mci_stop_dma() to use that instead.

---
 drivers/mmc/host/dw_mmc.c  |    6 +++++-
 include/linux/mmc/dw_mmc.h |    2 ++
 2 files changed, 7 insertions(+), 1 deletions(-)
drivers/mmc/host/dw_mmc.c +5 -1
index 10b6979..fcff3c0 100644
@@ -287,7 +287,7 @@ static void send_stop_cmd(struct dw_mci *host, struct mmc_data *data)
 /* DMA interface functions */
 static void dw_mci_stop_dma(struct dw_mci *host)
 {
-	if (host->use_dma) {
+	if (host->using_dma) {
 		host->dma_ops->stop(host);
 		host->dma_ops->cleanup(host);
 	} else {
@@ -435,6 +435,8 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
 	unsigned int i, direction, sg_len;
 	u32 temp;
 
+	host->using_dma = 0;
+
 	/* If we don't have a channel, we can't do DMA */
 	if (!host->use_dma)
 		return -ENODEV;
@@ -454,6 +456,8 @@ static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data)
 			return -EINVAL;
 	}
 
+	host->using_dma = 1;
+
 	if (data->flags & MMC_DATA_READ)
 		direction = DMA_FROM_DEVICE;
 	else
include/linux/mmc/dw_mmc.h +2 -0
index f3f68ee..6b46819 100644
@@ -48,6 +48,7 @@ struct mmc_data;
  * @data: The data currently being transferred, or NULL if no data
  *	transfer is in progress.
  * @use_dma: Whether DMA channel is initialized or not.
+ * @using_dma: Whether DMA is in use for the current transfer.
  * @sg_dma: Bus address of DMA buffer.
  * @sg_cpu: Virtual address of DMA buffer.
  * @dma_ops: Pointer to platform-specific DMA callbacks.
@@ -121,6 +122,7 @@ struct dw_mci {
 
 	/* DMA interface members*/
 	int			use_dma;
+	int			using_dma;
 
 	dma_addr_t		sg_dma;
 	void			*sg_cpu;
Signature · 1 line
1.7.2.3
#2 lore raw

PATCH 2/4 mmc: dw_mmc: remove unnecessary error messages

In reply to James Hogan

Remove error messages for timeout and CRC failure, since the error code already indicates the problem.

---
 drivers/mmc/host/dw_mmc.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)
drivers/mmc/host/dw_mmc.c +0 -4
index fcff3c0..bf2157a 100644
@@ -908,12 +908,8 @@ static void dw_mci_tasklet_func(unsigned long priv)
 
 			if (status & DW_MCI_DATA_ERROR_FLAGS) {
 				if (status & SDMMC_INT_DTO) {
-					dev_err(&host->pdev->dev,
-						"data timeout error\n");
 					data->error = -ETIMEDOUT;
 				} else if (status & SDMMC_INT_DCRC) {
-					dev_err(&host->pdev->dev,
-						"data CRC error\n");
 					data->error = -EILSEQ;
 				} else {
 					dev_err(&host->pdev->dev,
Signature · 1 line
1.7.2.3
#3 lore raw

PATCH 3/4 mmc: dw_mmc: handle "no CRC status" error

In reply to James Hogan

When a data write isn't acknowledged by the card (so no CRC status token is detected after the data), the error -EIO is returned instead of the -ETIMEDOUT expected by mmc_test 15 - "Correct xfer_size at write (start failure)" and 17 "Correct xfer_size at write (midway failure)". In PIO mode the reported number of bytes transferred is also exaggerated since the last block actually failed.

Handle the "Write no CRC" error specially, setting the error to -ETIMEDOUT and setting the bytes_xferred to 0.

---
 drivers/mmc/host/dw_mmc.c |   19 +++++++++++++++----
 1 files changed, 15 insertions(+), 4 deletions(-)
drivers/mmc/host/dw_mmc.c +15 -4
index bf2157a..0dac397 100644
@@ -496,15 +496,16 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data)
 	host->sg = NULL;
 	host->data = data;
 
+	if (data->flags & MMC_DATA_READ)
+		host->dir_status = DW_MCI_RECV_STATUS;
+	else
+		host->dir_status = DW_MCI_SEND_STATUS;
+
 	if (dw_mci_submit_data_dma(host, data)) {
 		host->sg = data->sg;
 		host->pio_offset = 0;
 		host->part_buf_start = 0;
 		host->part_buf_count = 0;
-		if (data->flags & MMC_DATA_READ)
-			host->dir_status = DW_MCI_RECV_STATUS;
-		else
-			host->dir_status = DW_MCI_SEND_STATUS;
 
 		mci_writel(host, RINTSTS, SDMMC_INT_TXDR | SDMMC_INT_RXDR);
 		temp = mci_readl(host, INTMASK);
@@ -911,6 +912,16 @@ static void dw_mci_tasklet_func(unsigned long priv)
 					data->error = -ETIMEDOUT;
 				} else if (status & SDMMC_INT_DCRC) {
 					data->error = -EILSEQ;
+				} else if (status & SDMMC_INT_EBE &&
+					   host->dir_status ==
+							DW_MCI_SEND_STATUS) {
+					/*
+					 * No data CRC status was returned.
+					 * The number of bytes transferred will
+					 * be exaggerated in PIO mode.
+					 */
+					data->bytes_xfered = 0;
+					data->error = -ETIMEDOUT;
 				} else {
 					dev_err(&host->pdev->dev,
 						"data FIFO error "
Signature · 1 line
1.7.2.3
#4 lore raw

PATCH 4/4 mmc: dw_mmc: reset FIFO after an error

In reply to James Hogan

If an error occurs mid way through a transaction (such as a missing CRC status response after the 2nd block written out of 3), then the FIFO may still contain data which will interfere with the next transaction. Therefore after an error has been detected, reset the fifo using the CTRL register.

---
 drivers/mmc/host/dw_mmc.c |   12 +++++++++++-
 1 files changed, 11 insertions(+), 1 deletions(-)
drivers/mmc/host/dw_mmc.c +11 -1
index 0dac397..0c839d3 100644
@@ -849,7 +849,7 @@ static void dw_mci_tasklet_func(unsigned long priv)
 	struct mmc_command *cmd;
 	enum dw_mci_state state;
 	enum dw_mci_state prev_state;
-	u32 status;
+	u32 status, ctrl;
 
 	spin_lock(&host->lock);
 
@@ -929,6 +929,16 @@ static void dw_mci_tasklet_func(unsigned long priv)
 						status);
 					data->error = -EIO;
 				}
+				/*
+				 * After an error, there may be data lingering
+				 * in the FIFO, so reset it - doing so
+				 * generates a block interrupt, hence setting
+				 * the scatter-gather pointer to NULL.
+				 */
+				host->sg = NULL;
+				ctrl = mci_readl(host, CTRL);
+				ctrl |= SDMMC_CTRL_FIFO_RESET;
+				mci_writel(host, CTRL, ctrl);
 			} else {
 				data->bytes_xfered = data->blocks * data->blksz;
 				data->error = 0;
Signature · 1 line
1.7.2.3
Acked-by on the v1 series
#5 lore raw
In reply to James Hogan
Quoted 13 lines · James Hogan

More improvements and fixes for the Synopsys DesignWare MCI driver so that it passes the mmc_test suite:

[PATCH 1/4] mmc: dw_mmc: fix stop when fallen back to PIO Fixes a hang after an error/timeout in PIO mode. [PATCH 2/4] mmc: dw_mmc: remove unnecessary error messages Removes some dev_err's since an errno is sufficient. [PATCH 3/4] mmc: dw_mmc: handle "no CRC status" error Fixes "Correct xfer_size at write" tests.
[PATCH 4/4] mmc: dw_mmc: reset FIFO after an error Fixes modified "Correct xfer_size at write" tests (3 blocks instead of 2).

Quoted 3 lines

 drivers/mmc/host/dw_mmc.c  |   41 +++++++++++++++++++++++++++++++---------- include/linux/mmc/dw_mmc.h |    2 ++

 2 files changed, 33 insertions(+), 10 deletions(-)

These all look good to me.

maintainer Tested-by
#6 lore raw
Quoted 26 lines · Will Newton
Quoted 13 lines · James Hogan

More improvements and fixes for the Synopsys DesignWare MCI driver so that it passes the mmc_test suite:

[PATCH 1/4] mmc: dw_mmc: fix stop when fallen back to PIO
Fixes a hang after an error/timeout in PIO mode.
[PATCH 2/4] mmc: dw_mmc: remove unnecessary error messages
Removes some dev_err's since an errno is sufficient.
[PATCH 3/4] mmc: dw_mmc: handle "no CRC status" error
Fixes "Correct xfer_size at write" tests.
[PATCH 4/4] mmc: dw_mmc: reset FIFO after an error
Fixes modified "Correct xfer_size at write" tests (3 blocks instead of 2).

Quoted 3 lines
 drivers/mmc/host/dw_mmc.c  |   41 +++++++++++++++++++++++++++++++----------
 include/linux/mmc/dw_mmc.h |    2 ++
 2 files changed, 33 insertions(+), 10 deletions(-)

These all look good to me.

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

#7 lore raw
Quoted 1 line · Jaehoon Chung

Thanks for testing

Cheers
James

Quoted 29 lines
Quoted 26 lines · Will Newton
Quoted 13 lines · James Hogan

More improvements and fixes for the Synopsys DesignWare MCI driver so that it passes the mmc_test suite:

[PATCH 1/4] mmc: dw_mmc: fix stop when fallen back to PIO
Fixes a hang after an error/timeout in PIO mode.
[PATCH 2/4] mmc: dw_mmc: remove unnecessary error messages
Removes some dev_err's since an errno is sufficient.
[PATCH 3/4] mmc: dw_mmc: handle "no CRC status" error
Fixes "Correct xfer_size at write" tests.
[PATCH 4/4] mmc: dw_mmc: reset FIFO after an error
Fixes modified "Correct xfer_size at write" tests (3 blocks instead of 2).

Quoted 3 lines
 drivers/mmc/host/dw_mmc.c  |   41 +++++++++++++++++++++++++++++++----------
 include/linux/mmc/dw_mmc.h |    2 ++
 2 files changed, 33 insertions(+), 10 deletions(-)

These all look good to me.

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

#8 lore raw
In reply to James Hogan

Hi James,

Quoted 12 lines · James Hogan

More improvements and fixes for the Synopsys DesignWare MCI driver so that it passes the mmc_test suite:

[PATCH 1/4] mmc: dw_mmc: fix stop when fallen back to PIO
Fixes a hang after an error/timeout in PIO mode.
[PATCH 2/4] mmc: dw_mmc: remove unnecessary error messages
Removes some dev_err's since an errno is sufficient.
[PATCH 3/4] mmc: dw_mmc: handle "no CRC status" error
Fixes "Correct xfer_size at write" tests.
[PATCH 4/4] mmc: dw_mmc: reset FIFO after an error
Fixes modified "Correct xfer_size at write" tests (3 blocks instead of 2).

All pushed to mmc-next for 3.1 with Will's ACK and Jaehoon's Tested-by, thanks.

- Chris.

Signature · 2 lines
Chris Ball   <[email protected]>   <http://printf.net/>
One Laptop Per Child