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,
--
prev 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.