All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ben Dooks <ben@simtec.co.uk>
To: linux-mmc@vger.kernel.org
Subject: [patch 9/9] s3cmci: DMA fixes
Date: Tue, 18 Aug 2009 12:56:13 +0100	[thread overview]
Message-ID: <20090818115700.076744295@fluff.org> (raw)
In-Reply-To: 20090818115604.056816271@fluff.org

[-- Attachment #1: s3cmci-dma-fixes.patch --]
[-- Type: text/plain, Size: 5886 bytes --]

Fixes for the DMA transfer mode of the driver to try and improve the
state of the code:

- Ensure that dma_complete is set during the end of the command phase
  so that transfers do not stall awaiting the completion

- Update the DMA debugging to provide a bit more useful information
  such as how many DMA descriptors where not processed and print the
  DMA addresses in hexadecimal.

- Fix the DMA channel request code to actually request DMA for the
  S3CMCI block instead of whatever '0' signified.

- Add fallback to PIO if we cannot get the DMA channel, as many of the
  devices with this block only have a limited number of DMA channels.

- Only try and claim and free the DMA channel if we are trying to use it.

This improves the driver DMA code to the point where it can now identify
a card and read the partition table. However the DMA can still stall when
trying to move data between the host and memory.

Signed-off-by: Ben Dooks <ben@simtec.co.uk>

---
 drivers/mmc/host/s3cmci.c |   62 ++++++++++++++++++++++++++++++++++------------
 drivers/mmc/host/s3cmci.h |    3 --
 2 files changed, 47 insertions(+), 18 deletions(-)

Index: b/drivers/mmc/host/s3cmci.c
===================================================================
--- a/drivers/mmc/host/s3cmci.c	2009-08-12 13:55:53.000000000 +0100
+++ b/drivers/mmc/host/s3cmci.c	2009-08-12 13:59:28.000000000 +0100
@@ -183,6 +183,21 @@ static inline bool s3cmci_host_usedma(st
 #endif
 }
 
+/**
+ * s3cmci_host_canpio - return true if host has pio code available
+ *
+ * Return true if the driver has been compiled with the PIO support code
+ * available.
+ */
+static inline bool s3cmci_host_canpio(void)
+{
+#ifdef CONFIG_MMC_S3C_PIO
+	return true;
+#else
+	return false;
+#endif
+}
+
 static inline u32 enable_imask(struct s3cmci_host *host, u32 imask)
 {
 	u32 newmask;
@@ -786,6 +801,7 @@ static void s3cmci_dma_done_callback(str
 	dbg(host, dbg_dma, "DMA FINISHED Size:%i DSTA:%08x DCNT:%08x\n",
 		size, mci_dsta, mci_dcnt);
 
+	host->dma_complete = 1;
 	host->complete_what = COMPLETION_FINALIZE;
 
 out:
@@ -816,7 +832,8 @@ static void finalize_request(struct s3cm
 	if (cmd->data && (cmd->error == 0) &&
 	    (cmd->data->error == 0)) {
 		if (s3cmci_host_usedma(host) && (!host->dma_complete)) {
-			dbg(host, dbg_dma, "DMA Missing!\n");
+			dbg(host, dbg_dma, "DMA Missing (%d)!\n",
+			    host->dma_complete);
 			return;
 		}
 	}
@@ -1065,7 +1082,7 @@ static int s3cmci_prepare_pio(struct s3c
 static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)
 {
 	int dma_len, i;
-	int rw = (data->flags & MMC_DATA_WRITE) ? 1 : 0;
+	int rw = data->flags & MMC_DATA_WRITE;
 
 	BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
 
@@ -1073,7 +1090,7 @@ static int s3cmci_prepare_dma(struct s3c
 	s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH);
 
 	dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
-			     (rw) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+			     rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
 
 	if (dma_len == 0)
 		return -ENOMEM;
@@ -1084,11 +1101,11 @@ static int s3cmci_prepare_dma(struct s3c
 	for (i = 0; i < dma_len; i++) {
 		int res;
 
-		dbg(host, dbg_dma, "enqueue %i:%u@%u\n", i,
-			sg_dma_address(&data->sg[i]),
-			sg_dma_len(&data->sg[i]));
+		dbg(host, dbg_dma, "enqueue %i: %08x@%u\n", i,
+		    sg_dma_address(&data->sg[i]),
+		    sg_dma_len(&data->sg[i]));
 
-		res = s3c2410_dma_enqueue(host->dma, (void *) host,
+		res = s3c2410_dma_enqueue(host->dma, host,
 					  sg_dma_address(&data->sg[i]),
 					  sg_dma_len(&data->sg[i]));
 
@@ -1581,8 +1598,6 @@ static int __devinit s3cmci_probe(struct
 	host->complete_what 	= COMPLETION_NONE;
 	host->pio_active 	= XFER_NONE;
 
-	host->dma		= S3CMCI_DMA;
-
 #ifdef CONFIG_MMC_S3C_PIODMA
 	host->dodma		= host->pdata->dma;
 #endif
@@ -1665,10 +1680,21 @@ static int __devinit s3cmci_probe(struct
 		gpio_direction_input(host->pdata->gpio_wprotect);
 	}
 
-	if (s3c2410_dma_request(S3CMCI_DMA, &s3cmci_dma_client, NULL) < 0) {
-		dev_err(&pdev->dev, "unable to get DMA channel.\n");
-		ret = -EBUSY;
-		goto probe_free_gpio_wp;
+	/* depending on the dma state, get a dma channel to use. */
+
+	if (s3cmci_host_usedma(host)) {
+		host->dma = s3c2410_dma_request(DMACH_SDI, &s3cmci_dma_client,
+						host);
+		if (host->dma < 0) {
+			dev_err(&pdev->dev, "cannot get DMA channel.\n");
+			if (!s3cmci_host_canpio()) {
+				ret = -EBUSY;
+				goto probe_free_gpio_wp;
+			} else {
+				dev_warn(&pdev->dev, "falling back to PIO.\n");
+				host->dodma = 0;
+			}
+		}
 	}
 
 	host->clk = clk_get(&pdev->dev, "sdi");
@@ -1676,7 +1702,7 @@ static int __devinit s3cmci_probe(struct
 		dev_err(&pdev->dev, "failed to find clock source.\n");
 		ret = PTR_ERR(host->clk);
 		host->clk = NULL;
-		goto probe_free_host;
+		goto probe_free_dma;
 	}
 
 	ret = clk_enable(host->clk);
@@ -1738,6 +1764,10 @@ static int __devinit s3cmci_probe(struct
  clk_free:
 	clk_put(host->clk);
 
+ probe_free_dma:
+	if (s3cmci_host_usedma(host))
+		s3c2410_dma_free(host->dma, &s3cmci_dma_client);
+
  probe_free_gpio_wp:
 	if (host->pdata->gpio_wprotect)
 		gpio_free(host->pdata->gpio_wprotect);
@@ -1796,7 +1826,9 @@ static int __devexit s3cmci_remove(struc
 	clk_put(host->clk);
 
 	tasklet_disable(&host->pio_tasklet);
-	s3c2410_dma_free(S3CMCI_DMA, &s3cmci_dma_client);
+
+	if (s3cmci_host_usedma(host))
+		s3c2410_dma_free(host->dma, &s3cmci_dma_client);
 
 	free_irq(host->irq, host);
 
Index: b/drivers/mmc/host/s3cmci.h
===================================================================
--- a/drivers/mmc/host/s3cmci.h	2009-08-12 13:54:49.000000000 +0100
+++ b/drivers/mmc/host/s3cmci.h	2009-08-12 13:59:28.000000000 +0100
@@ -8,9 +8,6 @@
  * published by the Free Software Foundation.
  */
 
-/* FIXME: DMA Resource management ?! */
-#define S3CMCI_DMA 0
-
 enum s3cmci_waitfor {
 	COMPLETION_NONE,
 	COMPLETION_FINALIZE,

-- 

      parent reply	other threads:[~2009-08-18 11:57 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-08-18 11:56 [patch 0/9] s3cmci driver updates for next kernel merge Ben Dooks
2009-08-18 11:56 ` [patch 1/9] s3cmci: Use resource_size() instead of local macro Ben Dooks
2009-08-18 11:56 ` [patch 2/9] s3cmci: update probe to use new platform id list Ben Dooks
2009-08-18 11:56 ` [patch 3/9] s3cmci: Change GPIO to gpiolib from S3C24XX specific calls Ben Dooks
2009-08-18 11:56 ` [patch 4/9] s3cmci: Change to use dev_pm_ops Ben Dooks
2009-08-18 11:56 ` [patch 5/9] s3cmci: Fix direct write to interrupt mask Ben Dooks
2009-08-18 11:56 ` [patch 6/9] s3cmci: Add debugfs support for examining driver and hardware state Ben Dooks
2009-08-18 11:56 ` [patch 7/9] s3cmci: Add SDIO IRQ support Ben Dooks
2009-08-18 11:56 ` [patch 8/9] s3cmci: Kconfig selection for PIO/DMA/Both Ben Dooks
2009-08-18 11:56 ` Ben Dooks [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20090818115700.076744295@fluff.org \
    --to=ben@simtec.co.uk \
    --cc=linux-mmc@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.