[PATCH v3] s3cmci: port DMA code to dmaengine API

Vasily Khoruzhick anarsoul at gmail.com
Mon Jun 23 04:31:45 PDT 2014


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 at 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;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 181 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140623/7d4abff5/attachment-0001.sig>


More information about the linux-arm-kernel mailing list