All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] dma: sh: stop using .private
@ 2012-07-04 16:17 ` Guennadi Liakhovetski
  0 siblings, 0 replies; 16+ messages in thread
From: Guennadi Liakhovetski @ 2012-07-04 16:17 UTC (permalink / raw)
  To: Vinod Koul; +Cc: Magnus Damm, linux-sh, linux-mmc, Chris Ball, linux-kernel

Hi Vinod

Here's an attempt to convert the shdma driver to a new method, whereby a 
centrally provided filter function is used and the DMA_SLAVE_CONFIG command 
is enabled for slave operation. The last patch is an illustration of how 
this new method shall be used. If this approach is acceptable, I'll also 
convert the remaining shdma user drivers. This patch series goes on top of 
my earlier patches to split shdma.c. It might be easier at some point for 
you to have me provide you a git tree to pull from.

Chris, this time the mmc patch is not yet to be applied. We first have to 
sort out the dmaengine API.

Guennadi Liakhovetski (4):
  dmaengine: shdma: prepare to stop using struct dma_chan::private
  dma: sh: use an integer slave ID to improve API compatibility
  dma: sh: provide a migration path for slave drivers to stop using
    .private
  mmc: sh_mmcif: switch to the new DMA channel allocation and
    configuration

 drivers/dma/sh/shdma-base.c |  130 ++++++++++++++++++++++++++++++++-----------
 drivers/dma/sh/shdma.c      |   35 +++++------
 drivers/dma/sh/shdma.h      |    2 +
 drivers/mmc/host/sh_mmcif.c |   90 +++++++++++++++++-------------
 include/linux/sh_dma.h      |   12 ++--
 include/linux/shdma-base.h  |    7 +-
 6 files changed, 177 insertions(+), 99 deletions(-)

-- 
1.7.2.5

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 0/4] dma: sh: stop using .private
@ 2012-07-04 16:17 ` Guennadi Liakhovetski
  0 siblings, 0 replies; 16+ messages in thread
From: Guennadi Liakhovetski @ 2012-07-04 16:17 UTC (permalink / raw)
  To: Vinod Koul; +Cc: Magnus Damm, linux-sh, linux-mmc, Chris Ball, linux-kernel

Hi Vinod

Here's an attempt to convert the shdma driver to a new method, whereby a 
centrally provided filter function is used and the DMA_SLAVE_CONFIG command 
is enabled for slave operation. The last patch is an illustration of how 
this new method shall be used. If this approach is acceptable, I'll also 
convert the remaining shdma user drivers. This patch series goes on top of 
my earlier patches to split shdma.c. It might be easier at some point for 
you to have me provide you a git tree to pull from.

Chris, this time the mmc patch is not yet to be applied. We first have to 
sort out the dmaengine API.

Guennadi Liakhovetski (4):
  dmaengine: shdma: prepare to stop using struct dma_chan::private
  dma: sh: use an integer slave ID to improve API compatibility
  dma: sh: provide a migration path for slave drivers to stop using
    .private
  mmc: sh_mmcif: switch to the new DMA channel allocation and
    configuration

 drivers/dma/sh/shdma-base.c |  130 ++++++++++++++++++++++++++++++++-----------
 drivers/dma/sh/shdma.c      |   35 +++++------
 drivers/dma/sh/shdma.h      |    2 +
 drivers/mmc/host/sh_mmcif.c |   90 +++++++++++++++++-------------
 include/linux/sh_dma.h      |   12 ++--
 include/linux/shdma-base.h  |    7 +-
 6 files changed, 177 insertions(+), 99 deletions(-)

-- 
1.7.2.5

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH 1/4] dmaengine: shdma: prepare to stop using struct dma_chan::private
  2012-07-04 16:17 ` Guennadi Liakhovetski
@ 2012-07-04 16:17   ` Guennadi Liakhovetski
  -1 siblings, 0 replies; 16+ messages in thread
From: Guennadi Liakhovetski @ 2012-07-04 16:17 UTC (permalink / raw)
  To: Vinod Koul; +Cc: Magnus Damm, linux-sh, linux-mmc, Chris Ball, linux-kernel

Using struct dma_chan::private is deprecated. To update the shdma driver to
stop using it we first have to eliminate internal runtime uses of it. After
that we will also be able to stop using it for channel configuration.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/dma/sh/shdma-base.c |    9 +++++----
 drivers/dma/sh/shdma.c      |   24 ++++++++++--------------
 drivers/dma/sh/shdma.h      |    2 ++
 include/linux/sh_dma.h      |    2 --
 include/linux/shdma-base.h  |    1 +
 5 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
index ff060d0..f75ebfa 100644
--- a/drivers/dma/sh/shdma-base.c
+++ b/drivers/dma/sh/shdma-base.c
@@ -76,7 +76,7 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
 		container_of(tx, struct shdma_desc, async_tx),
 		*last = desc;
 	struct shdma_chan *schan = to_shdma_chan(tx->chan);
-	struct shdma_slave *slave = tx->chan->private;
+	struct shdma_slave *slave = schan->slave;
 	dma_async_tx_callback callback = tx->callback;
 	dma_cookie_t cookie;
 	bool power_up;
@@ -208,6 +208,7 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
 		goto edescalloc;
 	}
 	schan->desc_num = NR_DESCS_PER_CHANNEL;
