Message ID | 1401643329-6460-1-git-send-email-anarsoul@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On 1 June 2014 20:22:09 Vasily Khoruzhick wrote: > Utilise new s3c24xx-dma dmaengine driver for DMA ops. > > Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com> > --- > v2: - Don't store async dma descriptor, it's not used > - Request DMA channel via dma_request_slave_channel_compat() and use > hardcoded DMA channel. > - Add dependency on S3C24XX_DMAC (s3cmci uses filter function from it) > v3: - Use 'depends' instead of 'select' in Kconfig > - Drop useless controller registers reads from dma completion callback Ping? > drivers/mmc/host/Kconfig | 10 +-- > drivers/mmc/host/s3cmci.c | 180 > +++++++++++++--------------------------------- drivers/mmc/host/s3cmci.h | > 4 +- > 3 files changed, 52 insertions(+), 142 deletions(-) > > diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig > index 1384f67..0cd10e3 100644 > --- a/drivers/mmc/host/Kconfig > +++ b/drivers/mmc/host/Kconfig > @@ -420,6 +420,7 @@ config MMC_SPI > config MMC_S3C > tristate "Samsung S3C SD/MMC Card Interface support" > depends on ARCH_S3C24XX > + depends on S3C24XX_DMAC > help > This selects a driver for the MCI interface found in > Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs. > @@ -457,15 +458,6 @@ config MMC_S3C_DMA > working properly and needs to be debugged before this > option is useful. > > -config MMC_S3C_PIODMA > - bool "Support for both PIO and DMA" > - help > - Compile both the PIO and DMA transfer routines into the > - driver and let the platform select at run-time which one > - is best. > - > - See notes for the DMA option. > - > endchoice > > config MMC_SDRICOH_CS > diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c > index f237826..0d115a8 100644 > --- a/drivers/mmc/host/s3cmci.c > +++ b/drivers/mmc/host/s3cmci.c > @@ -12,6 +12,7 @@ > */ > > #include <linux/module.h> > +#include <linux/dmaengine.h> > #include <linux/dma-mapping.h> > #include <linux/clk.h> > #include <linux/mmc/host.h> > @@ -27,6 +28,7 @@ > #include <mach/dma.h> > #include <mach/gpio-samsung.h> > > +#include <linux/platform_data/dma-s3c24xx.h> > #include <linux/platform_data/mmc-s3cmci.h> > > #include "s3cmci.h" > @@ -140,10 +142,6 @@ static const int dbgmap_debug = dbg_err | dbg_debug; > dev_dbg(&host->pdev->dev, args); \ > } while (0) > > -static struct s3c2410_dma_client s3cmci_dma_client = { > - .name = "s3c-mci", > -}; > - > static void finalize_request(struct s3cmci_host *host); > static void s3cmci_send_request(struct mmc_host *mmc); > static void s3cmci_reset(struct s3cmci_host *host); > @@ -256,25 +254,8 @@ static inline bool s3cmci_host_usedma(struct > s3cmci_host *host) { > #ifdef CONFIG_MMC_S3C_PIO > return false; > -#elif defined(CONFIG_MMC_S3C_DMA) > +#else /* CONFIG_MMC_S3C_DMA */ > return true; > -#else > - return host->dodma; > -#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 > } > > @@ -841,60 +822,24 @@ static irqreturn_t s3cmci_irq_cd(int irq, void > *dev_id) return IRQ_HANDLED; > } > > -static void s3cmci_dma_done_callback(struct s3c2410_dma_chan *dma_ch, > - void *buf_id, int size, > - enum s3c2410_dma_buffresult result) > +static void s3cmci_dma_done_callback(void *arg) > { > - struct s3cmci_host *host = buf_id; > + struct s3cmci_host *host = arg; > unsigned long iflags; > - u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt; > - > - mci_csta = readl(host->base + S3C2410_SDICMDSTAT); > - mci_dsta = readl(host->base + S3C2410_SDIDSTA); > - mci_fsta = readl(host->base + S3C2410_SDIFSTA); > - mci_dcnt = readl(host->base + S3C2410_SDIDCNT); > > BUG_ON(!host->mrq); > BUG_ON(!host->mrq->data); > - BUG_ON(!host->dmatogo); > > spin_lock_irqsave(&host->complete_lock, iflags); > > - if (result != S3C2410_RES_OK) { > - dbg(host, dbg_fail, "DMA FAILED: csta=0x%08x dsta=0x%08x " > - "fsta=0x%08x dcnt:0x%08x result:0x%08x toGo:%u\n", > - mci_csta, mci_dsta, mci_fsta, > - mci_dcnt, result, host->dmatogo); > - > - goto fail_request; > - } > - > - host->dmatogo--; > - if (host->dmatogo) { > - dbg(host, dbg_dma, "DMA DONE Size:%i DSTA:[%08x] " > - "DCNT:[%08x] toGo:%u\n", > - size, mci_dsta, mci_dcnt, host->dmatogo); > - > - goto out; > - } > - > - dbg(host, dbg_dma, "DMA FINISHED Size:%i DSTA:%08x DCNT:%08x\n", > - size, mci_dsta, mci_dcnt); > + dbg(host, dbg_dma, "DMA FINISHED\n"); > > host->dma_complete = 1; > host->complete_what = COMPLETION_FINALIZE; > > -out: > tasklet_schedule(&host->pio_tasklet); > spin_unlock_irqrestore(&host->complete_lock, iflags); > - return; > > -fail_request: > - host->mrq->data->error = -EINVAL; > - host->complete_what = COMPLETION_FINALIZE; > - clear_imask(host); > - > - goto out; > } > > static void finalize_request(struct s3cmci_host *host) > @@ -966,7 +911,7 @@ static void finalize_request(struct s3cmci_host *host) > * DMA channel and the fifo to clear out any garbage. */ > if (mrq->data->error != 0) { > if (s3cmci_host_usedma(host)) > - s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH); > + dmaengine_terminate_all(host->dma); > > if (host->is2440) { > /* Clear failure register and reset fifo. */ > @@ -992,29 +937,6 @@ request_done: > mmc_request_done(host->mmc, mrq); > } > > -static void s3cmci_dma_setup(struct s3cmci_host *host, > - enum dma_data_direction source) > -{ > - static enum dma_data_direction last_source = -1; > - static int setup_ok; > - > - if (last_source == source) > - return; > - > - last_source = source; > - > - s3c2410_dma_devconfig(host->dma, source, > - host->mem->start + host->sdidata); > - > - if (!setup_ok) { > - s3c2410_dma_config(host->dma, 4); > - s3c2410_dma_set_buffdone_fn(host->dma, > - s3cmci_dma_done_callback); > - s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART); > - setup_ok = 1; > - } > -} > - > static void s3cmci_send_command(struct s3cmci_host *host, > struct mmc_command *cmd) > { > @@ -1162,43 +1084,45 @@ static int s3cmci_prepare_pio(struct s3cmci_host > *host, struct mmc_data *data) > > static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data > *data) { > - int dma_len, i; > int rw = data->flags & MMC_DATA_WRITE; > + struct dma_async_tx_descriptor *desc; > + struct dma_slave_config conf = { > + .src_addr = host->mem->start + host->sdidata, > + .dst_addr = host->mem->start + host->sdidata, > + .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, > + .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, > + }; > > BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR); > > - s3cmci_dma_setup(host, rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE); > - 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); > - > - if (dma_len == 0) > - return -ENOMEM; > - > - host->dma_complete = 0; > - host->dmatogo = dma_len; > - > - for (i = 0; i < dma_len; i++) { > - int res; > - > - dbg(host, dbg_dma, "enqueue %i: %08x@%u\n", i, > - sg_dma_address(&data->sg[i]), > - sg_dma_len(&data->sg[i])); > + /* Restore prescaler value */ > + writel(host->prescaler, host->base + S3C2410_SDIPRE); > > - res = s3c2410_dma_enqueue(host->dma, host, > - sg_dma_address(&data->sg[i]), > - sg_dma_len(&data->sg[i])); > + if (!rw) > + conf.direction = DMA_DEV_TO_MEM; > + else > + conf.direction = DMA_MEM_TO_DEV; > > - if (res) { > - s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH); > - return -EBUSY; > - } > - } > + dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, > + rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE); > > - s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_START); > + dmaengine_slave_config(host->dma, &conf); > + desc = dmaengine_prep_slave_sg(host->dma, data->sg, data->sg_len, > + conf.direction, > + DMA_CTRL_ACK | DMA_PREP_INTERRUPT); > + if (!desc) > + goto unmap_exit; > + desc->callback = s3cmci_dma_done_callback; > + desc->callback_param = host; > + dmaengine_submit(desc); > + dma_async_issue_pending(host->dma); > > return 0; > + > +unmap_exit: > + dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, > + rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE); > + return -ENOMEM; > } > > static void s3cmci_send_request(struct mmc_host *mmc) > @@ -1676,10 +1600,6 @@ static int s3cmci_probe(struct platform_device *pdev) > host->complete_what = COMPLETION_NONE; > host->pio_active = XFER_NONE; > > -#ifdef CONFIG_MMC_S3C_PIODMA > - host->dodma = host->pdata->use_dma; > -#endif > - > host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); > if (!host->mem) { > dev_err(&pdev->dev, > @@ -1765,17 +1685,17 @@ static int s3cmci_probe(struct platform_device > *pdev) /* 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) { > + dma_cap_mask_t mask; > + > + dma_cap_zero(mask); > + dma_cap_set(DMA_SLAVE, mask); > + > + host->dma = dma_request_slave_channel_compat(mask, > + s3c24xx_dma_filter, (void *)DMACH_SDI, &pdev->dev, "rx-tx"); > + if (!host->dma) { > 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; > - } > + ret = -EBUSY; > + goto probe_free_gpio_wp; > } > } > > @@ -1816,7 +1736,7 @@ static int s3cmci_probe(struct platform_device *pdev) > mmc->max_segs = 128; > > dbg(host, dbg_debug, > - "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n", > + "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%p.\n", > (host->is2440?"2440":""), > host->base, host->irq, host->irq_cd, host->dma); > > @@ -1852,7 +1772,7 @@ static int s3cmci_probe(struct platform_device *pdev) > > probe_free_dma: > if (s3cmci_host_usedma(host)) > - s3c2410_dma_free(host->dma, &s3cmci_dma_client); > + dma_release_channel(host->dma); > > probe_free_gpio_wp: > if (!host->pdata->no_wprotect) > @@ -1914,7 +1834,7 @@ static int s3cmci_remove(struct platform_device *pdev) > tasklet_disable(&host->pio_tasklet); > > if (s3cmci_host_usedma(host)) > - s3c2410_dma_free(host->dma, &s3cmci_dma_client); > + dma_release_channel(host->dma); > > free_irq(host->irq, host); > > diff --git a/drivers/mmc/host/s3cmci.h b/drivers/mmc/host/s3cmci.h > index c76b53d..cc2e46c 100644 > --- a/drivers/mmc/host/s3cmci.h > +++ b/drivers/mmc/host/s3cmci.h > @@ -26,7 +26,7 @@ struct s3cmci_host { > void __iomem *base; > int irq; > int irq_cd; > - int dma; > + struct dma_chan *dma; > > unsigned long clk_rate; > unsigned long clk_div; > @@ -36,8 +36,6 @@ struct s3cmci_host { > int is2440; > unsigned sdiimsk; > unsigned sdidata; > - int dodma; > - int dmatogo; > > bool irq_disabled; > bool irq_enabled;
On Mon, Jun 23, 2014 at 2:31 PM, Vasily Khoruzhick <anarsoul@gmail.com> wrote: > > On 1 June 2014 20:22:09 Vasily Khoruzhick wrote: > > Utilise new s3c24xx-dma dmaengine driver for DMA ops. > > > > Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com> > > --- > > v2: - Don't store async dma descriptor, it's not used > > - Request DMA channel via dma_request_slave_channel_compat() and use > > hardcoded DMA channel. > > - Add dependency on S3C24XX_DMAC (s3cmci uses filter function from it) > > v3: - Use 'depends' instead of 'select' in Kconfig > > - Drop useless controller registers reads from dma completion callback > > Ping? Ping? > > drivers/mmc/host/Kconfig | 10 +-- > > drivers/mmc/host/s3cmci.c | 180 > > +++++++++++++--------------------------------- drivers/mmc/host/s3cmci.h | > > 4 +- > > 3 files changed, 52 insertions(+), 142 deletions(-)
On Mon, Jun 30, 2014 at 10:03 PM, Vasily Khoruzhick <anarsoul@gmail.com> wrote: > On Mon, Jun 23, 2014 at 2:31 PM, Vasily Khoruzhick <anarsoul@gmail.com> wrote: >> >> On 1 June 2014 20:22:09 Vasily Khoruzhick wrote: >> > Utilise new s3c24xx-dma dmaengine driver for DMA ops. >> > >> > Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com> >> > --- >> > v2: - Don't store async dma descriptor, it's not used >> > - Request DMA channel via dma_request_slave_channel_compat() and use >> > hardcoded DMA channel. >> > - Add dependency on S3C24XX_DMAC (s3cmci uses filter function from it) >> > v3: - Use 'depends' instead of 'select' in Kconfig >> > - Drop useless controller registers reads from dma completion callback >> >> Ping? > > Ping? Could anyone tell me through which tree this patch should be merged? I'm pretty sure that I've included everyone from get_maintainer.pl output except LKML, but no response from maintainer so far. Regards Vasily >> > drivers/mmc/host/Kconfig | 10 +-- >> > drivers/mmc/host/s3cmci.c | 180 >> > +++++++++++++--------------------------------- drivers/mmc/host/s3cmci.h | >> > 4 +- >> > 3 files changed, 52 insertions(+), 142 deletions(-)
On Monday 07 July 2014, Vasily Khoruzhick wrote: > On Mon, Jun 30, 2014 at 10:03 PM, Vasily Khoruzhick <anarsoul@gmail.com> wrote: > > On Mon, Jun 23, 2014 at 2:31 PM, Vasily Khoruzhick <anarsoul@gmail.com> wrote: > >> > >> On 1 June 2014 20:22:09 Vasily Khoruzhick wrote: > >> > Utilise new s3c24xx-dma dmaengine driver for DMA ops. > >> > > >> > Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com> > >> > --- > >> > v2: - Don't store async dma descriptor, it's not used > >> > - Request DMA channel via dma_request_slave_channel_compat() and use > >> > hardcoded DMA channel. > >> > - Add dependency on S3C24XX_DMAC (s3cmci uses filter function from it) > >> > v3: - Use 'depends' instead of 'select' in Kconfig > >> > - Drop useless controller registers reads from dma completion callback > >> > >> Ping? > > > > Ping? > > Could anyone tell me through which tree this patch should be merged? > I'm pretty sure that I've included everyone from get_maintainer.pl > output > except LKML, but no response from maintainer so far. I think you did everything right, Ulf or Chris should really pick up this patch. The one thing you could improve is the changeset text which you wrote as "Utilise new s3c24xx-dma dmaengine driver for DMA ops." What we really need here is an explanation of why we want this, e.g. what problems are solved by it etc. I definitely really want this patch as part of 3.17 so we can enabled multiplatform for the platforms that use this driver. You should also list the Acked-by: Arnd Bergmann <arnd@arndb.de> line under your "Signed-off-by" line. Arnd
On 7 July 2014 23:12, Arnd Bergmann <arnd@arndb.de> wrote: > On Monday 07 July 2014, Vasily Khoruzhick wrote: >> On Mon, Jun 30, 2014 at 10:03 PM, Vasily Khoruzhick <anarsoul@gmail.com> wrote: >> > On Mon, Jun 23, 2014 at 2:31 PM, Vasily Khoruzhick <anarsoul@gmail.com> wrote: >> >> >> >> On 1 June 2014 20:22:09 Vasily Khoruzhick wrote: >> >> > Utilise new s3c24xx-dma dmaengine driver for DMA ops. >> >> > >> >> > Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com> >> >> > --- >> >> > v2: - Don't store async dma descriptor, it's not used >> >> > - Request DMA channel via dma_request_slave_channel_compat() and use >> >> > hardcoded DMA channel. >> >> > - Add dependency on S3C24XX_DMAC (s3cmci uses filter function from it) >> >> > v3: - Use 'depends' instead of 'select' in Kconfig >> >> > - Drop useless controller registers reads from dma completion callback >> >> >> >> Ping? >> > >> > Ping? >> >> Could anyone tell me through which tree this patch should be merged? >> I'm pretty sure that I've included everyone from get_maintainer.pl >> output >> except LKML, but no response from maintainer so far. > > I think you did everything right, Ulf or Chris should really pick up this > patch. The one thing you could improve is the changeset text which you > wrote as "Utilise new s3c24xx-dma dmaengine driver for DMA ops." What we > really need here is an explanation of why we want this, e.g. what problems > are solved by it etc. I definitely really want this patch as part of 3.17 > so we can enabled multiplatform for the platforms that use this driver. > > You should also list the > > Acked-by: Arnd Bergmann <arnd@arndb.de> > > line under your "Signed-off-by" line. > > Arnd Sorry for the delay. Thanks! Applied for next with Arnd's ack. Kind regards Uffe
On 8 July 2014 14:51:01 Ulf Hansson wrote: > Sorry for the delay. > > Thanks! Applied for next with Arnd's ack. > > Kind regards > Uffe Thank you! And since now old s3c24xx DMA (non-dmaengine) has no users we can remove it completely. I'll send a patch soon. Regards Vasily
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 1384f67..0cd10e3 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -420,6 +420,7 @@ config MMC_SPI config MMC_S3C tristate "Samsung S3C SD/MMC Card Interface support" depends on ARCH_S3C24XX + depends on S3C24XX_DMAC help This selects a driver for the MCI interface found in Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs. @@ -457,15 +458,6 @@ config MMC_S3C_DMA working properly and needs to be debugged before this option is useful. -config MMC_S3C_PIODMA - bool "Support for both PIO and DMA" - help - Compile both the PIO and DMA transfer routines into the - driver and let the platform select at run-time which one - is best. - - See notes for the DMA option. - endchoice config MMC_SDRICOH_CS diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index f237826..0d115a8 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -12,6 +12,7 @@ */ #include <linux/module.h> +#include <linux/dmaengine.h> #include <linux/dma-mapping.h> #include <linux/clk.h> #include <linux/mmc/host.h> @@ -27,6 +28,7 @@ #include <mach/dma.h> #include <mach/gpio-samsung.h> +#include <linux/platform_data/dma-s3c24xx.h> #include <linux/platform_data/mmc-s3cmci.h> #include "s3cmci.h" @@ -140,10 +142,6 @@ static const int dbgmap_debug = dbg_err | dbg_debug; dev_dbg(&host->pdev->dev, args); \ } while (0) -static struct s3c2410_dma_client s3cmci_dma_client = { - .name = "s3c-mci", -}; - static void finalize_request(struct s3cmci_host *host); static void s3cmci_send_request(struct mmc_host *mmc); static void s3cmci_reset(struct s3cmci_host *host); @@ -256,25 +254,8 @@ static inline bool s3cmci_host_usedma(struct s3cmci_host *host) { #ifdef CONFIG_MMC_S3C_PIO return false; -#elif defined(CONFIG_MMC_S3C_DMA) +#else /* CONFIG_MMC_S3C_DMA */ return true; -#else - return host->dodma; -#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 } @@ -841,60 +822,24 @@ static irqreturn_t s3cmci_irq_cd(int irq, void *dev_id) return IRQ_HANDLED; } -static void s3cmci_dma_done_callback(struct s3c2410_dma_chan *dma_ch, - void *buf_id, int size, - enum s3c2410_dma_buffresult result) +static void s3cmci_dma_done_callback(void *arg) { - struct s3cmci_host *host = buf_id; + struct s3cmci_host *host = arg; unsigned long iflags; - u32 mci_csta, mci_dsta, mci_fsta, mci_dcnt; - - mci_csta = readl(host->base + S3C2410_SDICMDSTAT); - mci_dsta = readl(host->base + S3C2410_SDIDSTA); - mci_fsta = readl(host->base + S3C2410_SDIFSTA); - mci_dcnt = readl(host->base + S3C2410_SDIDCNT); BUG_ON(!host->mrq); BUG_ON(!host->mrq->data); - BUG_ON(!host->dmatogo); spin_lock_irqsave(&host->complete_lock, iflags); - if (result != S3C2410_RES_OK) { - dbg(host, dbg_fail, "DMA FAILED: csta=0x%08x dsta=0x%08x " - "fsta=0x%08x dcnt:0x%08x result:0x%08x toGo:%u\n", - mci_csta, mci_dsta, mci_fsta, - mci_dcnt, result, host->dmatogo); - - goto fail_request; - } - - host->dmatogo--; - if (host->dmatogo) { - dbg(host, dbg_dma, "DMA DONE Size:%i DSTA:[%08x] " - "DCNT:[%08x] toGo:%u\n", - size, mci_dsta, mci_dcnt, host->dmatogo); - - goto out; - } - - dbg(host, dbg_dma, "DMA FINISHED Size:%i DSTA:%08x DCNT:%08x\n", - size, mci_dsta, mci_dcnt); + dbg(host, dbg_dma, "DMA FINISHED\n"); host->dma_complete = 1; host->complete_what = COMPLETION_FINALIZE; -out: tasklet_schedule(&host->pio_tasklet); spin_unlock_irqrestore(&host->complete_lock, iflags); - return; -fail_request: - host->mrq->data->error = -EINVAL; - host->complete_what = COMPLETION_FINALIZE; - clear_imask(host); - - goto out; } static void finalize_request(struct s3cmci_host *host) @@ -966,7 +911,7 @@ static void finalize_request(struct s3cmci_host *host) * DMA channel and the fifo to clear out any garbage. */ if (mrq->data->error != 0) { if (s3cmci_host_usedma(host)) - s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH); + dmaengine_terminate_all(host->dma); if (host->is2440) { /* Clear failure register and reset fifo. */ @@ -992,29 +937,6 @@ request_done: mmc_request_done(host->mmc, mrq); } -static void s3cmci_dma_setup(struct s3cmci_host *host, - enum dma_data_direction source) -{ - static enum dma_data_direction last_source = -1; - static int setup_ok; - - if (last_source == source) - return; - - last_source = source; - - s3c2410_dma_devconfig(host->dma, source, - host->mem->start + host->sdidata); - - if (!setup_ok) { - s3c2410_dma_config(host->dma, 4); - s3c2410_dma_set_buffdone_fn(host->dma, - s3cmci_dma_done_callback); - s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART); - setup_ok = 1; - } -} - static void s3cmci_send_command(struct s3cmci_host *host, struct mmc_command *cmd) { @@ -1162,43 +1084,45 @@ static int s3cmci_prepare_pio(struct s3cmci_host *host, struct mmc_data *data) static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data) { - int dma_len, i; int rw = data->flags & MMC_DATA_WRITE; + struct dma_async_tx_descriptor *desc; + struct dma_slave_config conf = { + .src_addr = host->mem->start + host->sdidata, + .dst_addr = host->mem->start + host->sdidata, + .src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, + .dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES, + }; BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR); - s3cmci_dma_setup(host, rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - 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); - - if (dma_len == 0) - return -ENOMEM; - - host->dma_complete = 0; - host->dmatogo = dma_len; - - for (i = 0; i < dma_len; i++) { - int res; - - dbg(host, dbg_dma, "enqueue %i: %08x@%u\n", i, - sg_dma_address(&data->sg[i]), - sg_dma_len(&data->sg[i])); + /* Restore prescaler value */ + writel(host->prescaler, host->base + S3C2410_SDIPRE); - res = s3c2410_dma_enqueue(host->dma, host, - sg_dma_address(&data->sg[i]), - sg_dma_len(&data->sg[i])); + if (!rw) + conf.direction = DMA_DEV_TO_MEM; + else + conf.direction = DMA_MEM_TO_DEV; - if (res) { - s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_FLUSH); - return -EBUSY; - } - } + dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, + rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE); - s3c2410_dma_ctrl(host->dma, S3C2410_DMAOP_START); + dmaengine_slave_config(host->dma, &conf); + desc = dmaengine_prep_slave_sg(host->dma, data->sg, data->sg_len, + conf.direction, + DMA_CTRL_ACK | DMA_PREP_INTERRUPT); + if (!desc) + goto unmap_exit; + desc->callback = s3cmci_dma_done_callback; + desc->callback_param = host; + dmaengine_submit(desc); + dma_async_issue_pending(host->dma); return 0; + +unmap_exit: + dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, + rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE); + return -ENOMEM; } static void s3cmci_send_request(struct mmc_host *mmc) @@ -1676,10 +1600,6 @@ static int s3cmci_probe(struct platform_device *pdev) host->complete_what = COMPLETION_NONE; host->pio_active = XFER_NONE; -#ifdef CONFIG_MMC_S3C_PIODMA - host->dodma = host->pdata->use_dma; -#endif - host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!host->mem) { dev_err(&pdev->dev, @@ -1765,17 +1685,17 @@ static int s3cmci_probe(struct platform_device *pdev) /* 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) { + dma_cap_mask_t mask; + + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + + host->dma = dma_request_slave_channel_compat(mask, + s3c24xx_dma_filter, (void *)DMACH_SDI, &pdev->dev, "rx-tx"); + if (!host->dma) { 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; - } + ret = -EBUSY; + goto probe_free_gpio_wp; } } @@ -1816,7 +1736,7 @@ static int s3cmci_probe(struct platform_device *pdev) mmc->max_segs = 128; dbg(host, dbg_debug, - "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%u.\n", + "probe: mode:%s mapped mci_base:%p irq:%u irq_cd:%u dma:%p.\n", (host->is2440?"2440":""), host->base, host->irq, host->irq_cd, host->dma); @@ -1852,7 +1772,7 @@ static int s3cmci_probe(struct platform_device *pdev) probe_free_dma: if (s3cmci_host_usedma(host)) - s3c2410_dma_free(host->dma, &s3cmci_dma_client); + dma_release_channel(host->dma); probe_free_gpio_wp: if (!host->pdata->no_wprotect) @@ -1914,7 +1834,7 @@ static int s3cmci_remove(struct platform_device *pdev) tasklet_disable(&host->pio_tasklet); if (s3cmci_host_usedma(host)) - s3c2410_dma_free(host->dma, &s3cmci_dma_client); + dma_release_channel(host->dma); free_irq(host->irq, host); diff --git a/drivers/mmc/host/s3cmci.h b/drivers/mmc/host/s3cmci.h index c76b53d..cc2e46c 100644 --- a/drivers/mmc/host/s3cmci.h +++ b/drivers/mmc/host/s3cmci.h @@ -26,7 +26,7 @@ struct s3cmci_host { void __iomem *base; int irq; int irq_cd; - int dma; + struct dma_chan *dma; unsigned long clk_rate; unsigned long clk_div; @@ -36,8 +36,6 @@ struct s3cmci_host { int is2440; unsigned sdiimsk; unsigned sdidata; - int dodma; - int dmatogo; bool irq_disabled; bool irq_enabled;
Utilise new s3c24xx-dma dmaengine driver for DMA ops. Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com> --- v2: - Don't store async dma descriptor, it's not used - Request DMA channel via dma_request_slave_channel_compat() and use hardcoded DMA channel. - Add dependency on S3C24XX_DMAC (s3cmci uses filter function from it) v3: - Use 'depends' instead of 'select' in Kconfig - Drop useless controller registers reads from dma completion callback drivers/mmc/host/Kconfig | 10 +-- drivers/mmc/host/s3cmci.c | 180 +++++++++++++--------------------------------- drivers/mmc/host/s3cmci.h | 4 +- 3 files changed, 52 insertions(+), 142 deletions(-)