+	schan->slave = slave;
 
 	for (i = 0; i < NR_DESCS_PER_CHANNEL; i++) {
 		desc = ops->embedded_desc(schan->desc, i);
@@ -365,9 +366,9 @@ static void shdma_free_chan_resources(struct dma_chan *chan)
 	if (!list_empty(&schan->ld_queue))
 		shdma_chan_ld_cleanup(schan, true);
 
-	if (chan->private) {
+	if (schan->slave) {
 		/* The caller is holding dma_list_mutex */
-		struct shdma_slave *slave = chan->private;
+		struct shdma_slave *slave = schan->slave;
 		clear_bit(slave->slave_id, shdma_slave_used);
 		chan->private = NULL;
 	}
@@ -558,7 +559,7 @@ static struct dma_async_tx_descriptor *shdma_prep_slave_sg(
 	struct shdma_chan *schan = to_shdma_chan(chan);
 	struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
 	const struct shdma_ops *ops = sdev->ops;
-	struct shdma_slave *slave = chan->private;
+	struct shdma_slave *slave = schan->slave;
 	dma_addr_t slave_addr;
 
 	if (!chan)
diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
index f06906f..9f0a2e5 100644
--- a/drivers/dma/sh/shdma.c
+++ b/drivers/dma/sh/shdma.c
@@ -291,10 +291,8 @@ static void sh_dmae_setup_xfer(struct shdma_chan *schan,
 						    shdma_chan);
 
 	if (sslave) {
-		struct sh_dmae_slave *slave = container_of(sslave,
-					struct sh_dmae_slave, shdma_slave);
 		const struct sh_dmae_slave_config *cfg -			slave->config;
+			sh_chan->config;
 
 		dmae_set_dmars(sh_chan, cfg->mid_rid);
 		dmae_set_chcr(sh_chan, cfg->chcr);
@@ -326,13 +324,11 @@ static int sh_dmae_set_slave(struct shdma_chan *schan,
 {
 	struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
 						    shdma_chan);
-	struct sh_dmae_slave *slave = container_of(sslave, struct sh_dmae_slave,
-						   shdma_slave);
 	const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, sslave->slave_id);
 	if (!cfg)
 		return -ENODEV;
 
-	slave->config = cfg;
+	sh_chan->config = cfg;
 
 	return 0;
 }
@@ -579,13 +575,12 @@ static int sh_dmae_resume(struct device *dev)
 
 	for (i = 0; i < shdev->pdata->channel_num; i++) {
 		struct sh_dmae_chan *sh_chan = shdev->chan[i];
-		struct sh_dmae_slave *param = sh_chan->shdma_chan.dma_chan.private;
 
 		if (!sh_chan->shdma_chan.desc_num)
 			continue;
 
-		if (param) {
-			const struct sh_dmae_slave_config *cfg = param->config;
+		if (sh_chan->shdma_chan.slave) {
+			const struct sh_dmae_slave_config *cfg = sh_chan->config;
 			dmae_set_dmars(sh_chan, cfg->mid_rid);
 			dmae_set_chcr(sh_chan, cfg->chcr);
 		} else {
@@ -609,14 +604,15 @@ const struct dev_pm_ops sh_dmae_pm = {
 
 static dma_addr_t sh_dmae_slave_addr(struct shdma_chan *schan)
 {
-	struct sh_dmae_slave *param = schan->dma_chan.private;
+	struct sh_dmae_chan *sh_chan = container_of(schan,
+					struct sh_dmae_chan, shdma_chan);
 
 	/*
-	 * Implicit BUG_ON(!param)
-	 * if (param != NULL), this is a successfully requested slave channel,
-	 * therefore param->config != NULL too.
+	 * Implicit BUG_ON(!sh_chan->config)
+	 * This is an exclusive slave DMA operation, may only be called after a
+	 * successful slave configuration.
 	 */
-	return param->config->addr;
+	return sh_chan->config->addr;
 }
 
 static struct shdma_desc *sh_dmae_embedded_desc(void *buf, int i)
diff --git a/drivers/dma/sh/shdma.h b/drivers/dma/sh/shdma.h
index 840e47d..9314e93 100644
--- a/drivers/dma/sh/shdma.h
+++ b/drivers/dma/sh/shdma.h
@@ -13,6 +13,7 @@
 #ifndef __DMA_SHDMA_H
 #define __DMA_SHDMA_H
 
+#include <linux/sh_dma.h>
 #include <linux/shdma-base.h>
 #include <linux/dmaengine.h>
 #include <linux/interrupt.h>
@@ -25,6 +26,7 @@ struct device;
 
 struct sh_dmae_chan {
 	struct shdma_chan shdma_chan;
+	const struct sh_dmae_slave_config *config; /* Slave DMA configuration */
 	int xmit_shift;			/* log_2(bytes_per_xfer) */
 	u32 __iomem *base;
 	char dev_id[16];		/* unique name per DMAC of channel */
diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
index 7c8ca41..a79f10a 100644
--- a/include/linux/sh_dma.h
+++ b/include/linux/sh_dma.h
@@ -20,8 +20,6 @@ struct device;
 /* Used by slave DMA clients to request DMA to/from a specific peripheral */
 struct sh_dmae_slave {
 	struct shdma_slave		shdma_slave;	/* Set by the platform */
-	struct device			*dma_dev;	/* Set by the platform */
-	const struct sh_dmae_slave_config *config;	/* Set by the driver */
 };
 
 /*
diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h
index 83efd13..c3a19e9 100644
--- a/include/linux/shdma-base.h
+++ b/include/linux/shdma-base.h
@@ -66,6 +66,7 @@ struct shdma_chan {
 	size_t max_xfer_len;		/* max transfer length */
 	int id;				/* Raw id of this channel */
 	int irq;			/* Channel IRQ */
+	struct shdma_slave *slave;	/* Client data for slave DMA */
 	enum shdma_pm_state pm_state;
 };
 
-- 
1.7.2.5


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 1/4] dmaengine: shdma: prepare to stop using struct dma_chan::private
@ 2012-07-04 16:17   ` Guennadi Liakhovetski
  0 siblings, 0 replies; 16+ messages in thread
From: Guennadi Liakhovetski @ 2012-07-04 16:17 UTC (permalink / raw)
  To: Vinod Koul; +Cc: Magnus Damm, linux-sh, linux-mmc, Chris Ball, linux-kernel

Using struct dma_chan::private is deprecated. To update the shdma driver to
stop using it we first have to eliminate internal runtime uses of it. After
that we will also be able to stop using it for channel configuration.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/dma/sh/shdma-base.c |    9 +++++----
 drivers/dma/sh/shdma.c      |   24 ++++++++++--------------
 drivers/dma/sh/shdma.h      |    2 ++
 include/linux/sh_dma.h      |    2 --
 include/linux/shdma-base.h  |    1 +
 5 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
index ff060d0..f75ebfa 100644
--- a/drivers/dma/sh/shdma-base.c
+++ b/drivers/dma/sh/shdma-base.c
@@ -76,7 +76,7 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
 		container_of(tx, struct shdma_desc, async_tx),
 		*last = desc;
 	struct shdma_chan *schan = to_shdma_chan(tx->chan);
-	struct shdma_slave *slave = tx->chan->private;
+	struct shdma_slave *slave = schan->slave;
 	dma_async_tx_callback callback = tx->callback;
 	dma_cookie_t cookie;
 	bool power_up;
@@ -208,6 +208,7 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
 		goto edescalloc;
 	}
 	schan->desc_num = NR_DESCS_PER_CHANNEL;
+	schan->slave = slave;
 
 	for (i = 0; i < NR_DESCS_PER_CHANNEL; i++) {
 		desc = ops->embedded_desc(schan->desc, i);
@@ -365,9 +366,9 @@ static void shdma_free_chan_resources(struct dma_chan *chan)
 	if (!list_empty(&schan->ld_queue))
 		shdma_chan_ld_cleanup(schan, true);
 
-	if (chan->private) {
+	if (schan->slave) {
 		/* The caller is holding dma_list_mutex */
-		struct shdma_slave *slave = chan->private;
+		struct shdma_slave *slave = schan->slave;
 		clear_bit(slave->slave_id, shdma_slave_used);
 		chan->private = NULL;
 	}
@@ -558,7 +559,7 @@ static struct dma_async_tx_descriptor *shdma_prep_slave_sg(
 	struct shdma_chan *schan = to_shdma_chan(chan);
 	struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
 	const struct shdma_ops *ops = sdev->ops;
-	struct shdma_slave *slave = chan->private;
+	struct shdma_slave *slave = schan->slave;
 	dma_addr_t slave_addr;
 
 	if (!chan)
diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
index f06906f..9f0a2e5 100644
--- a/drivers/dma/sh/shdma.c
+++ b/drivers/dma/sh/shdma.c
@@ -291,10 +291,8 @@ static void sh_dmae_setup_xfer(struct shdma_chan *schan,
 						    shdma_chan);
 
 	if (sslave) {
-		struct sh_dmae_slave *slave = container_of(sslave,
-					struct sh_dmae_slave, shdma_slave);
 		const struct sh_dmae_slave_config *cfg =
-			slave->config;
+			sh_chan->config;
 
 		dmae_set_dmars(sh_chan, cfg->mid_rid);
 		dmae_set_chcr(sh_chan, cfg->chcr);
@@ -326,13 +324,11 @@ static int sh_dmae_set_slave(struct shdma_chan *schan,
 {
 	struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
 						    shdma_chan);
-	struct sh_dmae_slave *slave = container_of(sslave, struct sh_dmae_slave,
-						   shdma_slave);
 	const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, sslave->slave_id);
 	if (!cfg)
 		return -ENODEV;
 
-	slave->config = cfg;
+	sh_chan->config = cfg;
 
 	return 0;
 }
@@ -579,13 +575,12 @@ static int sh_dmae_resume(struct device *dev)
 
 	for (i = 0; i < shdev->pdata->channel_num; i++) {
 		struct sh_dmae_chan *sh_chan = shdev->chan[i];
-		struct sh_dmae_slave *param = sh_chan->shdma_chan.dma_chan.private;
 
 		if (!sh_chan->shdma_chan.desc_num)
 			continue;
 
-		if (param) {
-			const struct sh_dmae_slave_config *cfg = param->config;
+		if (sh_chan->shdma_chan.slave) {
+			const struct sh_dmae_slave_config *cfg = sh_chan->config;
 			dmae_set_dmars(sh_chan, cfg->mid_rid);
 			dmae_set_chcr(sh_chan, cfg->chcr);
 		} else {
@@ -609,14 +604,15 @@ const struct dev_pm_ops sh_dmae_pm = {
 
 static dma_addr_t sh_dmae_slave_addr(struct shdma_chan *schan)
 {
-	struct sh_dmae_slave *param = schan->dma_chan.private;
+	struct sh_dmae_chan *sh_chan = container_of(schan,
+					struct sh_dmae_chan, shdma_chan);
 
 	/*
-	 * Implicit BUG_ON(!param)
-	 * if (param != NULL), this is a successfully requested slave channel,
-	 * therefore param->config != NULL too.
+	 * Implicit BUG_ON(!sh_chan->config)
+	 * This is an exclusive slave DMA operation, may only be called after a
+	 * successful slave configuration.
 	 */
-	return param->config->addr;
+	return sh_chan->config->addr;
 }
 
 static struct shdma_desc *sh_dmae_embedded_desc(void *buf, int i)
diff --git a/drivers/dma/sh/shdma.h b/drivers/dma/sh/shdma.h
index 840e47d..9314e93 100644
--- a/drivers/dma/sh/shdma.h
+++ b/drivers/dma/sh/shdma.h
@@ -13,6 +13,7 @@
 #ifndef __DMA_SHDMA_H
 #define __DMA_SHDMA_H
 
+#include <linux/sh_dma.h>
 #include <linux/shdma-base.h>
 #include <linux/dmaengine.h>
 #include <linux/interrupt.h>
@@ -25,6 +26,7 @@ struct device;
 
 struct sh_dmae_chan {
 	struct shdma_chan shdma_chan;
+	const struct sh_dmae_slave_config *config; /* Slave DMA configuration */
 	int xmit_shift;			/* log_2(bytes_per_xfer) */
 	u32 __iomem *base;
 	char dev_id[16];		/* unique name per DMAC of channel */
diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
index 7c8ca41..a79f10a 100644
--- a/include/linux/sh_dma.h
+++ b/include/linux/sh_dma.h
@@ -20,8 +20,6 @@ struct device;
 /* Used by slave DMA clients to request DMA to/from a specific peripheral */
 struct sh_dmae_slave {
 	struct shdma_slave		shdma_slave;	/* Set by the platform */
-	struct device			*dma_dev;	/* Set by the platform */
-	const struct sh_dmae_slave_config *config;	/* Set by the driver */
 };
 
 /*
diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h
index 83efd13..c3a19e9 100644
--- a/include/linux/shdma-base.h
+++ b/include/linux/shdma-base.h
@@ -66,6 +66,7 @@ struct shdma_chan {
 	size_t max_xfer_len;		/* max transfer length */
 	int id;				/* Raw id of this channel */
 	int irq;			/* Channel IRQ */
+	struct shdma_slave *slave;	/* Client data for slave DMA */
 	enum shdma_pm_state pm_state;
 };
 
-- 
1.7.2.5


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 2/4] dma: sh: use an integer slave ID to improve API compatibility
  2012-07-04 16:17 ` Guennadi Liakhovetski
@ 2012-07-04 16:17   ` Guennadi Liakhovetski
  -1 siblings, 0 replies; 16+ messages in thread
From: Guennadi Liakhovetski @ 2012-07-04 16:17 UTC (permalink / raw)
  To: Vinod Koul; +Cc: Magnus Damm, linux-sh, linux-mmc, Chris Ball, linux-kernel

Initially struct shdma_slave has been introduced with the only member - an
unsigned slave ID - to describe common properties of DMA slaves in an
extensible way. However, experience shows, that a slave ID is indeed the
only parameter, needed to identify DMA slaves. This is also, what is used
by the core dmaengine API in struct dma_slave_config. We switch to using
the slave_id directly, instead of passing a pointer to struct shdma_slave
to improve compatibility with the core. We also make the slave_id signed
for easier error checking.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/dma/sh/shdma-base.c |   25 +++++++++++++------------
 drivers/dma/sh/shdma.c      |   12 ++++++------
 include/linux/sh_dma.h      |    8 ++++----
 include/linux/shdma-base.h  |    8 ++++----
 4 files changed, 27 insertions(+), 26 deletions(-)

diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
index f75ebfa..73db282 100644
--- a/drivers/dma/sh/shdma-base.c
+++ b/drivers/dma/sh/shdma-base.c
@@ -76,7 +76,6 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
 		container_of(tx, struct shdma_desc, async_tx),
 		*last = desc;
 	struct shdma_chan *schan = to_shdma_chan(tx->chan);
-	struct shdma_slave *slave = schan->slave;
 	dma_async_tx_callback callback = tx->callback;
 	dma_cookie_t cookie;
 	bool power_up;
@@ -138,7 +137,7 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
 			 * Make it int then, on error remove chunks from the
 			 * queue again
 			 */
-			ops->setup_xfer(schan, slave);
+			ops->setup_xfer(schan, schan->slave_id);
 
 			if (schan->pm_state = SHDMA_PM_PENDING)
 				shdma_chan_xfer_ld_queue(schan);
@@ -186,7 +185,7 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
 	 * never runs concurrently with itself or free_chan_resources.
 	 */
 	if (slave) {
-		if (slave->slave_id >= slave_num) {
+		if (slave->slave_id < 0 || slave->slave_id >= slave_num) {
 			ret = -EINVAL;
 			goto evalid;
 		}
@@ -196,9 +195,13 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
 			goto etestused;
 		}
 
-		ret = ops->set_slave(schan, slave);
+		ret = ops->set_slave(schan, slave->slave_id);
 		if (ret < 0)
 			goto esetslave;
+
+		schan->slave_id = slave->slave_id;
+	} else {
+		schan->slave_id = -EINVAL;
 	}
 
 	schan->desc = kcalloc(NR_DESCS_PER_CHANNEL,
@@ -208,7 +211,6 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
 		goto edescalloc;
 	}
 	schan->desc_num = NR_DESCS_PER_CHANNEL;
-	schan->slave = slave;
 
 	for (i = 0; i < NR_DESCS_PER_CHANNEL; i++) {
 		desc = ops->embedded_desc(schan->desc, i);
@@ -366,10 +368,9 @@ static void shdma_free_chan_resources(struct dma_chan *chan)
 	if (!list_empty(&schan->ld_queue))
 		shdma_chan_ld_cleanup(schan, true);
 
-	if (schan->slave) {
+	if (schan->slave_id >= 0) {
 		/* The caller is holding dma_list_mutex */
-		struct shdma_slave *slave = schan->slave;
-		clear_bit(slave->slave_id, shdma_slave_used);
+		clear_bit(schan->slave_id, shdma_slave_used);
 		chan->private = NULL;
 	}
 
@@ -559,7 +560,7 @@ static struct dma_async_tx_descriptor *shdma_prep_slave_sg(
 	struct shdma_chan *schan = to_shdma_chan(chan);
 	struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
 	const struct shdma_ops *ops = sdev->ops;
-	struct shdma_slave *slave = schan->slave;
+	int slave_id = schan->slave_id;
 	dma_addr_t slave_addr;
 
 	if (!chan)
@@ -568,9 +569,9 @@ static struct dma_async_tx_descriptor *shdma_prep_slave_sg(
 	BUG_ON(!schan->desc_num);
 
 	/* Someone calling slave DMA on a generic channel? */
-	if (!slave || !sg_len) {
-		dev_warn(schan->dev, "%s: bad parameter: %p, %d, %d\n",
-			 __func__, slave, sg_len, slave ? slave->slave_id : -1);
+	if (slave_id < 0 || !sg_len) {
+		dev_warn(schan->dev, "%s: bad parameter: len=%d, id=%d\n",
+			 __func__, sg_len, slave_id);
 		return NULL;
 	}
 
diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
index 9f0a2e5..9a10d8b 100644
--- a/drivers/dma/sh/shdma.c
+++ b/drivers/dma/sh/shdma.c
@@ -285,12 +285,12 @@ static bool sh_dmae_channel_busy(struct shdma_chan *schan)
 }
 
 static void sh_dmae_setup_xfer(struct shdma_chan *schan,
-			       struct shdma_slave *sslave)
+			       int slave_id)
 {
 	struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
 						    shdma_chan);
 
-	if (sslave) {
+	if (slave_id >= 0) {
 		const struct sh_dmae_slave_config *cfg  			sh_chan->config;
 
@@ -302,7 +302,7 @@ static void sh_dmae_setup_xfer(struct shdma_chan *schan,
 }
 
 static const struct sh_dmae_slave_config *dmae_find_slave(
-	struct sh_dmae_chan *sh_chan, unsigned int slave_id)
+	struct sh_dmae_chan *sh_chan, int slave_id)
 {
 	struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
 	struct sh_dmae_pdata *pdata = shdev->pdata;
@@ -320,11 +320,11 @@ static const struct sh_dmae_slave_config *dmae_find_slave(
 }
 
 static int sh_dmae_set_slave(struct shdma_chan *schan,
-			     struct shdma_slave *sslave)
+			     int slave_id)
 {
 	struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
 						    shdma_chan);
-	const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, sslave->slave_id);
+	const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, slave_id);
 	if (!cfg)
 		return -ENODEV;
 
@@ -579,7 +579,7 @@ static int sh_dmae_resume(struct device *dev)
 		if (!sh_chan->shdma_chan.desc_num)
 			continue;
 
-		if (sh_chan->shdma_chan.slave) {
+		if (sh_chan->shdma_chan.slave_id >= 0) {
 			const struct sh_dmae_slave_config *cfg = sh_chan->config;
 			dmae_set_dmars(sh_chan, cfg->mid_rid);
 			dmae_set_chcr(sh_chan, cfg->chcr);
diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
index a79f10a..4e83f3e 100644
--- a/include/linux/sh_dma.h
+++ b/include/linux/sh_dma.h
@@ -27,10 +27,10 @@ struct sh_dmae_slave {
  * a certain peripheral
  */
 struct sh_dmae_slave_config {
-	unsigned int			slave_id;
-	dma_addr_t			addr;
-	u32				chcr;
-	char				mid_rid;
+	int		slave_id;
+	dma_addr_t	addr;
+	u32		chcr;
+	char		mid_rid;
 };
 
 struct sh_dmae_channel {
diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h
index c3a19e9..6263ad2 100644
--- a/include/linux/shdma-base.h
+++ b/include/linux/shdma-base.h
@@ -43,7 +43,7 @@ struct device;
  */
 
 struct shdma_slave {
-	unsigned int slave_id;
+	int slave_id;
 };
 
 struct shdma_desc {
@@ -66,7 +66,7 @@ struct shdma_chan {
 	size_t max_xfer_len;		/* max transfer length */
 	int id;				/* Raw id of this channel */
 	int irq;			/* Channel IRQ */
-	struct shdma_slave *slave;	/* Client data for slave DMA */
+	int slave_id;			/* Client ID for slave DMA */
 	enum shdma_pm_state pm_state;
 };
 
@@ -93,8 +93,8 @@ struct shdma_ops {
 	dma_addr_t (*slave_addr)(struct shdma_chan *);
 	int (*desc_setup)(struct shdma_chan *, struct shdma_desc *,
 			  dma_addr_t, dma_addr_t, size_t *);
-	int (*set_slave)(struct shdma_chan *, struct shdma_slave *);
-	void (*setup_xfer)(struct shdma_chan *, struct shdma_slave *);
+	int (*set_slave)(struct shdma_chan *, int);
+	void (*setup_xfer)(struct shdma_chan *, int);
 	void (*start_xfer)(struct shdma_chan *, struct shdma_desc *);
 	struct shdma_desc *(*embedded_desc)(void *, int);
 	bool (*chan_irq)(struct shdma_chan *, int);
-- 
1.7.2.5


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 2/4] dma: sh: use an integer slave ID to improve API compatibility
@ 2012-07-04 16:17   ` Guennadi Liakhovetski
  0 siblings, 0 replies; 16+ messages in thread
From: Guennadi Liakhovetski @ 2012-07-04 16:17 UTC (permalink / raw)
  To: Vinod Koul; +Cc: Magnus Damm, linux-sh, linux-mmc, Chris Ball, linux-kernel

Initially struct shdma_slave has been introduced with the only member - an
unsigned slave ID - to describe common properties of DMA slaves in an
extensible way. However, experience shows, that a slave ID is indeed the
only parameter, needed to identify DMA slaves. This is also, what is used
by the core dmaengine API in struct dma_slave_config. We switch to using
the slave_id directly, instead of passing a pointer to struct shdma_slave
to improve compatibility with the core. We also make the slave_id signed
for easier error checking.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/dma/sh/shdma-base.c |   25 +++++++++++++------------
 drivers/dma/sh/shdma.c      |   12 ++++++------
 include/linux/sh_dma.h      |    8 ++++----
 include/linux/shdma-base.h  |    8 ++++----
 4 files changed, 27 insertions(+), 26 deletions(-)

diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
index f75ebfa..73db282 100644
--- a/drivers/dma/sh/shdma-base.c
+++ b/drivers/dma/sh/shdma-base.c
@@ -76,7 +76,6 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
 		container_of(tx, struct shdma_desc, async_tx),
 		*last = desc;
 	struct shdma_chan *schan = to_shdma_chan(tx->chan);
-	struct shdma_slave *slave = schan->slave;
 	dma_async_tx_callback callback = tx->callback;
 	dma_cookie_t cookie;
 	bool power_up;
@@ -138,7 +137,7 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
 			 * Make it int then, on error remove chunks from the
 			 * queue again
 			 */
-			ops->setup_xfer(schan, slave);
+			ops->setup_xfer(schan, schan->slave_id);
 
 			if (schan->pm_state == SHDMA_PM_PENDING)
 				shdma_chan_xfer_ld_queue(schan);
@@ -186,7 +185,7 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
 	 * never runs concurrently with itself or free_chan_resources.
 	 */
 	if (slave) {
-		if (slave->slave_id >= slave_num) {
+		if (slave->slave_id < 0 || slave->slave_id >= slave_num) {
 			ret = -EINVAL;
 			goto evalid;
 		}
@@ -196,9 +195,13 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
 			goto etestused;
 		}
 
-		ret = ops->set_slave(schan, slave);
+		ret = ops->set_slave(schan, slave->slave_id);
 		if (ret < 0)
 			goto esetslave;
+
+		schan->slave_id = slave->slave_id;
+	} else {
+		schan->slave_id = -EINVAL;
 	}
 
 	schan->desc = kcalloc(NR_DESCS_PER_CHANNEL,
@@ -208,7 +211,6 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
 		goto edescalloc;
 	}
 	schan->desc_num = NR_DESCS_PER_CHANNEL;
-	schan->slave = slave;
 
 	for (i = 0; i < NR_DESCS_PER_CHANNEL; i++) {
 		desc = ops->embedded_desc(schan->desc, i);
@@ -366,10 +368,9 @@ static void shdma_free_chan_resources(struct dma_chan *chan)
 	if (!list_empty(&schan->ld_queue))
 		shdma_chan_ld_cleanup(schan, true);
 
-	if (schan->slave) {
+	if (schan->slave_id >= 0) {
 		/* The caller is holding dma_list_mutex */
-		struct shdma_slave *slave = schan->slave;
-		clear_bit(slave->slave_id, shdma_slave_used);
+		clear_bit(schan->slave_id, shdma_slave_used);
 		chan->private = NULL;
 	}
 
@@ -559,7 +560,7 @@ static struct dma_async_tx_descriptor *shdma_prep_slave_sg(
 	struct shdma_chan *schan = to_shdma_chan(chan);
 	struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
 	const struct shdma_ops *ops = sdev->ops;
-	struct shdma_slave *slave = schan->slave;
+	int slave_id = schan->slave_id;
 	dma_addr_t slave_addr;
 
 	if (!chan)
@@ -568,9 +569,9 @@ static struct dma_async_tx_descriptor *shdma_prep_slave_sg(
 	BUG_ON(!schan->desc_num);
 
 	/* Someone calling slave DMA on a generic channel? */
-	if (!slave || !sg_len) {
-		dev_warn(schan->dev, "%s: bad parameter: %p, %d, %d\n",
-			 __func__, slave, sg_len, slave ? slave->slave_id : -1);
+	if (slave_id < 0 || !sg_len) {
+		dev_warn(schan->dev, "%s: bad parameter: len=%d, id=%d\n",
+			 __func__, sg_len, slave_id);
 		return NULL;
 	}
 
diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
index 9f0a2e5..9a10d8b 100644
--- a/drivers/dma/sh/shdma.c
+++ b/drivers/dma/sh/shdma.c
@@ -285,12 +285,12 @@ static bool sh_dmae_channel_busy(struct shdma_chan *schan)
 }
 
 static void sh_dmae_setup_xfer(struct shdma_chan *schan,
-			       struct shdma_slave *sslave)
+			       int slave_id)
 {
 	struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
 						    shdma_chan);
 
-	if (sslave) {
+	if (slave_id >= 0) {
 		const struct sh_dmae_slave_config *cfg =
 			sh_chan->config;
 
@@ -302,7 +302,7 @@ static void sh_dmae_setup_xfer(struct shdma_chan *schan,
 }
 
 static const struct sh_dmae_slave_config *dmae_find_slave(
-	struct sh_dmae_chan *sh_chan, unsigned int slave_id)
+	struct sh_dmae_chan *sh_chan, int slave_id)
 {
 	struct sh_dmae_device *shdev = to_sh_dev(sh_chan);
 	struct sh_dmae_pdata *pdata = shdev->pdata;
@@ -320,11 +320,11 @@ static const struct sh_dmae_slave_config *dmae_find_slave(
 }
 
 static int sh_dmae_set_slave(struct shdma_chan *schan,
-			     struct shdma_slave *sslave)
+			     int slave_id)
 {
 	struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
 						    shdma_chan);
-	const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, sslave->slave_id);
+	const struct sh_dmae_slave_config *cfg = dmae_find_slave(sh_chan, slave_id);
 	if (!cfg)
 		return -ENODEV;
 
@@ -579,7 +579,7 @@ static int sh_dmae_resume(struct device *dev)
 		if (!sh_chan->shdma_chan.desc_num)
 			continue;
 
-		if (sh_chan->shdma_chan.slave) {
+		if (sh_chan->shdma_chan.slave_id >= 0) {
 			const struct sh_dmae_slave_config *cfg = sh_chan->config;
 			dmae_set_dmars(sh_chan, cfg->mid_rid);
 			dmae_set_chcr(sh_chan, cfg->chcr);
diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
index a79f10a..4e83f3e 100644
--- a/include/linux/sh_dma.h
+++ b/include/linux/sh_dma.h
@@ -27,10 +27,10 @@ struct sh_dmae_slave {
  * a certain peripheral
  */
 struct sh_dmae_slave_config {
-	unsigned int			slave_id;
-	dma_addr_t			addr;
-	u32				chcr;
-	char				mid_rid;
+	int		slave_id;
+	dma_addr_t	addr;
+	u32		chcr;
+	char		mid_rid;
 };
 
 struct sh_dmae_channel {
diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h
index c3a19e9..6263ad2 100644
--- a/include/linux/shdma-base.h
+++ b/include/linux/shdma-base.h
@@ -43,7 +43,7 @@ struct device;
  */
 
 struct shdma_slave {
-	unsigned int slave_id;
+	int slave_id;
 };
 
 struct shdma_desc {
@@ -66,7 +66,7 @@ struct shdma_chan {
 	size_t max_xfer_len;		/* max transfer length */
 	int id;				/* Raw id of this channel */
 	int irq;			/* Channel IRQ */
-	struct shdma_slave *slave;	/* Client data for slave DMA */
+	int slave_id;			/* Client ID for slave DMA */
 	enum shdma_pm_state pm_state;
 };
 
@@ -93,8 +93,8 @@ struct shdma_ops {
 	dma_addr_t (*slave_addr)(struct shdma_chan *);
 	int (*desc_setup)(struct shdma_chan *, struct shdma_desc *,
 			  dma_addr_t, dma_addr_t, size_t *);
-	int (*set_slave)(struct shdma_chan *, struct shdma_slave *);
-	void (*setup_xfer)(struct shdma_chan *, struct shdma_slave *);
+	int (*set_slave)(struct shdma_chan *, int);
+	void (*setup_xfer)(struct shdma_chan *, int);
 	void (*start_xfer)(struct shdma_chan *, struct shdma_desc *);
 	struct shdma_desc *(*embedded_desc)(void *, int);
 	bool (*chan_irq)(struct shdma_chan *, int);
-- 
1.7.2.5


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 3/4] dma: sh: provide a migration path for slave drivers to stop using .private
  2012-07-04 16:17 ` Guennadi Liakhovetski
@ 2012-07-04 16:17   ` Guennadi Liakhovetski
  -1 siblings, 0 replies; 16+ messages in thread
From: Guennadi Liakhovetski @ 2012-07-04 16:17 UTC (permalink / raw)
  To: Vinod Koul; +Cc: Magnus Damm, linux-sh, linux-mmc, Chris Ball, linux-kernel

This patch extends the sh dmaengine driver to support the preferred channel
selection and configuration method, instead of using the "private" field
from struct dma_chan. We add a standard filter function to be used by
slave drivers instead of implementing their own ones, and add support for
the DMA_SLAVE_CONFIG control operation, which must accompany the new
channel selection method. We still support the legacy .private channel
allocation method to cater for a smooth driver migration.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/dma/sh/shdma-base.c |  114 +++++++++++++++++++++++++++++++++---------
 drivers/dma/sh/shdma.c      |    5 +-
 include/linux/sh_dma.h      |    2 +
 include/linux/shdma-base.h  |    2 +-
 4 files changed, 95 insertions(+), 28 deletions(-)

diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
index 73db282..0c34c73 100644
--- a/drivers/dma/sh/shdma-base.c
+++ b/drivers/dma/sh/shdma-base.c
@@ -171,6 +171,65 @@ static struct shdma_desc *shdma_get_desc(struct shdma_chan *schan)
 	return NULL;
 }
 
+static int shdma_setup_slave(struct shdma_chan *schan, int slave_id)
+{
+	struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
+	const struct shdma_ops *ops = sdev->ops;
+	int ret;
+
+	if (slave_id < 0 || slave_id >= slave_num)
+		return -EINVAL;
+
+	if (test_and_set_bit(slave_id, shdma_slave_used))
+		return -EBUSY;
+
+	ret = ops->set_slave(schan, slave_id, false);
+	if (ret < 0) {
+		clear_bit(slave_id, shdma_slave_used);
+		return ret;
+	}
+
+	schan->slave_id = slave_id;
+
+	return 0;
+}
+
+/*
+ * This is the standard shdma filter function to be used as a replacement to the
+ * "old" method, using the .private pointer. If for some reason you allocate a
+ * channel without slave data, use something like ERR_PTR(-EINVAL) as a filter
+ * parameter. If this filter is used, the slave driver, after calling
+ * dma_request_channel(), will also have to call dmaengine_slave_config() with
+ * .slave_id, .direction, and either .src_addr or .dst_addr set.
+ * NOTE: this filter doesn't support multiple DMAC drivers with the DMA_SLAVE
+ * capability! If this becomes a requirement, hardware glue drivers, using this
+ * services would have to provide their own filters, which first would check
+ * the device driver, similar to how other DMAC drivers, e.g., sa11x0-dma.c, do
+ * this, and only then, in case of a match, call this common filter.
+ */
+bool shdma_chan_filter(struct dma_chan *chan, void *arg)
+{
+	struct shdma_chan *schan = to_shdma_chan(chan);
+	struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
+	const struct shdma_ops *ops = sdev->ops;
+	int slave_id = (int)arg;
+	int ret;
+
+	if (slave_id < 0)
+		/* No slave requested - arbitrary channel */
+		return true;
+
+	if (slave_id >= slave_num)
+		return false;
+
+	ret = ops->set_slave(schan, slave_id, true);
+	if (ret < 0)
+		return false;
+
+	return true;
+}
+EXPORT_SYMBOL(shdma_chan_filter);
+
 static int shdma_alloc_chan_resources(struct dma_chan *chan)
 {
 	struct shdma_chan *schan = to_shdma_chan(chan);
@@ -185,21 +244,10 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
 	 * never runs concurrently with itself or free_chan_resources.
 	 */
 	if (slave) {
-		if (slave->slave_id < 0 || slave->slave_id >= slave_num) {
-			ret = -EINVAL;
-			goto evalid;
-		}
-
-		if (test_and_set_bit(slave->slave_id, shdma_slave_used)) {
-			ret = -EBUSY;
-			goto etestused;
-		}
-
-		ret = ops->set_slave(schan, slave->slave_id);
+		/* Legacy mode: .private is set in filter */
+		ret = shdma_setup_slave(schan, slave->slave_id);
 		if (ret < 0)
 			goto esetslave;
-
-		schan->slave_id = slave->slave_id;
 	} else {
 		schan->slave_id = -EINVAL;
 	}
@@ -228,8 +276,6 @@ edescalloc:
 	if (slave)
 esetslave:
 		clear_bit(slave->slave_id, shdma_slave_used);
-etestused:
-evalid:
 	chan->private = NULL;
 	return ret;
 }
@@ -587,22 +633,40 @@ static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 	struct shdma_chan *schan = to_shdma_chan(chan);
 	struct shdma_dev *sdev = to_shdma_dev(chan->device);
 	const struct shdma_ops *ops = sdev->ops;
+	struct dma_slave_config *config;
 	unsigned long flags;
-
-	/* Only supports DMA_TERMINATE_ALL */
-	if (cmd != DMA_TERMINATE_ALL)
-		return -ENXIO;
+	int ret;
 
 	if (!chan)
 		return -EINVAL;
 
-	spin_lock_irqsave(&schan->chan_lock, flags);
-
-	ops->halt_channel(schan);
-
-	spin_unlock_irqrestore(&schan->chan_lock, flags);
+	switch (cmd) {
+	case DMA_TERMINATE_ALL:
+		spin_lock_irqsave(&schan->chan_lock, flags);
+		ops->halt_channel(schan);
+		spin_unlock_irqrestore(&schan->chan_lock, flags);
 
-	shdma_chan_ld_cleanup(schan, true);
+		shdma_chan_ld_cleanup(schan, true);
+		break;
+	case DMA_SLAVE_CONFIG:
+		/*
+		 * So far only .slave_id is used, but the slave drivers are
+		 * encouraged to also set a transfer direction and an address.
+		 */
+		if (!arg)
+			return -EINVAL;
+		/*
+		 * We could lock this, but you shouldn't be configuring the
+		 * channel, while using it...
+		 */
+		config = (struct dma_slave_config*)arg;
+		ret = shdma_setup_slave(schan, config->slave_id);
+		if (ret < 0)
+			return ret;
+		break;
+	default:
+		return -ENXIO;
+	}
 
 	return 0;
 }
diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
index 9a10d8b..027c9be 100644
--- a/drivers/dma/sh/shdma.c
+++ b/drivers/dma/sh/shdma.c
@@ -320,7 +320,7 @@ static const struct sh_dmae_slave_config *dmae_find_slave(
 }
 
 static int sh_dmae_set_slave(struct shdma_chan *schan,
-			     int slave_id)
+			     int slave_id, bool try)
 {
 	struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
 						    shdma_chan);
@@ -328,7 +328,8 @@ static int sh_dmae_set_slave(struct shdma_chan *schan,
 	if (!cfg)
 		return -ENODEV;
 
-	sh_chan->config = cfg;
+	if (!try)
+		sh_chan->config = cfg;
 
 	return 0;
 }
diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
index 4e83f3e..b64d6be 100644
--- a/include/linux/sh_dma.h
+++ b/include/linux/sh_dma.h
@@ -99,4 +99,6 @@ struct sh_dmae_pdata {
 #define CHCR_TE	0x00000002
 #define CHCR_IE	0x00000004
 
+bool shdma_chan_filter(struct dma_chan *chan, void *arg);
+
 #endif
diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h
index 6263ad2..93f9821 100644
--- a/include/linux/shdma-base.h
+++ b/include/linux/shdma-base.h
@@ -93,7 +93,7 @@ struct shdma_ops {
 	dma_addr_t (*slave_addr)(struct shdma_chan *);
 	int (*desc_setup)(struct shdma_chan *, struct shdma_desc *,
 			  dma_addr_t, dma_addr_t, size_t *);
-	int (*set_slave)(struct shdma_chan *, int);
+	int (*set_slave)(struct shdma_chan *, int, bool);
 	void (*setup_xfer)(struct shdma_chan *, int);
 	void (*start_xfer)(struct shdma_chan *, struct shdma_desc *);
 	struct shdma_desc *(*embedded_desc)(void *, int);
-- 
1.7.2.5


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 3/4] dma: sh: provide a migration path for slave drivers to stop using .private
@ 2012-07-04 16:17   ` Guennadi Liakhovetski
  0 siblings, 0 replies; 16+ messages in thread
From: Guennadi Liakhovetski @ 2012-07-04 16:17 UTC (permalink / raw)
  To: Vinod Koul; +Cc: Magnus Damm, linux-sh, linux-mmc, Chris Ball, linux-kernel

This patch extends the sh dmaengine driver to support the preferred channel
selection and configuration method, instead of using the "private" field
from struct dma_chan. We add a standard filter function to be used by
slave drivers instead of implementing their own ones, and add support for
the DMA_SLAVE_CONFIG control operation, which must accompany the new
channel selection method. We still support the legacy .private channel
allocation method to cater for a smooth driver migration.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/dma/sh/shdma-base.c |  114 +++++++++++++++++++++++++++++++++---------
 drivers/dma/sh/shdma.c      |    5 +-
 include/linux/sh_dma.h      |    2 +
 include/linux/shdma-base.h  |    2 +-
 4 files changed, 95 insertions(+), 28 deletions(-)

diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c
index 73db282..0c34c73 100644
--- a/drivers/dma/sh/shdma-base.c
+++ b/drivers/dma/sh/shdma-base.c
@@ -171,6 +171,65 @@ static struct shdma_desc *shdma_get_desc(struct shdma_chan *schan)
 	return NULL;
 }
 
+static int shdma_setup_slave(struct shdma_chan *schan, int slave_id)
+{
+	struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
+	const struct shdma_ops *ops = sdev->ops;
+	int ret;
+
+	if (slave_id < 0 || slave_id >= slave_num)
+		return -EINVAL;
+
+	if (test_and_set_bit(slave_id, shdma_slave_used))
+		return -EBUSY;
+
+	ret = ops->set_slave(schan, slave_id, false);
+	if (ret < 0) {
+		clear_bit(slave_id, shdma_slave_used);
+		return ret;
+	}
+
+	schan->slave_id = slave_id;
+
+	return 0;
+}
+
+/*
+ * This is the standard shdma filter function to be used as a replacement to the
+ * "old" method, using the .private pointer. If for some reason you allocate a
+ * channel without slave data, use something like ERR_PTR(-EINVAL) as a filter
+ * parameter. If this filter is used, the slave driver, after calling
+ * dma_request_channel(), will also have to call dmaengine_slave_config() with
+ * .slave_id, .direction, and either .src_addr or .dst_addr set.
+ * NOTE: this filter doesn't support multiple DMAC drivers with the DMA_SLAVE
+ * capability! If this becomes a requirement, hardware glue drivers, using this
+ * services would have to provide their own filters, which first would check
+ * the device driver, similar to how other DMAC drivers, e.g., sa11x0-dma.c, do
+ * this, and only then, in case of a match, call this common filter.
+ */
+bool shdma_chan_filter(struct dma_chan *chan, void *arg)
+{
+	struct shdma_chan *schan = to_shdma_chan(chan);
+	struct shdma_dev *sdev = to_shdma_dev(schan->dma_chan.device);
+	const struct shdma_ops *ops = sdev->ops;
+	int slave_id = (int)arg;
+	int ret;
+
+	if (slave_id < 0)
+		/* No slave requested - arbitrary channel */
+		return true;
+
+	if (slave_id >= slave_num)
+		return false;
+
+	ret = ops->set_slave(schan, slave_id, true);
+	if (ret < 0)
+		return false;
+
+	return true;
+}
+EXPORT_SYMBOL(shdma_chan_filter);
+
 static int shdma_alloc_chan_resources(struct dma_chan *chan)
 {
 	struct shdma_chan *schan = to_shdma_chan(chan);
@@ -185,21 +244,10 @@ static int shdma_alloc_chan_resources(struct dma_chan *chan)
 	 * never runs concurrently with itself or free_chan_resources.
 	 */
 	if (slave) {
-		if (slave->slave_id < 0 || slave->slave_id >= slave_num) {
-			ret = -EINVAL;
-			goto evalid;
-		}
-
-		if (test_and_set_bit(slave->slave_id, shdma_slave_used)) {
-			ret = -EBUSY;
-			goto etestused;
-		}
-
-		ret = ops->set_slave(schan, slave->slave_id);
+		/* Legacy mode: .private is set in filter */
+		ret = shdma_setup_slave(schan, slave->slave_id);
 		if (ret < 0)
 			goto esetslave;
-
-		schan->slave_id = slave->slave_id;
 	} else {
 		schan->slave_id = -EINVAL;
 	}
@@ -228,8 +276,6 @@ edescalloc:
 	if (slave)
 esetslave:
 		clear_bit(slave->slave_id, shdma_slave_used);
-etestused:
-evalid:
 	chan->private = NULL;
 	return ret;
 }
@@ -587,22 +633,40 @@ static int shdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 	struct shdma_chan *schan = to_shdma_chan(chan);
 	struct shdma_dev *sdev = to_shdma_dev(chan->device);
 	const struct shdma_ops *ops = sdev->ops;
+	struct dma_slave_config *config;
 	unsigned long flags;
-
-	/* Only supports DMA_TERMINATE_ALL */
-	if (cmd != DMA_TERMINATE_ALL)
-		return -ENXIO;
+	int ret;
 
 	if (!chan)
 		return -EINVAL;
 
-	spin_lock_irqsave(&schan->chan_lock, flags);
-
-	ops->halt_channel(schan);
-
-	spin_unlock_irqrestore(&schan->chan_lock, flags);
+	switch (cmd) {
+	case DMA_TERMINATE_ALL:
+		spin_lock_irqsave(&schan->chan_lock, flags);
+		ops->halt_channel(schan);
+		spin_unlock_irqrestore(&schan->chan_lock, flags);
 
-	shdma_chan_ld_cleanup(schan, true);
+		shdma_chan_ld_cleanup(schan, true);
+		break;
+	case DMA_SLAVE_CONFIG:
+		/*
+		 * So far only .slave_id is used, but the slave drivers are
+		 * encouraged to also set a transfer direction and an address.
+		 */
+		if (!arg)
+			return -EINVAL;
+		/*
+		 * We could lock this, but you shouldn't be configuring the
+		 * channel, while using it...
+		 */
+		config = (struct dma_slave_config*)arg;
+		ret = shdma_setup_slave(schan, config->slave_id);
+		if (ret < 0)
+			return ret;
+		break;
+	default:
+		return -ENXIO;
+	}
 
 	return 0;
 }
diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c
index 9a10d8b..027c9be 100644
--- a/drivers/dma/sh/shdma.c
+++ b/drivers/dma/sh/shdma.c
@@ -320,7 +320,7 @@ static const struct sh_dmae_slave_config *dmae_find_slave(
 }
 
 static int sh_dmae_set_slave(struct shdma_chan *schan,
-			     int slave_id)
+			     int slave_id, bool try)
 {
 	struct sh_dmae_chan *sh_chan = container_of(schan, struct sh_dmae_chan,
 						    shdma_chan);
@@ -328,7 +328,8 @@ static int sh_dmae_set_slave(struct shdma_chan *schan,
 	if (!cfg)
 		return -ENODEV;
 
-	sh_chan->config = cfg;
+	if (!try)
+		sh_chan->config = cfg;
 
 	return 0;
 }
diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h
index 4e83f3e..b64d6be 100644
--- a/include/linux/sh_dma.h
+++ b/include/linux/sh_dma.h
@@ -99,4 +99,6 @@ struct sh_dmae_pdata {
 #define CHCR_TE	0x00000002
 #define CHCR_IE	0x00000004
 
+bool shdma_chan_filter(struct dma_chan *chan, void *arg);
+
 #endif
diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h
index 6263ad2..93f9821 100644
--- a/include/linux/shdma-base.h
+++ b/include/linux/shdma-base.h
@@ -93,7 +93,7 @@ struct shdma_ops {
 	dma_addr_t (*slave_addr)(struct shdma_chan *);
 	int (*desc_setup)(struct shdma_chan *, struct shdma_desc *,
 			  dma_addr_t, dma_addr_t, size_t *);
-	int (*set_slave)(struct shdma_chan *, int);
+	int (*set_slave)(struct shdma_chan *, int, bool);
 	void (*setup_xfer)(struct shdma_chan *, int);
 	void (*start_xfer)(struct shdma_chan *, struct shdma_desc *);
 	struct shdma_desc *(*embedded_desc)(void *, int);
-- 
1.7.2.5


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 4/4] mmc: sh_mmcif: switch to the new DMA channel allocation and configuration
  2012-07-04 16:17 ` Guennadi Liakhovetski
@ 2012-07-04 16:17   ` Guennadi Liakhovetski
  -1 siblings, 0 replies; 16+ messages in thread
From: Guennadi Liakhovetski @ 2012-07-04 16:17 UTC (permalink / raw)
  To: Vinod Koul; +Cc: Magnus Damm, linux-sh, linux-mmc, Chris Ball, linux-kernel

Using the "private" field from struct dma_chan is deprecated. The sh
dmaengine driver now also supports the preferred DMA channel allocation
and configuration method, using a standard filter function and a channel
configuration operation. This patch updates sh_mmcif to use this new
method.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/mmc/host/sh_mmcif.c |   90 ++++++++++++++++++++++++------------------
 1 files changed, 51 insertions(+), 39 deletions(-)

diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 9e3b9b1..0f07d28 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -211,8 +211,6 @@ struct sh_mmcif_host {
 	struct mmc_host *mmc;
 	struct mmc_request *mrq;
 	struct platform_device *pd;
-	struct sh_dmae_slave dma_slave_tx;
-	struct sh_dmae_slave dma_slave_rx;
 	struct clk *hclk;
 	unsigned int clk;
 	int bus_width;
@@ -371,52 +369,66 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
 		desc, cookie);
 }
 
-static bool sh_mmcif_filter(struct dma_chan *chan, void *arg)
-{
-	dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg);
-	chan->private = arg;
-	return true;
-}
-
 static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
 				 struct sh_mmcif_plat_data *pdata)
 {
-	struct sh_dmae_slave *tx, *rx;
+	struct resource *res = platform_get_resource(host->pd, IORESOURCE_MEM, 0);
+	struct dma_slave_config cfg;
+	dma_cap_mask_t mask;
+	int ret;
+
 	host->dma_active = false;
 
+	if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0)
+		return;
+
 	/* We can only either use DMA for both Tx and Rx or not use it at all */
-	tx = &host->dma_slave_tx;
-	tx->shdma_slave.slave_id = pdata->slave_id_tx;
-	rx = &host->dma_slave_rx;
-	rx->shdma_slave.slave_id = pdata->slave_id_rx;
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	host->chan_tx = dma_request_channel(mask, shdma_chan_filter,
+					    (void *)pdata->slave_id_tx);
+	dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
+		host->chan_tx);
 
-	if (tx->shdma_slave.slave_id > 0 && rx->shdma_slave.slave_id > 0) {
-		dma_cap_mask_t mask;
+	if (!host->chan_tx)
+		return;
 
-		dma_cap_zero(mask);
-		dma_cap_set(DMA_SLAVE, mask);
+	cfg.slave_id = pdata->slave_id_tx;
+	cfg.direction = DMA_MEM_TO_DEV;
+	cfg.dst_addr = res->start + MMCIF_CE_DATA;
+	cfg.src_addr = 0;
+	ret = dmaengine_slave_config(host->chan_tx, &cfg);
+	if (ret < 0)
+		goto ecfgtx;
 
-		host->chan_tx = dma_request_channel(mask, sh_mmcif_filter,
-						    &tx->shdma_slave);
-		dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
-			host->chan_tx);
+	host->chan_rx = dma_request_channel(mask, shdma_chan_filter,
+					    (void *)pdata->slave_id_rx);
+	dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
+		host->chan_rx);
 
-		if (!host->chan_tx)
-			return;
+	if (!host->chan_rx)
+		goto erqrx;
 
-		host->chan_rx = dma_request_channel(mask, sh_mmcif_filter,
-						    &rx->shdma_slave);
-		dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
-			host->chan_rx);
+	cfg.slave_id = pdata->slave_id_rx;
+	cfg.direction = DMA_DEV_TO_MEM;
+	cfg.dst_addr = 0;
+	cfg.src_addr = res->start + MMCIF_CE_DATA;
+	ret = dmaengine_slave_config(host->chan_rx, &cfg);
+	if (ret < 0)
+		goto ecfgrx;
 
-		if (!host->chan_rx) {
-			dma_release_channel(host->chan_tx);
-			host->chan_tx = NULL;
-			return;
-		}
+	init_completion(&host->dma_complete);
 
-		init_completion(&host->dma_complete);
-	}
+	return;
+
+ecfgrx:
+	dma_release_channel(host->chan_rx);
+	host->chan_rx = NULL;
+erqrx:
+ecfgtx:
+	dma_release_channel(host->chan_tx);
+	host->chan_tx = NULL;
 }
 
 static void sh_mmcif_release_dma(struct sh_mmcif_host *host)
-- 
1.7.2.5


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH 4/4] mmc: sh_mmcif: switch to the new DMA channel allocation and configuration
@ 2012-07-04 16:17   ` Guennadi Liakhovetski
  0 siblings, 0 replies; 16+ messages in thread
From: Guennadi Liakhovetski @ 2012-07-04 16:17 UTC (permalink / raw)
  To: Vinod Koul; +Cc: Magnus Damm, linux-sh, linux-mmc, Chris Ball, linux-kernel

Using the "private" field from struct dma_chan is deprecated. The sh
dmaengine driver now also supports the preferred DMA channel allocation
and configuration method, using a standard filter function and a channel
configuration operation. This patch updates sh_mmcif to use this new
method.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
---
 drivers/mmc/host/sh_mmcif.c |   90 ++++++++++++++++++++++++------------------
 1 files changed, 51 insertions(+), 39 deletions(-)

diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
index 9e3b9b1..0f07d28 100644
--- a/drivers/mmc/host/sh_mmcif.c
+++ b/drivers/mmc/host/sh_mmcif.c
@@ -211,8 +211,6 @@ struct sh_mmcif_host {
 	struct mmc_host *mmc;
 	struct mmc_request *mrq;
 	struct platform_device *pd;
-	struct sh_dmae_slave dma_slave_tx;
-	struct sh_dmae_slave dma_slave_rx;
 	struct clk *hclk;
 	unsigned int clk;
 	int bus_width;
@@ -371,52 +369,66 @@ static void sh_mmcif_start_dma_tx(struct sh_mmcif_host *host)
 		desc, cookie);
 }
 
-static bool sh_mmcif_filter(struct dma_chan *chan, void *arg)
-{
-	dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg);
-	chan->private = arg;
-	return true;
-}
-
 static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
 				 struct sh_mmcif_plat_data *pdata)
 {
-	struct sh_dmae_slave *tx, *rx;
+	struct resource *res = platform_get_resource(host->pd, IORESOURCE_MEM, 0);
+	struct dma_slave_config cfg;
+	dma_cap_mask_t mask;
+	int ret;
+
 	host->dma_active = false;
 
+	if (pdata->slave_id_tx <= 0 || pdata->slave_id_rx <= 0)
+		return;
+
 	/* We can only either use DMA for both Tx and Rx or not use it at all */
-	tx = &host->dma_slave_tx;
-	tx->shdma_slave.slave_id = pdata->slave_id_tx;
-	rx = &host->dma_slave_rx;
-	rx->shdma_slave.slave_id = pdata->slave_id_rx;
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	host->chan_tx = dma_request_channel(mask, shdma_chan_filter,
+					    (void *)pdata->slave_id_tx);
+	dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
+		host->chan_tx);
 
-	if (tx->shdma_slave.slave_id > 0 && rx->shdma_slave.slave_id > 0) {
-		dma_cap_mask_t mask;
+	if (!host->chan_tx)
+		return;
 
-		dma_cap_zero(mask);
-		dma_cap_set(DMA_SLAVE, mask);
+	cfg.slave_id = pdata->slave_id_tx;
+	cfg.direction = DMA_MEM_TO_DEV;
+	cfg.dst_addr = res->start + MMCIF_CE_DATA;
+	cfg.src_addr = 0;
+	ret = dmaengine_slave_config(host->chan_tx, &cfg);
+	if (ret < 0)
+		goto ecfgtx;
 
-		host->chan_tx = dma_request_channel(mask, sh_mmcif_filter,
-						    &tx->shdma_slave);
-		dev_dbg(&host->pd->dev, "%s: TX: got channel %p\n", __func__,
-			host->chan_tx);
+	host->chan_rx = dma_request_channel(mask, shdma_chan_filter,
+					    (void *)pdata->slave_id_rx);
+	dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
+		host->chan_rx);
 
-		if (!host->chan_tx)
-			return;
+	if (!host->chan_rx)
+		goto erqrx;
 
-		host->chan_rx = dma_request_channel(mask, sh_mmcif_filter,
-						    &rx->shdma_slave);
-		dev_dbg(&host->pd->dev, "%s: RX: got channel %p\n", __func__,
-			host->chan_rx);
+	cfg.slave_id = pdata->slave_id_rx;
+	cfg.direction = DMA_DEV_TO_MEM;
+	cfg.dst_addr = 0;
+	cfg.src_addr = res->start + MMCIF_CE_DATA;
+	ret = dmaengine_slave_config(host->chan_rx, &cfg);
+	if (ret < 0)
+		goto ecfgrx;
 
-		if (!host->chan_rx) {
-			dma_release_channel(host->chan_tx);
-			host->chan_tx = NULL;
-			return;
-		}
+	init_completion(&host->dma_complete);
 
-		init_completion(&host->dma_complete);
-	}
+	return;
+
+ecfgrx:
+	dma_release_channel(host->chan_rx);
+	host->chan_rx = NULL;
+erqrx:
+ecfgtx:
+	dma_release_channel(host->chan_tx);
+	host->chan_tx = NULL;
 }
 
 static void sh_mmcif_release_dma(struct sh_mmcif_host *host)
-- 
1.7.2.5


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH 3/4] dma: sh: provide a migration path for slave drivers to stop using .private
  2012-07-04 16:17   ` Guennadi Liakhovetski
@ 2012-07-11 21:55     ` Magnus Damm
  -1 siblings, 0 replies; 16+ messages in thread
From: Magnus Damm @ 2012-07-11 21:55 UTC (permalink / raw)
  To: Guennadi Liakhovetski
  Cc: Vinod Koul, linux-sh, linux-mmc, Chris Ball, linux-kernel, Paul Mundt

Hi Guennadi,

[CC Paul]

On Thu, Jul 5, 2012 at 1:17 AM, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> This patch extends the sh dmaengine driver to support the preferred channel
> selection and configuration method, instead of using the "private" field
> from struct dma_chan. We add a standard filter function to be used by
> slave drivers instead of implementing their own ones, and add support for
> the DMA_SLAVE_CONFIG control operation, which must accompany the new
> channel selection method. We still support the legacy .private channel
> allocation method to cater for a smooth driver migration.
>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> ---

Thanks for your efforts on this. Something that caught my eye in this
patch is this portion:

+bool shdma_chan_filter(struct dma_chan *chan, void *arg);

If we would use this function in our DMA Engine slave drivers (MMCIF,
SDHI, SCIF, FSI, SIU and so on) then wouldn't we add a strict
dependency on this symbol provided by this particular DMA Engine
driver implementation for the DMAC hardware (that your patch
modifies)?

And what do we do if we want to use the same DMA Engine slave driver
with a different DMA Engine driver implementation?

From my point of view, there must be some better way to not have such
tight dependencies between the DMA Engine slave consumer and the DMA
Engine driver. Not sure what that looks like though. This symbol
dependency is pretty far from great IMO.

Thanks,

/ magnus

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 3/4] dma: sh: provide a migration path for slave drivers to stop using .private
@ 2012-07-11 21:55     ` Magnus Damm
  0 siblings, 0 replies; 16+ messages in thread
From: Magnus Damm @ 2012-07-11 21:55 UTC (permalink / raw)
  To: Guennadi Liakhovetski
  Cc: Vinod Koul, linux-sh, linux-mmc, Chris Ball, linux-kernel, Paul Mundt

Hi Guennadi,

[CC Paul]

On Thu, Jul 5, 2012 at 1:17 AM, Guennadi Liakhovetski
<g.liakhovetski@gmx.de> wrote:
> This patch extends the sh dmaengine driver to support the preferred channel
> selection and configuration method, instead of using the "private" field
> from struct dma_chan. We add a standard filter function to be used by
> slave drivers instead of implementing their own ones, and add support for
> the DMA_SLAVE_CONFIG control operation, which must accompany the new
> channel selection method. We still support the legacy .private channel
> allocation method to cater for a smooth driver migration.
>
> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> ---

Thanks for your efforts on this. Something that caught my eye in this
patch is this portion:

+bool shdma_chan_filter(struct dma_chan *chan, void *arg);

If we would use this function in our DMA Engine slave drivers (MMCIF,
SDHI, SCIF, FSI, SIU and so on) then wouldn't we add a strict
dependency on this symbol provided by this particular DMA Engine
driver implementation for the DMAC hardware (that your patch
modifies)?

And what do we do if we want to use the same DMA Engine slave driver
with a different DMA Engine driver implementation?

>From my point of view, there must be some better way to not have such
tight dependencies between the DMA Engine slave consumer and the DMA
Engine driver. Not sure what that looks like though. This symbol
dependency is pretty far from great IMO.

Thanks,

/ magnus

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 3/4] dma: sh: provide a migration path for slave drivers to stop using .private
  2012-07-11 21:55     ` Magnus Damm
@ 2012-07-12  4:00       ` Paul Mundt
  -1 siblings, 0 replies; 16+ messages in thread
From: Paul Mundt @ 2012-07-12  4:00 UTC (permalink / raw)
  To: Magnus Damm
  Cc: Guennadi Liakhovetski, Vinod Koul, linux-sh, linux-mmc,
	Chris Ball, linux-kernel

On Thu, Jul 12, 2012 at 06:55:32AM +0900, Magnus Damm wrote:
> Hi Guennadi,
> 
> [CC Paul]
> 
> On Thu, Jul 5, 2012 at 1:17 AM, Guennadi Liakhovetski
> <g.liakhovetski@gmx.de> wrote:
> > This patch extends the sh dmaengine driver to support the preferred channel
> > selection and configuration method, instead of using the "private" field
> > from struct dma_chan. We add a standard filter function to be used by
> > slave drivers instead of implementing their own ones, and add support for
> > the DMA_SLAVE_CONFIG control operation, which must accompany the new
> > channel selection method. We still support the legacy .private channel
> > allocation method to cater for a smooth driver migration.
> >
> > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> > ---
> 
> Thanks for your efforts on this. Something that caught my eye in this
> patch is this portion:
> 
> +bool shdma_chan_filter(struct dma_chan *chan, void *arg);
> 
> If we would use this function in our DMA Engine slave drivers (MMCIF,
> SDHI, SCIF, FSI, SIU and so on) then wouldn't we add a strict
> dependency on this symbol provided by this particular DMA Engine
> driver implementation for the DMAC hardware (that your patch
> modifies)?
> 
> And what do we do if we want to use the same DMA Engine slave driver
> with a different DMA Engine driver implementation?
> 
> From my point of view, there must be some better way to not have such
> tight dependencies between the DMA Engine slave consumer and the DMA
> Engine driver. Not sure what that looks like though. This symbol
> dependency is pretty far from great IMO.
> 
I vaguely recall this coming up before, and it wasn't acceptable then
either.

We will by no means be adding driver-specific hooks in to other drivers
that really couldn't care less what the underlying DMA engine driving
them is.

We already have CPUs with different DMA engines that can be used by the
same drivers. As I said the last time, this needs to be fixed in the
dmaengine framework, period.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 3/4] dma: sh: provide a migration path for slave drivers to stop using .private
@ 2012-07-12  4:00       ` Paul Mundt
  0 siblings, 0 replies; 16+ messages in thread
From: Paul Mundt @ 2012-07-12  4:00 UTC (permalink / raw)
  To: Magnus Damm
  Cc: Guennadi Liakhovetski, Vinod Koul, linux-sh, linux-mmc,
	Chris Ball, linux-kernel

On Thu, Jul 12, 2012 at 06:55:32AM +0900, Magnus Damm wrote:
> Hi Guennadi,
> 
> [CC Paul]
> 
> On Thu, Jul 5, 2012 at 1:17 AM, Guennadi Liakhovetski
> <g.liakhovetski@gmx.de> wrote:
> > This patch extends the sh dmaengine driver to support the preferred channel
> > selection and configuration method, instead of using the "private" field
> > from struct dma_chan. We add a standard filter function to be used by
> > slave drivers instead of implementing their own ones, and add support for
> > the DMA_SLAVE_CONFIG control operation, which must accompany the new
> > channel selection method. We still support the legacy .private channel
> > allocation method to cater for a smooth driver migration.
> >
> > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> > ---
> 
> Thanks for your efforts on this. Something that caught my eye in this
> patch is this portion:
> 
> +bool shdma_chan_filter(struct dma_chan *chan, void *arg);
> 
> If we would use this function in our DMA Engine slave drivers (MMCIF,
> SDHI, SCIF, FSI, SIU and so on) then wouldn't we add a strict
> dependency on this symbol provided by this particular DMA Engine
> driver implementation for the DMAC hardware (that your patch
> modifies)?
> 
> And what do we do if we want to use the same DMA Engine slave driver
> with a different DMA Engine driver implementation?
> 
> From my point of view, there must be some better way to not have such
> tight dependencies between the DMA Engine slave consumer and the DMA
> Engine driver. Not sure what that looks like though. This symbol
> dependency is pretty far from great IMO.
> 
I vaguely recall this coming up before, and it wasn't acceptable then
either.

We will by no means be adding driver-specific hooks in to other drivers
that really couldn't care less what the underlying DMA engine driving
them is.

We already have CPUs with different DMA engines that can be used by the
same drivers. As I said the last time, this needs to be fixed in the
dmaengine framework, period.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 3/4] dma: sh: provide a migration path for slave drivers to stop using .private
  2012-07-12  4:00       ` Paul Mundt
@ 2012-07-12  8:34         ` Guennadi Liakhovetski
  -1 siblings, 0 replies; 16+ messages in thread
From: Guennadi Liakhovetski @ 2012-07-12  8:34 UTC (permalink / raw)
  To: Paul Mundt
  Cc: Magnus Damm, Vinod Koul, linux-sh, linux-mmc, Chris Ball, linux-kernel

Hi Paul, Magnus

On Thu, 12 Jul 2012, Paul Mundt wrote:

> On Thu, Jul 12, 2012 at 06:55:32AM +0900, Magnus Damm wrote:
> > Hi Guennadi,
> > 
> > [CC Paul]
> > 
> > On Thu, Jul 5, 2012 at 1:17 AM, Guennadi Liakhovetski
> > <g.liakhovetski@gmx.de> wrote:
> > > This patch extends the sh dmaengine driver to support the preferred channel
> > > selection and configuration method, instead of using the "private" field
> > > from struct dma_chan. We add a standard filter function to be used by
> > > slave drivers instead of implementing their own ones, and add support for
> > > the DMA_SLAVE_CONFIG control operation, which must accompany the new
> > > channel selection method. We still support the legacy .private channel
> > > allocation method to cater for a smooth driver migration.
> > >
> > > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> > > ---
> > 
> > Thanks for your efforts on this. Something that caught my eye in this
> > patch is this portion:
> > 
> > +bool shdma_chan_filter(struct dma_chan *chan, void *arg);
> > 
> > If we would use this function in our DMA Engine slave drivers (MMCIF,
> > SDHI, SCIF, FSI, SIU and so on) then wouldn't we add a strict
> > dependency on this symbol provided by this particular DMA Engine
> > driver implementation for the DMAC hardware (that your patch
> > modifies)?

This dependency is nothing new. Now all those drivers depend on shdma too, 
though, in a softer way - by using struct sh_dmae_slave. That struct is 
defined in include/linux/sh_dma.h and so we _could_ reuse it between 
several sh(-mobile) DMAC variants, but IIUC, there's currently no truly 
reliable way to make DMA slave drive drivers completely generic. And this 
will remain this way as long as DMA channel filtering is relying on an 
opaque argument, specific to each DMAC driver.

Russell has shown in a mail, how this hard dependency can be sort of 
eliminated by passing a string as a filter parameter. But then again - 
this _only_ works with drivers, that use this method. Similarly any non 
hardware-specific type could be used, e.g., an integer slave ID.

Moreover, I've been told explicitly, that exporting filter functions from 
respective DMAC drivers _is_ the correct way to use the current API...

> > And what do we do if we want to use the same DMA Engine slave driver
> > with a different DMA Engine driver implementation?
> > 
> > From my point of view, there must be some better way to not have such
> > tight dependencies between the DMA Engine slave consumer and the DMA
> > Engine driver. Not sure what that looks like though. This symbol
> > dependency is pretty far from great IMO.
> > 
> I vaguely recall this coming up before, and it wasn't acceptable then
> either.
> 
> We will by no means be adding driver-specific hooks in to other drivers
> that really couldn't care less what the underlying DMA engine driving
> them is.
> 
> We already have CPUs with different DMA engines that can be used by the
> same drivers. As I said the last time, this needs to be fixed in the
> dmaengine framework, period.

Sure, that's what my DMA mux-driver idea [1] is aiming to achieve.

Thanks
Guennadi

[1] http://article.gmane.org/gmane.linux.ports.arm.omap/80357
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH 3/4] dma: sh: provide a migration path for slave drivers to stop using .private
@ 2012-07-12  8:34         ` Guennadi Liakhovetski
  0 siblings, 0 replies; 16+ messages in thread
From: Guennadi Liakhovetski @ 2012-07-12  8:34 UTC (permalink / raw)
  To: Paul Mundt
  Cc: Magnus Damm, Vinod Koul, linux-sh, linux-mmc, Chris Ball, linux-kernel

Hi Paul, Magnus

On Thu, 12 Jul 2012, Paul Mundt wrote:

> On Thu, Jul 12, 2012 at 06:55:32AM +0900, Magnus Damm wrote:
> > Hi Guennadi,
> > 
> > [CC Paul]
> > 
> > On Thu, Jul 5, 2012 at 1:17 AM, Guennadi Liakhovetski
> > <g.liakhovetski@gmx.de> wrote:
> > > This patch extends the sh dmaengine driver to support the preferred channel
> > > selection and configuration method, instead of using the "private" field
> > > from struct dma_chan. We add a standard filter function to be used by
> > > slave drivers instead of implementing their own ones, and add support for
> > > the DMA_SLAVE_CONFIG control operation, which must accompany the new
> > > channel selection method. We still support the legacy .private channel
> > > allocation method to cater for a smooth driver migration.
> > >
> > > Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> > > ---
> > 
> > Thanks for your efforts on this. Something that caught my eye in this
> > patch is this portion:
> > 
> > +bool shdma_chan_filter(struct dma_chan *chan, void *arg);
> > 
> > If we would use this function in our DMA Engine slave drivers (MMCIF,
> > SDHI, SCIF, FSI, SIU and so on) then wouldn't we add a strict
> > dependency on this symbol provided by this particular DMA Engine
> > driver implementation for the DMAC hardware (that your patch
> > modifies)?

This dependency is nothing new. Now all those drivers depend on shdma too, 
though, in a softer way - by using struct sh_dmae_slave. That struct is 
defined in include/linux/sh_dma.h and so we _could_ reuse it between 
several sh(-mobile) DMAC variants, but IIUC, there's currently no truly 
reliable way to make DMA slave drive drivers completely generic. And this 
will remain this way as long as DMA channel filtering is relying on an 
opaque argument, specific to each DMAC driver.

Russell has shown in a mail, how this hard dependency can be sort of 
eliminated by passing a string as a filter parameter. But then again - 
this _only_ works with drivers, that use this method. Similarly any non 
hardware-specific type could be used, e.g., an integer slave ID.

Moreover, I've been told explicitly, that exporting filter functions from 
respective DMAC drivers _is_ the correct way to use the current API...

> > And what do we do if we want to use the same DMA Engine slave driver
> > with a different DMA Engine driver implementation?
> > 
> > From my point of view, there must be some better way to not have such
> > tight dependencies between the DMA Engine slave consumer and the DMA
> > Engine driver. Not sure what that looks like though. This symbol
> > dependency is pretty far from great IMO.
> > 
> I vaguely recall this coming up before, and it wasn't acceptable then
> either.
> 
> We will by no means be adding driver-specific hooks in to other drivers
> that really couldn't care less what the underlying DMA engine driving
> them is.
> 
> We already have CPUs with different DMA engines that can be used by the
> same drivers. As I said the last time, this needs to be fixed in the
> dmaengine framework, period.

Sure, that's what my DMA mux-driver idea [1] is aiming to achieve.

Thanks
Guennadi

[1] http://article.gmane.org/gmane.linux.ports.arm.omap/80357
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2012-07-12  8:35 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-04 16:17 [PATCH 0/4] dma: sh: stop using .private Guennadi Liakhovetski
2012-07-04 16:17 ` Guennadi Liakhovetski
2012-07-04 16:17 ` [PATCH 1/4] dmaengine: shdma: prepare to stop using struct dma_chan::private Guennadi Liakhovetski
2012-07-04 16:17   ` Guennadi Liakhovetski
2012-07-04 16:17 ` [PATCH 2/4] dma: sh: use an integer slave ID to improve API compatibility Guennadi Liakhovetski
2012-07-04 16:17   ` Guennadi Liakhovetski
2012-07-04 16:17 ` [PATCH 3/4] dma: sh: provide a migration path for slave drivers to stop using .private Guennadi Liakhovetski
2012-07-04 16:17   ` Guennadi Liakhovetski
2012-07-11 21:55   ` Magnus Damm
2012-07-11 21:55     ` Magnus Damm
2012-07-12  4:00     ` Paul Mundt
2012-07-12  4:00       ` Paul Mundt
2012-07-12  8:34       ` Guennadi Liakhovetski
2012-07-12  8:34         ` Guennadi Liakhovetski
2012-07-04 16:17 ` [PATCH 4/4] mmc: sh_mmcif: switch to the new DMA channel allocation and configuration Guennadi Liakhovetski
2012-07-04 16:17   ` Guennadi Liakhovetski

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.