To use DMA generic APIs for Samsung DMA
Subsystems (10)
v4 cover To use DMA generic APIs for Samsung DMA
This patchset adds support DMA generic APIs for Samsung DMA and is re-sent by the request of DMA maintainer, Vinod Koul.
V4 has the changes about 3 patches from V3.
Changes from V3:
- Divided '[03/13 patch] DMA: PL330: Add DMA capabilites' on V3 patchset into two patches.
- One is '03/14 patch' for supporting DMA_SLAVE_CONFIG command.
- Another is '04/14 patch' for supporting DMA_CYCLIC capability.
- Code clean-up
- Remove unnecessary vairable referance on '01/14 patch'.
- Remove redunancy code on '06/14 patch'
[PATCH V4 01/14] DMA: PL330: Add support runtime PM for PL330 DMAC [PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver
[PATCH V4 03/14] DMA: PL330: Support DMA_SLAVE_CONFIG command
[PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability
[PATCH V4 05/14] ARM: SAMSUNG: Update to use PL330-DMA driver
[PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
[PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330 driver
[PATCH V4 08/14] ARM: S5PV210: Use generic DMA PL330 driver
[PATCH V4 09/14] ARM: S5PC100: Use generic DMA PL330 driver
[PATCH V4 10/14] ARM: S5P64X0: Use generic DMA PL330 driver
[PATCH V4 11/14] ARM: SAMSUNG: Remove S3C-PL330-DMA driver
[PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
[PATCH V4 13/14] ASoC: Samsung: Update DMA interface
[PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
PATCH v4 1/14 DMA: PL330: Add support runtime PM for PL330 DMAC
--- drivers/dma/pl330.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 73 insertions(+), 2 deletions(-)
drivers/dma/pl330.c +73 -2
@@ -17,6 +17,7 @@#include <linux/interrupt.h> #include <linux/amba/bus.h> #include <linux/amba/pl330.h> +#include <linux/pm_runtime.h> #define NR_DEFAULT_DESC 16
@@ -83,6 +84,8 @@ struct dma_pl330_dmac {/* Peripheral channels connected to this DMAC */ struct dma_pl330_chan peripherals[0 ];/* keep at end */ + +struct clk *clk; };struct dma_pl330_desc {
@@ -696,6 +699,30 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) goto probe_err1; } + pdmac->clk =clk_get (&adev->dev,"dma" ); +if (IS_ERR (pdmac->clk)) { +dev_err (&adev->dev,"Cannot get operation clock.\n" ); + ret = -EINVAL ; + goto probe_err1; + } + +amba_set_drvdata (adev, pdmac); + +#ifdef CONFIG_PM_RUNTIME +/* to use the runtime PM helper functions */ +pm_runtime_enable (&adev->dev); + +/* enable the power domain */ +if (pm_runtime_get_sync (&adev->dev)) { +dev_err (&adev->dev,"failed to get runtime pm\n" ); + ret = -ENODEV ; + goto probe_err1; + } +#else +/* enable dma clk */ +clk_enable (pdmac->clk); +#endif + irq = adev->irq[0 ]; ret =request_irq (irq, pl330_irq_handler,0 ,dev_name (&adev->dev), pi);
@@ -763,8 +790,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) goto probe_err4; } -amba_set_drvdata (adev, pdmac); -dev_info (&adev->dev,"Loaded driver for PL330 DMAC-%d\n" , adev->periphid); dev_info(&adev->dev,
@@ -825,6 +850,13 @@ static int __devexit pl330_remove(struct amba_device *adev) res = &adev->res;release_mem_region (res->start,resource_size (res)); +#ifdef CONFIG_PM_RUNTIME +pm_runtime_put (&adev->dev); +pm_runtime_disable (&adev->dev); +#else +clk_disable (pdmac->clk); +#endif +kfree (pdmac);return 0 ;
@@ -838,10 +870,49 @@ static struct amba_id pl330_ids[] = { { 0, 0 }, }; +#ifdef CONFIG_PM_RUNTIME +static int pl330_runtime_suspend (struct device *dev) +{ +struct dma_pl330_dmac *pdmac =dev_get_drvdata (dev); + +if (!pdmac) { +dev_err (dev,"failed to get dmac\n" ); +return -ENODEV ; + } + +clk_disable (pdmac->clk); + +return 0 ; +} + +static int pl330_runtime_resume (struct device *dev) +{ +struct dma_pl330_dmac *pdmac =dev_get_drvdata (dev); + +if (!pdmac) { +dev_err (dev,"failed to get dmac\n" ); +return -ENODEV ; + } + +clk_enable (pdmac->clk); + +return 0 ; +} +#else +#define pl330_runtime_suspend NULL +#define pl330_runtime_resume NULL +#endif /* CONFIG_PM_RUNTIME */ + +static const struct dev_pm_ops pl330_pm_ops = { + .runtime_suspend = pl330_runtime_suspend, + .runtime_resume = pl330_runtime_resume, +}; +static struct amba_driver pl330_driver = { .drv = { .owner =THIS_MODULE , .name ="dma-pl330" , + .pm = &pl330_pm_ops, }, .id_table = pl330_ids, .probe = pl330_probe,
Signature · 1 line
1.7.1
PATCH v4 1/14 DMA: PL330: Add support runtime PM for PL330 DMAC
Quoted 120 lines · Boojin Kim
Signed-off-by Boojin Kim <[email protected]>--- drivers/dma/pl330.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 73 insertions(+), 2 deletions(-)drivers/dma/pl330.c +70
-2@@ -17,6 +17,7 @@#include <linux/interrupt.h> #include <linux/amba/bus.h> #include <linux/amba/pl330.h> +#include <linux/pm_runtime.h> #define NR_DEFAULT_DESC 16@@ -83,6 +84,8 @@ struct dma_pl330_dmac {/* Peripheral channels connected to this DMAC */ struct dma_pl330_chan peripherals[0 ];/* keep at end */ + +struct clk *clk; };struct dma_pl330_desc {@@ -696,6 +699,30 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) goto probe_err1; } + pdmac->clk =clk_get (&adev->dev,"dma" ); +if (IS_ERR (pdmac->clk)) { +dev_err (&adev->dev,"Cannot get operation clock.\n" ); + ret = -EINVAL ; + goto probe_err1; + } + +amba_set_drvdata (adev, pdmac); + +#ifdef CONFIG_PM_RUNTIME +/* to use the runtime PM helper functions */ +pm_runtime_enable (&adev->dev); + +/* enable the power domain */ +if (pm_runtime_get_sync (&adev->dev)) { +dev_err (&adev->dev,"failed to get runtime pm\n" ); + ret = -ENODEV ; + goto probe_err1; + } +#else +/* enable dma clk */ +clk_enable (pdmac->clk); +#endif + irq = adev->irq[0 ]; ret =request_irq (irq, pl330_irq_handler,0 ,dev_name (&adev->dev), pi);@@ -763,8 +790,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) goto probe_err4; } -amba_set_drvdata (adev, pdmac); -dev_info (&adev->dev,"Loaded driver for PL330 DMAC-%d\n" , adev->periphid); dev_info(&adev->dev,@@ -825,6 +850,13 @@ static int __devexit pl330_remove(struct amba_device *adev) res = &adev->res;release_mem_region (res->start,resource_size (res)); +#ifdef CONFIG_PM_RUNTIME +pm_runtime_put (&adev->dev); +pm_runtime_disable (&adev->dev); +#else +clk_disable (pdmac->clk); +#endif +kfree (pdmac);return 0 ;@@ -838,10 +870,49 @@ static struct amba_id pl330_ids[] = { { 0, 0 }, }; +#ifdef CONFIG_PM_RUNTIME +static int pl330_runtime_suspend (struct device *dev) +{ +struct dma_pl330_dmac *pdmac =dev_get_drvdata (dev); + +if (!pdmac) { +dev_err (dev,"failed to get dmac\n" ); +return -ENODEV ; + } + +clk_disable (pdmac->clk); + +return 0 ; +} + +static int pl330_runtime_resume (struct device *dev) +{ +struct dma_pl330_dmac *pdmac =dev_get_drvdata (dev); + +if (!pdmac) { +dev_err (dev,"failed to get dmac\n" ); +return -ENODEV ; + } + +clk_enable (pdmac->clk); + +return 0 ; +} +#else +#define pl330_runtime_suspend NULL +#define pl330_runtime_resume NULL +#endif /* CONFIG_PM_RUNTIME */ + +static const struct dev_pm_ops pl330_pm_ops = { + .runtime_suspend = pl330_runtime_suspend, + .runtime_resume = pl330_runtime_resume,
drivers/dma/pl330.c static struct amba_id pl330_ids[] = { · line 918
Quoted 10 lines
drivers/dma/pl330.c +3
-0+}; +static struct amba_driver pl330_driver = { .drv = { .owner =THIS_MODULE , .name ="dma-pl330" , + .pm = &pl330_pm_ops, }, .id_table = pl330_ids, .probe = pl330_probe,
I have a question for runtime PM of PL330 DMAC
This patch support runtime PM for PL330 DMAC, but the clock of "dma" is always on. If the clock of "dma" is always on, additional power(10mA) is consumed. I tested it.
I think that the PL330 DMAC only turn on the clock of "dma" when using DMA.
Thanks,
Chanwoo Choi
PATCH v4 2/14 DMA: PL330: Update PL330 DMA API driver
In reply to Boojin KimThis patch updates following 3 items.
1. Removes unneccessary code.
2. Add AMBA, PL330 configuration
3. Change the meaning of 'peri_id' variable from PL330 event number to specific dma id by user.
--- drivers/dma/Kconfig | 3 ++- drivers/dma/pl330.c | 31 ++++++++++++++++--------------- include/linux/amba/pl330.h | 2 +- 3 files changed, 19 insertions(+), 17 deletions(-)
drivers/dma/Kconfig +2 -1
@@ -193,7 +193,8 @@ config ARCH_HAS_ASYNC_TX_FIND_CHANNEL config PL330_DMA tristate "DMA API Driver for PL330" select DMA_ENGINE - depends on PL330 + depends on ARM_AMBA + select PL330 help Select if your platform has one or more PL330 DMACs. You need to provide platform specific settings via
drivers/dma/pl330.c +16 -15
@@ -455,7 +455,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)async_tx_ack (&desc->txd); desc->req.rqtype = peri->rqtype; - desc->req.peri = peri->peri_id; + desc->req.peri = pch->chan.chan_id;dma_async_tx_descriptor_init (&desc->txd, &pch->chan);
@@ -577,7 +577,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,struct dma_pl330_peri *peri = chan->private;struct scatterlist *sg;unsigned long flags; -int i, burst_size; +int i;dma_addr_t addr;if (unlikely (!pch || !sgl || !sg_len))
@@ -594,7 +594,6 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, } addr = peri->fifo_addr; - burst_size = peri->burst_sz; first =NULL ;
@@ -642,7 +641,7 @@ pl330_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, sg_dma_address(sg), addr, sg_dma_len(sg)); } - desc->rqcfg.brst_size = burst_size; + desc->rqcfg.brst_size = peri->burst_sz; desc->rqcfg.brst_len =1 ; }
@@ -748,17 +747,19 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)struct dma_pl330_peri *peri = &pdat->peri[i]; pch = &pdmac->peripherals[i]; -switch (peri->rqtype) { -case MEMTOMEM : -dma_cap_set (DMA_MEMCPY , pd->cap_mask); -break ; -case MEMTODEV : -case DEVTOMEM : -dma_cap_set (DMA_SLAVE , pd->cap_mask); -break ; -default : -dev_err (&adev->dev,"DEVTODEV Not Supported\n" ); -continue ; +if (peri) { +switch (peri->rqtype) { +case MEMTOMEM : +dma_cap_set (DMA_MEMCPY , pd->cap_mask); +break ; +case MEMTODEV : +case DEVTOMEM : +dma_cap_set (DMA_SLAVE , pd->cap_mask); +break ; +default : +dev_err (&adev->dev,"DEVTODEV Not Supported\n" ); +continue ; + } }INIT_LIST_HEAD (&pch->work_list);
include/linux/amba/pl330.h +1 -1
@@ -19,7 +19,7 @@ struct dma_pl330_peri {* Peri_Req i/f of the DMAC that is * peripheral could be reached from. */ -u8 peri_id;/* {0, 31} */ +u8 peri_id;/* specific dma id */ enum pl330_reqtype rqtype;/* For M->D and D->M Channels */
Signature · 1 line
1.7.1
PATCH v4 2/14 DMA: PL330: Update PL330 DMA API driver
drivers/dma/pl330.c static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch) · line 458
Quoted 10 lines · Boojin Kim
drivers/dma/pl330.c +1
-1@@ -455,7 +455,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch) ? ? ? ?async_tx_ack(&desc->txd); ? ? ? ?desc->req.rqtype = peri->rqtype; - ? ? ? desc->req.peri = peri->peri_id; + ? ? ? desc->req.peri = pch->chan.chan_id;
Btw, I plan to revert this if my patch is accepted that proposes to free chan_id solely for use by DMAC drivers(which we should employ to pass paltform assigned channel ID to client drivers)
Quoted 19 lines
drivers/dma/pl330.c +4
-11@@ -748,17 +747,19 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) ? ? ? ? ? ? ? ?struct dma_pl330_peri *peri = &pdat->peri[i]; ? ? ? ? ? ? ? ?pch = &pdmac->peripherals[i]; - ? ? ? ? ? ? ? switch (peri->rqtype) { - ? ? ? ? ? ? ? case MEMTOMEM: - ? ? ? ? ? ? ? ? ? ? ? dma_cap_set(DMA_MEMCPY, pd->cap_mask); - ? ? ? ? ? ? ? ? ? ? ? break; - ? ? ? ? ? ? ? case MEMTODEV: - ? ? ? ? ? ? ? case DEVTOMEM: - ? ? ? ? ? ? ? ? ? ? ? dma_cap_set(DMA_SLAVE, pd->cap_mask); - ? ? ? ? ? ? ? ? ? ? ? break; - ? ? ? ? ? ? ? default: - ? ? ? ? ? ? ? ? ? ? ? dev_err(&adev->dev, "DEVTODEV Not Supported\n"); - ? ? ? ? ? ? ? ? ? ? ? continue; + ? ? ? ? ? ? ? if (peri) { + ? ? ? ? ? ? ? ? ? ? ? switch (peri->rqtype) { + ? ? ? ? ? ? ? ? ? ? ? case MEMTOMEM: + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dma_cap_set(DMA_MEMCPY, pd->cap_mask);
drivers/dma/pl330.c pl330_probe(struct amba_device *adev, const struct amba_id *id) · line 763
Quoted 10 lines
drivers/dma/pl330.c +9
-0+ ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break; + ? ? ? ? ? ? ? ? ? ? ? case MEMTODEV: + ? ? ? ? ? ? ? ? ? ? ? case DEVTOMEM: + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dma_cap_set(DMA_SLAVE, pd->cap_mask); + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break; + ? ? ? ? ? ? ? ? ? ? ? default: + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? dev_err(&adev->dev, "DEVTODEV Not Supported\n"); + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? continue; + ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ?}
If you pass platform data correctly, you don't need to check against NULL peri.
PATCH v4 2/14 DMA: PL330: Update PL330 DMA API driver
Quoted 54 lines
-----Original Message-----
From: Jassi Brar [mailto:jassisinghbrar at gmail.com]
Sent: Monday, July 25, 2011 5:58 PM
To: Boojin Kim
Cc: linux-arm-kernel at lists.infradead.org; linux-samsung-soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant Likely; Mark Brown
Subject: Re: [PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driverdrivers/dma/pl330.c static struct dma_pl330_desc *pl330_get_desc(struct
Quoted 5 lines · Boojin Kim
drivers/dma/pl330.c +0
-0@@ -455,7 +455,7 @@ static struct dma_pl330_desc *pl330_get_desc(struct
dma_pl330_chan*pch)drivers/dma/pl330.c static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch) · line 458
Quoted 5 lines
drivers/dma/pl330.c +1
-1async_tx_ack (&desc->txd); desc->req.rqtype = peri->rqtype; - desc->req.peri = peri->peri_id; + desc->req.peri = pch->chan.chan_id;Btw, I plan to revert this if my patch is accepted that proposes to free
chan_idsolely for use by DMAC drivers(which we should employ to pass paltform assigned channel ID to client drivers)drivers/dma/pl330.c pl330_probe(struct amba_device *adev, const struct
Quoted 1 line
drivers/dma/pl330.c +0
-0@@ -748,17 +747,19 @@ pl330_probe(struct amba_device *adev, const struct
amba_id*id)Quoted 15 lines
drivers/dma/pl330.c +1
-11struct dma_pl330_peri *peri = &pdat->peri[i]; pch = &pdmac->peripherals[i]; -switch (peri->rqtype) { -case MEMTOMEM : -dma_cap_set (DMA_MEMCPY , pd->cap_mask); -break ; -case MEMTODEV : -case DEVTOMEM : -dma_cap_set (DMA_SLAVE , pd->cap_mask); -break ; -default : -dev_err (&adev->dev,"DEVTODEV Not Supported\n" ); -continue ; +if (peri) {drivers/dma/pl330.c pl330_probe(struct amba_device *adev, const struct amba_id *id)
Quoted 10 lines
drivers/dma/pl330.c +10
-0+switch (peri->rqtype) { +case MEMTOMEM : +dma_cap_set (DMA_MEMCPY , pd->cap_mask); +break ; +case MEMTODEV : +case DEVTOMEM : +dma_cap_set (DMA_SLAVE , pd->cap_mask); +break ; +default : + dev_err(&adev->dev, "DEVTODEV Not
Quoted 6 lines
Supported\n");
drivers/dma/pl330.c pl330_probe(struct amba_device *adev, const struct amba_id *id) · line 763
Quoted 3 lines
drivers/dma/pl330.c +2
-0+continue ; + } }If you pass platform data correctly, you don't need to check against NULL peri.
Ok, It may be excessive error check. I will remove this point.
PATCH v4 3/14 DMA: PL330: Support DMA_SLAVE_CONFIG command
In reply to Boojin KimThis patch adds support DMA_SLAVE_CONFIG command.
--- drivers/dma/pl330.c | 53 +++++++++++++++++++++++++++++++++++++------------- 1 files changed, 39 insertions(+), 14 deletions(-)
drivers/dma/pl330.c +39 -14
@@ -256,25 +256,50 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)static int pl330_control (struct dma_chan *chan,enum dma_ctrl_cmd cmd,unsigned long arg) {struct dma_pl330_chan *pch =to_pchan (chan); -struct dma_pl330_desc *desc; +struct dma_pl330_desc *desc, *_dt;unsigned long flags; +struct dma_pl330_dmac *pdmac = pch->dmac; +struct dma_slave_config *slave_config; +struct dma_pl330_peri *peri; +LIST_HEAD (list); -/* Only supports DMA_TERMINATE_ALL */ -if (cmd !=DMA_TERMINATE_ALL ) -return -ENXIO ; - -spin_lock_irqsave (&pch->lock, flags); - -/* FLUSH the PL330 Channel thread */ -pl330_chan_ctrl (pch->pl330_chid,PL330_OP_FLUSH ); +switch (cmd) { +case DMA_TERMINATE_ALL : +spin_lock_irqsave (&pch->lock, flags); -/* Mark all desc done */ -list_for_each_entry (desc, &pch->work_list, node) - desc->status =DONE ; +/* FLUSH the PL330 Channel thread */ +pl330_chan_ctrl (pch->pl330_chid,PL330_OP_FLUSH ); -spin_unlock_irqrestore (&pch->lock, flags); +/* Mark all desc done */ +list_for_each_entry_safe (desc, _dt, &pch->work_list , node) { + desc->status =DONE ; + pch->completed = desc->txd.cookie; +list_move_tail (&desc->node, &list); + } -pl330_tasklet ((unsigned long ) pch); +list_splice_tail_init (&list, &pdmac->desc_pool); +spin_unlock_irqrestore (&pch->lock, flags); +break ; +case DMA_SLAVE_CONFIG : + slave_config = (struct dma_slave_config *)arg; + peri = pch->chan.private; + +if (slave_config->direction ==DMA_TO_DEVICE ) { +if (slave_config->dst_addr) + peri->fifo_addr = slave_config->dst_addr; +if (slave_config->dst_addr_width) + peri->burst_sz =__ffs (slave_config->dst_addr_width); + }else if (slave_config->direction ==DMA_FROM_DEVICE ) { +if (slave_config->src_addr) + peri->fifo_addr = slave_config->src_addr; +if (slave_config->src_addr_width) + peri->burst_sz =__ffs (slave_config->src_addr_width); + } +break ; +default : +dev_err (pch->dmac->pif.dev,"Not supported command.\n" ); +return -ENXIO ; + }return 0 ; }
Signature · 1 line
1.7.1
PATCH v4 3/14 DMA: PL330: Support DMA_SLAVE_CONFIG command
Quoted 52 lines · Boojin Kim
This patch adds support
DMA_SLAVE_CONFIGcommand.Signed-off-by Boojin Kim <[email protected]>--- drivers/dma/pl330.c | 53 +++++++++++++++++++++++++++++++++++++------------- 1 files changed, 39 insertions(+), 14 deletions(-)drivers/dma/pl330.c +18
-14@@ -256,25 +256,50 @@ static int pl330_alloc_chan_resources(struct dma_chan *chan)static int pl330_control (struct dma_chan *chan,enum dma_ctrl_cmd cmd,unsigned long arg) {struct dma_pl330_chan *pch =to_pchan (chan); -struct dma_pl330_desc *desc; +struct dma_pl330_desc *desc, *_dt;unsigned long flags; +struct dma_pl330_dmac *pdmac = pch->dmac; +struct dma_slave_config *slave_config; +struct dma_pl330_peri *peri; +LIST_HEAD (list); -/* Only supports DMA_TERMINATE_ALL */ -if (cmd !=DMA_TERMINATE_ALL ) -return -ENXIO ; - -spin_lock_irqsave (&pch->lock, flags); - -/* FLUSH the PL330 Channel thread */ -pl330_chan_ctrl (pch->pl330_chid,PL330_OP_FLUSH ); +switch (cmd) { +case DMA_TERMINATE_ALL : +spin_lock_irqsave (&pch->lock, flags); -/* Mark all desc done */ -list_for_each_entry (desc, &pch->work_list, node) - desc->status =DONE ; +/* FLUSH the PL330 Channel thread */ +pl330_chan_ctrl (pch->pl330_chid,PL330_OP_FLUSH ); -spin_unlock_irqrestore (&pch->lock, flags); +/* Mark all desc done */ +list_for_each_entry_safe (desc, _dt, &pch->work_list , node) { + desc->status =DONE ; + pch->completed = desc->txd.cookie; +list_move_tail (&desc->node, &list); + } -pl330_tasklet ((unsigned long ) pch); +list_splice_tail_init (&list, &pdmac->desc_pool); +spin_unlock_irqrestore (&pch->lock, flags);
drivers/dma/pl330.c static int pl330_alloc_chan_resources(struct dma_chan *chan) · line 291
Quoted 10 lines
drivers/dma/pl330.c +10
-0+break ; +case DMA_SLAVE_CONFIG : + slave_config = (struct dma_slave_config *)arg; + peri = pch->chan.private; + +if (slave_config->direction ==DMA_TO_DEVICE ) { +if (slave_config->dst_addr) + peri->fifo_addr = slave_config->dst_addr; +if (slave_config->dst_addr_width) + peri->burst_sz =__ffs (slave_config->dst_addr_width);
This doesn't sound right, why can't you use xxx_maxburst field instead?
drivers/dma/pl330.c static int pl330_alloc_chan_resources(struct dma_chan *chan) · line 296
Quoted 5 lines
drivers/dma/pl330.c +5
-0+ }else if (slave_config->direction ==DMA_FROM_DEVICE ) { +if (slave_config->src_addr) + peri->fifo_addr = slave_config->src_addr; +if (slave_config->src_addr_width) + peri->burst_sz =__ffs (slave_config->src_addr_width);
ditto...
Quoted 9 lines
drivers/dma/pl330.c +6
-0+ } +break ; +default : +dev_err (pch->dmac->pif.dev,"Not supported command.\n" ); +return -ENXIO ; + }return 0 ; }
Signature · 2 lines
~Vinod Koul Intel Corp.
PATCH v4 3/14 DMA: PL330: Support DMA_SLAVE_CONFIG command
Vinod Koul Wrote:
Quoted 62 lines
Sent: Monday, July 25, 2011 7:27 PM
To: Boojin Kim
Cc: vinod.koul at intel.com; linux-arm-kernel at lists.infradead.org; linux- samsung-soc at vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely; Mark Brown; Dan Williams
Subject: Re: [PATCH V4 03/14] DMA: PL330: SupportDMA_SLAVE_CONFIGcommandQuoted 5 lines · Boojin Kim
This patch adds support
DMA_SLAVE_CONFIGcommand.Signed-off-by Boojin Kim <[email protected]>--- drivers/dma/pl330.c | 53 +++++++++++++++++++++++++++++++++++++-------------
drivers/dma/pl330.c static int pl330_alloc_chan_resources(struct
Quoted 7 lines
1 files changed, 39 insertions(+), 14 deletions(-)drivers/dma/pl330.c +0
-0@@ -256,25 +256,50 @@ static int pl330_alloc_chan_resources(struct
dma_chan*chan)drivers/dma/pl330.c static int pl330_alloc_chan_resources(struct · line 256
Quoted 1 line
drivers/dma/pl330.c +0
-0static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmdcmd, unsigned long arg)
Quoted 21 lines
drivers/dma/pl330.c +8
-9{struct dma_pl330_chan *pch =to_pchan (chan); -struct dma_pl330_desc *desc; +struct dma_pl330_desc *desc, *_dt;unsigned long flags; +struct dma_pl330_dmac *pdmac = pch->dmac; +struct dma_slave_config *slave_config; +struct dma_pl330_peri *peri; +LIST_HEAD (list); -/* Only supports DMA_TERMINATE_ALL */ -if (cmd !=DMA_TERMINATE_ALL ) -return -ENXIO ; - -spin_lock_irqsave (&pch->lock, flags); - -/* FLUSH the PL330 Channel thread */ -pl330_chan_ctrl (pch->pl330_chid,PL330_OP_FLUSH ); +switch (cmd) { +case DMA_TERMINATE_ALL : +spin_lock_irqsave (&pch->lock, flags);drivers/dma/pl330.c static int pl330_alloc_chan_resources(struct dma_chan *chan)
Quoted 10 lines
drivers/dma/pl330.c +4
-4-/* Mark all desc done */ -list_for_each_entry (desc, &pch->work_list, node) - desc->status =DONE ; +/* FLUSH the PL330 Channel thread */ +pl330_chan_ctrl (pch->pl330_chid,PL330_OP_FLUSH ); -spin_unlock_irqrestore (&pch->lock, flags); +/* Mark all desc done */ +list_for_each_entry_safe (desc, _dt, &pch->work_list , node){
Quoted 5 lines
drivers/dma/pl330.c +4
-0+ desc->status =DONE ; + pch->completed = desc->txd.cookie; +list_move_tail (&desc->node, &list); + }
Quoted 15 lines
Quoted 4 lines
drivers/dma/pl330.c +3
-1-pl330_tasklet ((unsigned long ) pch); +list_splice_tail_init (&list, &pdmac->desc_pool); +spin_unlock_irqrestore (&pch->lock, flags); +break ;drivers/dma/pl330.c static int pl330_alloc_chan_resources(struct dma_chan *chan)
Quoted 10 lines
drivers/dma/pl330.c +9
-0+case DMA_SLAVE_CONFIG : + slave_config = (struct dma_slave_config *)arg; + peri = pch->chan.private; + +if (slave_config->direction ==DMA_TO_DEVICE ) { +if (slave_config->dst_addr) + peri->fifo_addr = slave_config->dst_addr; +if (slave_config->dst_addr_width) + peri->burst_sz =__ffs (slave_config- dst_addr_width);This doesn't sound right, why can't you use
xxx_maxburstfield instead?
Can you explain the problem in more detail?
Do you mean that 'xxx_maxburst' takes place of 'xxx_addr_width' or __ffs() isn't proper here?
Additionally, I will modify this code to consider '_maxburst' field.
Quoted 21 lines
drivers/dma/pl330.c static int pl330_alloc_chan_resources(struct dma_chan *chan)
Quoted 7 lines
drivers/dma/pl330.c +5
-0+ }else if (slave_config->direction ==DMA_FROM_DEVICE ) { +if (slave_config->src_addr) + peri->fifo_addr = slave_config->src_addr; +if (slave_config->src_addr_width) + peri->burst_sz =__ffs (slave_config- src_addr_width);ditto...
Quoted 9 lines
drivers/dma/pl330.c +6
-0+ } +break ; +default : +dev_err (pch->dmac->pif.dev,"Not supported command.\n" ); +return -ENXIO ; + }return 0;
}--
~Vinod Koul
Intel Corp.
PATCH v4 3/14 DMA: PL330: Support DMA_SLAVE_CONFIG command
Quoted 78 lines · Boojin Kim
Vinod Koul Wrote:
Quoted 62 lines
Sent: Monday, July 25, 2011 7:27 PM
To: Boojin Kim
Cc: vinod.koul at intel.com; linux-arm-kernel at lists.infradead.org; linux- samsung-soc at vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely; Mark Brown; Dan Williams
Subject: Re: [PATCH V4 03/14] DMA: PL330: SupportDMA_SLAVE_CONFIGcommandQuoted 5 lines · Boojin Kim
This patch adds support
DMA_SLAVE_CONFIGcommand.Signed-off-by Boojin Kim <[email protected]>--- drivers/dma/pl330.c | 53 +++++++++++++++++++++++++++++++++++++-------------
drivers/dma/pl330.c static int pl330_alloc_chan_resources(struct
Quoted 7 lines
1 files changed, 39 insertions(+), 14 deletions(-)drivers/dma/pl330.c +0
-0@@ -256,25 +256,50 @@ static int pl330_alloc_chan_resources(struct
dma_chan*chan)drivers/dma/pl330.c static int pl330_alloc_chan_resources(struct · line 256
Quoted 1 line
drivers/dma/pl330.c +0
-0static int pl330_control(struct dma_chan *chan, enum dma_ctrl_cmdcmd, unsigned long arg)
Quoted 21 lines
drivers/dma/pl330.c +8
-9{struct dma_pl330_chan *pch =to_pchan (chan); -struct dma_pl330_desc *desc; +struct dma_pl330_desc *desc, *_dt;unsigned long flags; +struct dma_pl330_dmac *pdmac = pch->dmac; +struct dma_slave_config *slave_config; +struct dma_pl330_peri *peri; +LIST_HEAD (list); -/* Only supports DMA_TERMINATE_ALL */ -if (cmd !=DMA_TERMINATE_ALL ) -return -ENXIO ; - -spin_lock_irqsave (&pch->lock, flags); - -/* FLUSH the PL330 Channel thread */ -pl330_chan_ctrl (pch->pl330_chid,PL330_OP_FLUSH ); +switch (cmd) { +case DMA_TERMINATE_ALL : +spin_lock_irqsave (&pch->lock, flags);drivers/dma/pl330.c static int pl330_alloc_chan_resources(struct dma_chan *chan)
Quoted 10 lines
drivers/dma/pl330.c +4
-4-/* Mark all desc done */ -list_for_each_entry (desc, &pch->work_list, node) - desc->status =DONE ; +/* FLUSH the PL330 Channel thread */ +pl330_chan_ctrl (pch->pl330_chid,PL330_OP_FLUSH ); -spin_unlock_irqrestore (&pch->lock, flags); +/* Mark all desc done */ +list_for_each_entry_safe (desc, _dt, &pch->work_list , node){
Quoted 5 lines
drivers/dma/pl330.c +4
-0+ desc->status =DONE ; + pch->completed = desc->txd.cookie; +list_move_tail (&desc->node, &list); + }Quoted 15 lines
Quoted 4 lines
drivers/dma/pl330.c +3
-1-pl330_tasklet ((unsigned long ) pch); +list_splice_tail_init (&list, &pdmac->desc_pool); +spin_unlock_irqrestore (&pch->lock, flags); +break ;drivers/dma/pl330.c static int pl330_alloc_chan_resources(struct dma_chan *chan)
Quoted 10 lines
drivers/dma/pl330.c +9
-0+case DMA_SLAVE_CONFIG : + slave_config = (struct dma_slave_config *)arg; + peri = pch->chan.private; + +if (slave_config->direction ==DMA_TO_DEVICE ) { +if (slave_config->dst_addr) + peri->fifo_addr = slave_config->dst_addr; +if (slave_config->dst_addr_width) + peri->burst_sz =__ffs (slave_config- dst_addr_width);This doesn't sound right, why can't you use
xxx_maxburstfield instead?
Quoted 5 lines
Can you explain the problem in more detail?
Do you mean that 'xxx_maxburst' takes place of 'xxx_addr_width' or__ffs()isn't proper here?Additionally, I will modify this code to consider '
_maxburst' field.
__ffs is okay and sensible.
I meant you should use proper fields for passing info, which in this case would be dst_maxburst for specifying destination burst sizes
Signature · 2 lines
~Vinod Koul Intel Corp.
PATCH v4 3/14 DMA: PL330: Support DMA_SLAVE_CONFIG command
Vinod Koul Wrote:
Quoted 96 lines
Sent: Monday, July 25, 2011 10:48 PM
To: Boojin Kim
Cc: vinod.koul at intel.com; linux-arm-kernel at lists.infradead.org; linux- samsung-soc at vger.kernel.org; 'Kukjin Kim'; 'Jassi Brar'; 'Grant Likely'; 'Mark Brown'; 'Dan Williams'
Subject: RE: [PATCH V4 03/14] DMA: PL330: SupportDMA_SLAVE_CONFIGcommandQuoted 4 lines · Boojin Kim
Vinod Koul Wrote:
Quoted 3 lines
Sent: Monday, July 25, 2011 7:27 PM
To: Boojin Kim
Cc: vinod.koul at intel.com; linux-arm-kernel at lists.infradead.org;linux-
Quoted 11 lines
Quoted 11 lines
samsung-soc at vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely; Mark Brown; Dan Williams
Subject: Re: [PATCH V4 03/14] DMA: PL330: SupportDMA_SLAVE_CONFIGcommandQuoted 5 lines · Boojin Kim
This patch adds support
DMA_SLAVE_CONFIGcommand.Signed-off-by Boojin Kim <[email protected]>--- drivers/dma/pl330.c | 53+++++++++++++++++++++++++++++++++++++----
Quoted 8 lines
Quoted 8 lines
---------
drivers/dma/pl330.c static int
Quoted 7 lines
1 files changed, 39 insertions(+), 14 deletions(-)drivers/dma/pl330.c +0
-0@@ -256,25 +256,50 @@ static intpl330_alloc_chan_resources(struct
Quoted 2 lines
Quoted 2 lines
dma_chan*chan)Quoted 1 line
drivers/dma/pl330.c +0
-0static int pl330_control(struct dma_chan *chan, enum
dma_ctrl_cmdQuoted 39 lines
Quoted 29 lines
cmd, unsigned long arg)
Quoted 28 lines
drivers/dma/pl330.c +10
-12{struct dma_pl330_chan *pch =to_pchan (chan); -struct dma_pl330_desc *desc; +struct dma_pl330_desc *desc, *_dt;unsigned long flags; +struct dma_pl330_dmac *pdmac = pch->dmac; +struct dma_slave_config *slave_config; +struct dma_pl330_peri *peri; +LIST_HEAD (list); -/* Only supports DMA_TERMINATE_ALL */ -if (cmd !=DMA_TERMINATE_ALL ) -return -ENXIO ; - -spin_lock_irqsave (&pch->lock, flags); - -/* FLUSH the PL330 Channel thread */ -pl330_chan_ctrl (pch->pl330_chid,PL330_OP_FLUSH ); +switch (cmd) { +case DMA_TERMINATE_ALL : +spin_lock_irqsave (&pch->lock, flags); -/* Mark all desc done */ -list_for_each_entry (desc, &pch->work_list, node) - desc->status =DONE ; +/* FLUSH the PL330 Channel thread */ +pl330_chan_ctrl (pch->pl330_chid,PL330_OP_FLUSH );Quoted 3 lines
drivers/dma/pl330.c static int pl330_alloc_chan_resources(struct dma_chan *chan)
Quoted 3 lines
drivers/dma/pl330.c +2
-1-spin_unlock_irqrestore (&pch->lock, flags); +/* Mark all desc done */ + list_for_each_entry_safe(desc, _dt, &pch-
work_list, node)Quoted 6 lines
{
Quoted 5 lines
drivers/dma/pl330.c +4
-0+ desc->status =DONE ; + pch->completed = desc->txd.cookie; +list_move_tail (&desc->node, &list); + }Quoted 16 lines
Quoted 11 lines
drivers/dma/pl330.c static int pl330_alloc_chan_resources(struct dma_chan *chan)
Quoted 11 lines
drivers/dma/pl330.c +10
-1-pl330_tasklet ((unsigned long ) pch); +list_splice_tail_init (&list, &pdmac->desc_pool); +spin_unlock_irqrestore (&pch->lock, flags); +break ; +case DMA_SLAVE_CONFIG : + slave_config = (struct dma_slave_config *)arg; + peri = pch->chan.private; + +if (slave_config->direction ==DMA_TO_DEVICE ) { +if (slave_config->dst_addr) + peri->fifo_addr = slave_config-
dst_addr;Quoted 4 lines
drivers/dma/pl330.c static int · line 292
Quoted 3 lines
drivers/dma/pl330.c +2
-0+if (slave_config->dst_addr_width) + peri->burst_sz =__ffs (slave_config- dst_addr_width);This doesn't sound right, why can't you use
xxx_maxburstfieldinstead?
Quoted 2 lines
Can you explain the problem in more detail?
Do you mean that 'xxx_maxburst' takes place of 'xxx_addr_width' or
Quoted 7 lines
__ffs()Quoted 3 lines
isn't proper here?
Additionally, I will modify this code to consider '
_maxburst' field.
__ffsis okay and sensible.
I meant you should use proper fields for passing info, which in this case would bedst_maxburstfor specifying destination burst sizes
I think the naming seems to make confusion.
'Peri->burst_sz' on this code means the width of fifo in bytes of the peri. It's same with the meaning 'xxx_addr_width'. So, I think it's proper usage. 'peri->burst_sz' is passed to PL330 HW. PL330 HW wants to get the power of 2 based the fifo width for it.
For example, If fifo width is 8 bytes, PL330 HW should get '3' for it. And I will modify code to consider xxx_maxburst.
Quoted 3 lines
--
~Vinod Koul
Intel Corp.
PATCH v4 3/14 DMA: PL330: Support DMA_SLAVE_CONFIG command
Quoted 10 lines · Boojin Kim
Vinod Koul Wrote:
Quoted 2 lines
I meant you should use proper fields for passing info, which in this case would be
dst_maxburstfor specifying destination burst sizesI think the naming seems to make confusion.
'Peri->burst_sz' on this code means the width of fifo in bytes of the peri. It's same with the meaning 'xxx_addr_width'. So, I think it's proper usage. 'peri->burst_sz' is passed to PL330 HW. PL330 HW wants to get the power of 2 based the fifo width for it.
For example, If fifo width is 8 bytes, PL330 HW should get '3' for it. And I will modify code to considerxxx_maxburst.
IMHO from your description above, peri->burst_sz is misnamed. Please add a comment at this location to say something like:
/* peri->burst_sz is the peripheral fifo width */
to explain this.
Thanks.
PATCH v4 4/14 DMA: PL330: Add DMA_CYCLIC capability
In reply to Boojin KimThis patch adds DMA_CYCLIC capability that is used for audio driver. DMA driver with DMA_CYCLIC capability reuses the dma requests that were submitted through tx_submit().
--- drivers/dma/pl330.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 111 insertions(+), 0 deletions(-)
drivers/dma/pl330.c +111 -0
@@ -69,6 +69,11 @@ struct dma_pl330_chan {* NULL if the channel is available to be acquired. */ void *pl330_chid; + +/* taks for cyclic capability */ +struct tasklet_struct *cyclic_task; + +bool cyclic; };struct dma_pl330_dmac {
@@ -184,6 +189,41 @@ static inline void fill_queue(struct dma_pl330_chan *pch) } } +static void pl330_tasklet_cyclic (unsigned long data) +{ +struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; +struct dma_pl330_desc *desc, *_dt; +unsigned long flags; +LIST_HEAD (list); + +spin_lock_irqsave (&pch->lock, flags); + +/* Pick up ripe tomatoes */ +list_for_each_entry_safe (desc, _dt, &pch->work_list, node) +if (desc->status ==DONE ) { +dma_async_tx_callback callback; + +list_move_tail (&desc->node, &pch->work_list); + pch->completed = desc->txd.cookie; + + desc->status =PREP ; + +/* Try to submit a req imm. +next to the last completed cookie */ +fill_queue (pch); + +/* Make sure the PL330 Channel thread is active */ +pl330_chan_ctrl (pch->pl330_chid,PL330_OP_START ); + + callback = desc->txd.callback; +if (callback) +callback (desc->txd.callback_param); + + } + +spin_unlock_irqrestore (&pch->lock, flags); +} +static void pl330_tasklet (unsigned long data) {struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
@@ -227,6 +267,9 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err)spin_unlock_irqrestore (&pch->lock, flags); +if (pch->cyclic_task) +tasklet_schedule (pch->cyclic_task); +else tasklet_schedule (&pch->task); }
@@ -316,6 +359,15 @@ static void pl330_free_chan_resources(struct dma_chan *chan)pl330_release_channel (pch->pl330_chid); pch->pl330_chid =NULL ; +if (pch->cyclic) { + pch->cyclic = false; +list_splice_tail_init (&pch->work_list, &pch->dmac->desc_pool); +if (pch->cyclic_task) { +tasklet_kill (pch->cyclic_task); + pch->cyclic_task =NULL ; + } + } +spin_unlock_irqrestore (&pch->lock, flags); }
@@ -547,6 +599,63 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)return burst_len; } +static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic ( +struct dma_chan *chan,dma_addr_t dma_addr,size_t len, +size_t period_len,enum dma_data_direction direction) +{ +struct dma_pl330_desc *desc; +struct dma_pl330_chan *pch =to_pchan (chan); +struct dma_pl330_peri *peri = chan->private; +dma_addr_t dst; +dma_addr_t src; + + pch =to_pchan (chan); +if (!pch) +return NULL ; + + desc =pl330_get_desc (pch); +if (!desc) { +dev_err (pch->dmac->pif.dev,"%s:%d Unable to fetch desc\n" , + __func__, __LINE__); +return NULL ; + } + +switch (direction) { +case DMA_TO_DEVICE : + desc->rqcfg.src_inc =1 ; + desc->rqcfg.dst_inc =0 ; + src = dma_addr; + dst = peri->fifo_addr; +break ; +case DMA_FROM_DEVICE : + desc->rqcfg.src_inc =0 ; + desc->rqcfg.dst_inc =1 ; + src = peri->fifo_addr; + dst = dma_addr; +break ; +default : +dev_err (pch->dmac->pif.dev,"%s:%d Invalid dma direction\n" , + __func__, __LINE__); +return NULL ; + } + + desc->rqcfg.brst_size = peri->burst_sz; + desc->rqcfg.brst_len =1 ; + +if (!pch->cyclic_task) { + pch->cyclic_task = +kmalloc (sizeof (struct tasklet_struct ),GFP_KERNEL ); +tasklet_init (pch->cyclic_task, + pl330_tasklet_cyclic, (unsigned int )pch); + } + + pch->cyclic = true; + +fill_px (&desc->px, dst, src, period_len); + +return &desc->txd; +} +static struct dma_async_tx_descriptor *pl330_prep_dma_memcpy (struct dma_chan *chan,dma_addr_t dst,dma_addr_t src,size_t len,unsigned long flags)
@@ -780,6 +889,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)case MEMTODEV :case DEVTOMEM :dma_cap_set (DMA_SLAVE , pd->cap_mask); +dma_cap_set (DMA_CYCLIC , pd->cap_mask);break ;default :dev_err (&adev->dev,"DEVTODEV Not Supported\n" );
@@ -805,6 +915,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) pd->device_alloc_chan_resources = pl330_alloc_chan_resources; pd->device_free_chan_resources = pl330_free_chan_resources; pd->device_prep_dma_memcpy = pl330_prep_dma_memcpy; + pd->device_prep_dma_cyclic = pl330_prep_dma_cyclic; pd->device_tx_status = pl330_tx_status; pd->device_prep_slave_sg = pl330_prep_slave_sg; pd->device_control = pl330_control;
Signature · 1 line
1.7.1
PATCH v4 4/14 DMA: PL330: Add DMA_CYCLIC capability
Quoted 8 lines · Boojin Kim
drivers/dma/pl330.c +8
-0+static void pl330_tasklet_cyclic (unsigned long data) +{ +struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; +struct dma_pl330_desc *desc, *_dt; +unsigned long flags; +LIST_HEAD (list); + +spin_lock_irqsave (&pch->lock, flags);
...
drivers/dma/pl330.c static inline void fill_queue(struct dma_pl330_chan *pch) · line 220
Quoted 3 lines
drivers/dma/pl330.c +3
-0+ callback = desc->txd.callback; +if (callback) +callback (desc->txd.callback_param);
On this again - what if the callback wants to terminate the DMA activity because there's no more audio data to be sent/received from the device?
Quoted 1 line
+
Useless blank line.
Quoted 9 lines
drivers/dma/pl330.c +5
-0+ } + +spin_unlock_irqrestore (&pch->lock, flags); +} +static void pl330_tasklet (unsigned long data) {struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;
drivers/dma/pl330.c static void dma_pl330_rqcb(void *token, enum pl330_op_err err) · line 273
Quoted 7 lines
drivers/dma/pl330.c +3
-0@@ -227,6 +267,9 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err)spin_unlock_irqrestore (&pch->lock, flags); +if (pch->cyclic_task) +tasklet_schedule (pch->cyclic_task); +else tasklet_schedule (&pch->task);
Indentation error.
Quoted 25 lines
drivers/dma/pl330.c +12
-0}@@ -316,6 +359,15 @@ static void pl330_free_chan_resources(struct dma_chan *chan)pl330_release_channel (pch->pl330_chid); pch->pl330_chid =NULL ; +if (pch->cyclic) { + pch->cyclic = false; +list_splice_tail_init (&pch->work_list, &pch->dmac->desc_pool); +if (pch->cyclic_task) { +tasklet_kill (pch->cyclic_task); + pch->cyclic_task =NULL ; + } + } +spin_unlock_irqrestore (&pch->lock, flags); }@@ -547,6 +599,63 @@ static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)return burst_len; } +static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic ( +struct dma_chan *chan,dma_addr_t dma_addr,size_t len, +size_t period_len,enum dma_data_direction direction)
drivers/dma/pl330.c static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len) · line 614
Quoted 10 lines
drivers/dma/pl330.c +10
-0+{ +struct dma_pl330_desc *desc; +struct dma_pl330_chan *pch =to_pchan (chan); +struct dma_pl330_peri *peri = chan->private; +dma_addr_t dst; +dma_addr_t src; + + pch =to_pchan (chan); +if (!pch) +return NULL ;
You've already done the to_pchan() thing when declaring pch. You've already dereferenced 'chan', so there's no way that pch could be NULL here.
Quoted 25 lines
drivers/dma/pl330.c +25
-0+ + desc =pl330_get_desc (pch); +if (!desc) { +dev_err (pch->dmac->pif.dev,"%s:%d Unable to fetch desc\n" , + __func__, __LINE__); +return NULL ; + } + +switch (direction) { +case DMA_TO_DEVICE : + desc->rqcfg.src_inc =1 ; + desc->rqcfg.dst_inc =0 ; + src = dma_addr; + dst = peri->fifo_addr; +break ; +case DMA_FROM_DEVICE : + desc->rqcfg.src_inc =0 ; + desc->rqcfg.dst_inc =1 ; + src = peri->fifo_addr; + dst = dma_addr; +break ; +default : +dev_err (pch->dmac->pif.dev,"%s:%d Invalid dma direction\n" , + __func__, __LINE__); +return NULL ;
drivers/dma/pl330.c static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len) · line 649
Quoted 10 lines
drivers/dma/pl330.c +10
-0+ } + + desc->rqcfg.brst_size = peri->burst_sz; + desc->rqcfg.brst_len =1 ; + +if (!pch->cyclic_task) { + pch->cyclic_task = +kmalloc (sizeof (struct tasklet_struct ),GFP_KERNEL ); +tasklet_init (pch->cyclic_task, + pl330_tasklet_cyclic, (unsigned int )pch);
Here you allocate memory for the cyclic task. Above you set this pointer to NULL. That sounds like a memory leak to me. Why are you kmallocing this memory - why can't it be part of the dma_pl330_chan structure? It's only 28 bytes.
PATCH v4 4/14 DMA: PL330: Add DMA_CYCLIC capability
Russell King - ARM Linux Wrote:
Quoted 3 lines
Sent: Monday, July 25, 2011 6:28 PM
To: Boojin Kim
Cc: linux-arm-kernel at lists.infradead.org;
linux-samsung-soc at vger.kernel.org;
Quoted 13 lines
Kukjin Kim; Vinod Koul; Jassi Brar; Grant Likely; Mark Brown; Dan Williams
Subject: Re: [PATCH V4 04/14] DMA: PL330: AddDMA_CYCLICcapabilityQuoted 8 lines · Boojin Kim
drivers/dma/pl330.c +8
-0+static void pl330_tasklet_cyclic (unsigned long data) +{ +struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; +struct dma_pl330_desc *desc, *_dt; +unsigned long flags; +LIST_HEAD (list); + +spin_lock_irqsave (&pch->lock, flags);...
Quoted 6 lines
drivers/dma/pl330.c static inline void fill_queue(struct dma_pl330_chan *pch) · line 220
Quoted 3 lines
drivers/dma/pl330.c +3
-0+ callback = desc->txd.callback; +if (callback) +callback (desc->txd.callback_param);On this again - what if the callback wants to terminate the DMA activity because there's no more audio data to be sent/received from the device?
Do you mean what is happened if the callback() is called after channel is terminated ?
Or What is happened if Callback() calls 'dma_release_channel()' to terminate DMA?
Quoted 4 lines
Quoted 2 lines
+
Useless blank line.
I will address your comment.
Quoted 12 lines
drivers/dma/pl330.c static void dma_pl330_rqcb(void *token, enum
Quoted 10 lines
drivers/dma/pl330.c +5
-0+ } + +spin_unlock_irqrestore (&pch->lock, flags); +} +static void pl330_tasklet (unsigned long data) {struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data;@@ -227,6 +267,9 @@ static void dma_pl330_rqcb(void *token, enum
pl330_op_errerr)Quoted 1 line
Quoted 8 lines
drivers/dma/pl330.c static void dma_pl330_rqcb(void *token, enum pl330_op_err err) · line 273
Quoted 6 lines
drivers/dma/pl330.c +3
-0spin_unlock_irqrestore (&pch->lock, flags); +if (pch->cyclic_task) +tasklet_schedule (pch->cyclic_task); +else tasklet_schedule (&pch->task);Indentation error.
Sorry again.. I will address your comment.
Quoted 4 lines
Review static void pl330_free_chan_resources(struct
Quoted 4 lines
}
(quoted diff) +0
-0@@ -316,6 +359,15 @@ static void pl330_free_chan_resources(struct
dma_chan
Quoted 7 lines
*chan)
drivers/dma/pl330.c static void pl330_free_chan_resources(struct dma_chan *chan)
Quoted 6 lines
drivers/dma/pl330.c +3
-0pl330_release_channel (pch->pl330_chid); pch->pl330_chid =NULL ; +if (pch->cyclic) { + pch->cyclic = false; + list_splice_tail_init(&pch->work_list,
&pch->dmac->desc_pool);
Quoted 10 lines
drivers/dma/pl330.c static inline int get_burst_len(struct
Quoted 10 lines
drivers/dma/pl330.c +6
-0+if (pch->cyclic_task) { +tasklet_kill (pch->cyclic_task); + pch->cyclic_task =NULL ; + } + } +spin_unlock_irqrestore (&pch->lock, flags); }@@ -547,6 +599,63 @@ static inline int get_burst_len(struct
dma_pl330_desc
Quoted 13 lines
*desc,
size_tlen)Quoted 12 lines
drivers/dma/pl330.c +9
-0return burst_len; } +static struct dma_async_tx_descriptor *pl330_prep_dma_cyclic ( +struct dma_chan *chan,dma_addr_t dma_addr,size_t len, +size_t period_len,enum dma_data_direction direction) +{ +struct dma_pl330_desc *desc; +struct dma_pl330_chan *pch =to_pchan (chan); +struct dma_pl330_peri *peri = chan->private; +dma_addr_t dst; +dma_addr_t src;
Quoted 8 lines
drivers/dma/pl330.c static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len) · line 614
Quoted 4 lines
drivers/dma/pl330.c +4
-0+ + pch =to_pchan (chan); +if (!pch) +return NULL ;You've already done the
to_pchan()thing when declaring pch. You've already dereferenced 'chan', so there's no way that pch could be NULL here.
I will address your comment.
Quoted 33 lines
Quoted 33 lines
drivers/dma/pl330.c +32
-0+ + desc =pl330_get_desc (pch); +if (!desc) { +dev_err (pch->dmac->pif.dev,"%s:%d Unable to fetch desc\n" , + __func__, __LINE__); +return NULL ; + } + +switch (direction) { +case DMA_TO_DEVICE : + desc->rqcfg.src_inc =1 ; + desc->rqcfg.dst_inc =0 ; + src = dma_addr; + dst = peri->fifo_addr; +break ; +case DMA_FROM_DEVICE : + desc->rqcfg.src_inc =0 ; + desc->rqcfg.dst_inc =1 ; + src = peri->fifo_addr; + dst = dma_addr; +break ; +default : +dev_err (pch->dmac->pif.dev,"%s:%d Invalid dma direction\n" , + __func__, __LINE__); +return NULL ; + } + + desc->rqcfg.brst_size = peri->burst_sz; + desc->rqcfg.brst_len =1 ; + +if (!pch->cyclic_task) { + pch->cyclic_task =
Quoted 8 lines
drivers/dma/pl330.c static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len) · line 649
Quoted 3 lines
drivers/dma/pl330.c +3
-0+kmalloc (sizeof (struct tasklet_struct ),GFP_KERNEL ); +tasklet_init (pch->cyclic_task, + pl330_tasklet_cyclic, (unsigned int )pch);Here you allocate memory for the cyclic task. Above you set this pointer to NULL. That sounds like a memory leak to me. Why are you kmallocing this memory - why can't it be part of the
dma_pl330_chanstructure? It's only 28 bytes.
It's my mistake. I should have been free of the memory.
And the reason why I use kmalloc for 'cyclic_task' is following. This memory size for 'cyclic_tasklet' is the 896 bytes ( = the number of channel * sizeof(struct tasklet_struct)= 32*28) for each DMAC. And This memory size is increased according to the number of DMAC.
And Samsung has the DMAC that is dedicated for Mem-to-Mem operation. If I make 'cyclic_task' be part of dma_pl330_chan, this DMAC that is dedicated for Mem-to-Mem operation should hold unused data.
So, I think it's loss that all dma channels hold own 'cyclic_task'.
PATCH v4 4/14 DMA: PL330: Add DMA_CYCLIC capability
Quoted 17 lines · Boojin Kim
Quoted 10 lines · Boojin Kim
Quoted 8 lines
drivers/dma/pl330.c +8
-0+static void pl330_tasklet_cyclic (unsigned long data) +{ +struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; +struct dma_pl330_desc *desc, *_dt; +unsigned long flags; +LIST_HEAD (list); + +spin_lock_irqsave (&pch->lock, flags);...
Quoted 6 lines
drivers/dma/pl330.c static inline void fill_queue(struct dma_pl330_chan *pch) · line 220
Quoted 3 lines
drivers/dma/pl330.c +3
-0+ callback = desc->txd.callback; +if (callback) +callback (desc->txd.callback_param);On this again - what if the callback wants to terminate the DMA activity because there's no more audio data to be sent/received from the device?
Quoted 4 lines
Do you mean what is happened if the
callback()is called after channel is terminated ?
Or What is happened ifCallback()calls 'dma_release_channel()' to terminate DMA?
No. I mean what if the callback wants to call dmaengine_terminate_all().
Quoted 13 lines
Quoted 10 lines
drivers/dma/pl330.c static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len) · line 649
Quoted 5 lines
drivers/dma/pl330.c +5
-0+if (!pch->cyclic_task) { + pch->cyclic_task = +kmalloc (sizeof (struct tasklet_struct ),GFP_KERNEL ); +tasklet_init (pch->cyclic_task, + pl330_tasklet_cyclic, (unsigned int )pch);Here you allocate memory for the cyclic task. Above you set this pointer to NULL. That sounds like a memory leak to me. Why are you kmallocing this memory - why can't it be part of the
dma_pl330_chanstructure? It's only 28 bytes.It's my mistake. I should have been free of the memory.
Quoted 8 lines
And the reason why I use kmalloc for '
cyclic_task' is following. This memory size for 'cyclic_tasklet' is the 896 bytes ( = the number of channel *sizeof(struct tasklet_struct)= 32*28) for each DMAC. And This memory size is increased according to the number of DMAC.
And Samsung has the DMAC that is dedicated for Mem-to-Mem operation. If I make 'cyclic_task' be part ofdma_pl330_chan, this DMAC that is dedicated for Mem-to-Mem operation should hold unused data.
So, I think it's loss that all dma channels hold own 'cyclic_task'.
Could you re-use the tasklet that already exists?
PATCH v4 4/14 DMA: PL330: Add DMA_CYCLIC capability
Quoted 18 lines · Russell King - ARM Linux
Quoted 17 lines · Boojin Kim
Quoted 16 lines · Boojin Kim
Quoted 8 lines
drivers/dma/pl330.c +8
-0+static void pl330_tasklet_cyclic (unsigned long data) +{ +struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; +struct dma_pl330_desc *desc, *_dt; +unsigned long flags; +LIST_HEAD (list); + +spin_lock_irqsave (&pch->lock, flags);...
drivers/dma/pl330.c static inline void fill_queue(struct dma_pl330_chan *pch) · line 220
Quoted 3 lines
drivers/dma/pl330.c +3
-0+ callback = desc->txd.callback; +if (callback) +callback (desc->txd.callback_param);On this again - what if the callback wants to terminate the DMA activity because there's no more audio data to be sent/received from the device?
Quoted 6 lines
Quoted 4 lines
Do you mean what is happened if the
callback()is called after channel is terminated ?
Or What is happened ifCallback()calls 'dma_release_channel()' to terminate DMA?No. I mean what if the callback wants to call
dmaengine_terminate_all().
you are supposed to drop the lock here, that way callback can call any DMA API, otherwise it will result in deadlock.
This make me wonder you haven't read the documentation at all, please ensure you have read Documentation/dmaengine.txt before next posting
Quoted 24 lines
Quoted 14 lines
Quoted 11 lines
drivers/dma/pl330.c static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len) · line 649
Quoted 6 lines
drivers/dma/pl330.c +5
-0+if (!pch->cyclic_task) { + pch->cyclic_task = +kmalloc (sizeof (struct tasklet_struct ),GFP_KERNEL ); +tasklet_init (pch->cyclic_task, + pl330_tasklet_cyclic, (unsigned int )pch);Here you allocate memory for the cyclic task. Above you set this pointer to NULL. That sounds like a memory leak to me. Why are you kmallocing this memory - why can't it be part of the
dma_pl330_chanstructure? It's only 28 bytes.It's my mistake. I should have been free of the memory.
Quoted 8 lines
And the reason why I use kmalloc for '
cyclic_task' is following. This memory size for 'cyclic_tasklet' is the 896 bytes ( = the number of channel *sizeof(struct tasklet_struct)= 32*28) for each DMAC. And This memory size is increased according to the number of DMAC.
And Samsung has the DMAC that is dedicated for Mem-to-Mem operation. If I make 'cyclic_task' be part ofdma_pl330_chan, this DMAC that is dedicated for Mem-to-Mem operation should hold unused data.
So, I think it's loss that all dma channels hold own 'cyclic_task'.Could you re-use the tasklet that already exists?
Signature · 2 lines
~Vinod Koul Intel Corp.
PATCH v4 4/14 DMA: PL330: Add DMA_CYCLIC capability
Quoted 24 lines · Vinod Koul
Quoted 23 lines · Russell King - ARM Linux
Quoted 21 lines · Boojin Kim
Quoted 10 lines · Boojin Kim
Quoted 8 lines
drivers/dma/pl330.c +8
-0+static void pl330_tasklet_cyclic (unsigned long data) +{ +struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; +struct dma_pl330_desc *desc, *_dt; +unsigned long flags; +LIST_HEAD (list); + +spin_lock_irqsave (&pch->lock, flags);...
Quoted 6 lines
drivers/dma/pl330.c static inline void fill_queue(struct dma_pl330_chan *pch) · line 220
Quoted 3 lines
drivers/dma/pl330.c +3
-0+ callback = desc->txd.callback; +if (callback) +callback (desc->txd.callback_param);On this again - what if the callback wants to terminate the DMA activity because there's no more audio data to be sent/received from the device?
Do you mean what is happened if the
callback()is called after channel is terminated ?
Or What is happened ifCallback()calls 'dma_release_channel()' to terminate DMA?
Quoted 5 lines
Quoted 1 line
No. I mean what if the callback wants to call
dmaengine_terminate_all().you are supposed to drop the lock here, that way callback can call any DMA API, otherwise it will result in deadlock.
This make me wonder you haven't read the documentation at all, please ensure you have readDocumentation/dmaengine.txtbefore next posting
I know that very well thank you. Please look at my previous post in the previous round of patches, and the response from Boojin Kim to see why I used this as an *EXAMPLE* to get this fixed.
PATCH v4 4/14 DMA: PL330: Add DMA_CYCLIC capability
Quoted 26 lines · Russell King - ARM Linux
Quoted 25 lines · Vinod Koul
Quoted 24 lines · Russell King - ARM Linux
Quoted 17 lines · Boojin Kim
Quoted 10 lines · Boojin Kim
Quoted 8 lines
drivers/dma/pl330.c +8
-0+static void pl330_tasklet_cyclic (unsigned long data) +{ +struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; +struct dma_pl330_desc *desc, *_dt; +unsigned long flags; +LIST_HEAD (list); + +spin_lock_irqsave (&pch->lock, flags);...
Quoted 6 lines
drivers/dma/pl330.c static inline void fill_queue(struct dma_pl330_chan *pch) · line 220
Quoted 3 lines
drivers/dma/pl330.c +3
-0+ callback = desc->txd.callback; +if (callback) +callback (desc->txd.callback_param);On this again - what if the callback wants to terminate the DMA activity because there's no more audio data to be sent/received from the device?
Quoted 4 lines
Do you mean what is happened if the
callback()is called after channel is terminated ?
Or What is happened ifCallback()calls 'dma_release_channel()' to terminate DMA?No. I mean what if the callback wants to call
dmaengine_terminate_all().
Quoted 8 lines
Quoted 4 lines
you are supposed to drop the lock here, that way callback can call any DMA API, otherwise it will result in deadlock.
This make me wonder you haven't read the documentation at all, please ensure you have readDocumentation/dmaengine.txtbefore next postingI know that very well thank you. Please look at my previous post in the previous round of patches, and the response from Boojin Kim to see why I used this as an *EXAMPLE* to get this fixed.
Russell,
Sorry that was not intended for you but for the author of patch Boojin Kim... Agree on your EXAMPLE, just wanted to ensure authors have read it as going thru this patch made it clear that they haven't.
Signature · 2 lines
~Vinod Koul Intel Corp.
PATCH v4 4/14 DMA: PL330: Add DMA_CYCLIC capability
Quoted 7 lines · Vinod Koul
Quoted 3 lines
I know that very well thank you. Please look at my previous post in the previous round of patches, and the response from Boojin Kim to see why I used this as an *EXAMPLE* to get this fixed.
Russell,
Sorry that was not intended for you but for the author of patch Boojin Kim... Agree on your EXAMPLE, just wanted to ensure authors have read it as going thru this patch made it clear that they haven't.
That wasn't obvious because of the To: and the use of 'you' in your reply.
In any case, let's fix up the documentation to be a little more complete and expansive about these conditions, and improve its formatting so it's easier to read.
A few points:
1. This really should describe the dma_slave_config structure in detail (or refer to the documentation in dmaengine.h) especially describing what is mandatory there.
2. Note the filter function thing - I think this should be mandatory for slave and cyclic channels. These typically have a DMA request signal associated with each channel, and so 'any random channel' isn't really acceptable like it is for the async_tx APIs.
3. I think this should specify that dmaengine_slave_config() should be specified as mandatory after obtaining the DMA engine channel.
Any comments on this before I prepare this as a proper patch?
Documentation/dmaengine.txt +140 -64
@@ -10,87 +10,163 @@ Below is a guide to device driver writers on how to use the Slave-DMA API of the DMA Engine. This is applicable only for slave DMA usage only. -The slave DMA usage consists of following steps +The slave DMA usage consists of following steps: 1. Allocate a DMA slave channel 2. Set slave and controller specific parameters 3. Get a descriptor for transaction 4. Submit the transaction and wait for callback notification +5. Issue pending requests 1. Allocate a DMA slave channel -Channel allocation is slightly different in the slave DMA context, client -drivers typically need a channel from a particular DMA controller only and even -in some cases a specific channel is desired. To request a channel -dma_request_channel() API is used. - -Interface: -struct dma_chan *dma_request_channel(dma_cap_mask_t mask, - dma_filter_fn filter_fn, - void *filter_param); -where dma_filter_fn is defined as: -typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); - -When the optional 'filter_fn' parameter is set to NULL dma_request_channel -simply returns the first channel that satisfies the capability mask. Otherwise, -when the mask parameter is insufficient for specifying the necessary channel, -the filter_fn routine can be used to disposition the available channels in the -system. The filter_fn routine is called once for each free channel in the -system. Upon seeing a suitable channel filter_fn returns DMA_ACK which flags -that channel to be the return value from dma_request_channel. A channel -allocated via this interface is exclusive to the caller, until -dma_release_channel() is called. + + Channel allocation is slightly different in the slave DMA context, + client drivers typically need a channel from a particular DMA + controller only and even in some cases a specific channel is desired. + To request a channel dma_request_channel() API is used. + + Interface: + struct dma_chan *dma_request_channel(dma_cap_mask_t mask, + dma_filter_fn filter_fn, + void *filter_param); + where dma_filter_fn is defined as: + typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); + + The 'filter_fn' parameter is optional, but highly recommended for + slave and cyclic channels as they typically need to obtain a specific + DMA channel. + + When the optional 'filter_fn' parameter is NULL, dma_request_channel() + simply returns the first channel that satisfies the capability mask. + + Otherwise, the 'filter_fn' routine will be called once for each free + channel which has a capability in 'mask'. 'filter_fn' is expected to + return 'true' when the desired DMA channel is found. + + A channel allocated via this interface is exclusive to the caller, + until dma_release_channel() is called. 2. Set slave and controller specific parameters -Next step is always to pass some specific information to the DMA driver. Most of -the generic information which a slave DMA can use is in struct dma_slave_config. -It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA -burst lengths etc. If some DMA controllers have more parameters to be sent then -they should try to embed struct dma_slave_config in their controller specific -structure. That gives flexibility to client to pass more parameters, if -required. - -Interface: -int dmaengine_slave_config(struct dma_chan *chan, - struct dma_slave_config *config) + + Next step is always to pass some specific information to the DMA + driver. Most of the generic information which a slave DMA can use + is in struct dma_slave_config. This allows the clients to specify + DMA direction, DMA addresses, bus widths, DMA burst lengths etc + for the peripheral. + + If some DMA controllers have more parameters to be sent then they + should try to embed struct dma_slave_config in their controller + specific structure. That gives flexibility to client to pass more + parameters, if required. + + Interface: + int dmaengine_slave_config(struct dma_chan *chan, + struct dma_slave_config *config) 3. Get a descriptor for transaction -For slave usage the various modes of slave transfers supported by the -DMA-engine are: -slave_sg - DMA a list of scatter gather buffers from/to a peripheral -dma_cyclic - Perform a cyclic DMA operation from/to a peripheral till the + + For slave usage the various modes of slave transfers supported by the + DMA-engine are: + + slave_sg - DMA a list of scatter gather buffers from/to a peripheral + dma_cyclic - Perform a cyclic DMA operation from/to a peripheral till the operation is explicitly stopped. -The non NULL return of this transfer API represents a "descriptor" for the given -transaction. -Interface: -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)( + A non-NULL return of this transfer API represents a "descriptor" for + the given transaction. + + Interface: + struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)( struct dma_chan *chan, struct scatterlist *dst_sg, unsigned int dst_nents, struct scatterlist *src_sg, unsigned int src_nents, unsigned long flags); -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)( + + struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_data_direction direction); + Once a descriptor has been obtained, the callback information can be + added and must then be submitted. Some DMA engine drivers may hold a + spinlock between a successful preparation and submission so it is + important that these two operations are closely paired. + + Note: + Although the async_tx API specifies that completion callback + routines cannot submit any new operations, this is not the + case for slave/cyclic DMA. + + For slave DMA, the subsequent transaction may not be available + for submission prior to callback function being invoked, so + slave DMA callbacks are permitted to prepare and submit a new + transaction. + + For cyclic DMA, a callback function may wish to terminate the + DMA via dmaengine_terminate_all(). + + Therefore, it is important that DMA engine drivers drop any + locks before calling the callback function which may cause a + deadlock. + + Note that callbacks will always be invoked from the DMA + engines tasklet, never from interrupt context. + 4. Submit the transaction and wait for callback notification -To schedule the transaction to be scheduled by dma device, the "descriptor" -returned in above (3) needs to be submitted. -To tell the dma driver that a transaction is ready to be serviced, the -descriptor->submit() callback needs to be invoked. This chains the descriptor to -the pending queue. -The transactions in the pending queue can be activated by calling the -issue_pending API. If channel is idle then the first transaction in queue is -started and subsequent ones queued up. -On completion of the DMA operation the next in queue is submitted and a tasklet -triggered. The tasklet would then call the client driver completion callback -routine for notification, if set. -Interface: -void dma_async_issue_pending(struct dma_chan *chan); - -============================================================================== - -Additional usage notes for dma driver writers -1/ Although DMA engine specifies that completion callback routines cannot submit -any new operations, but typically for slave DMA subsequent transaction may not -be available for submit prior to callback routine being called. This requirement -is not a requirement for DMA-slave devices. But they should take care to drop -the spin-lock they might be holding before calling the callback routine + + Once the descriptor has been prepared and the callback information + added, it must be placed on the DMA engine drivers pending queue. + + Interface: + dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc) + + This returns a cookie can be used to check the progress of DMA engine + activity via other DMA engine calls not covered in this document. + + dmaengine_submit() will not start the DMA operation, it merely adds + it to the pending queue. For this, see step 5, dma_async_issue_pending. + +5. Issue pending DMA requests + + The transactions in the pending queue can be activated by calling the + issue_pending API. If channel is idle then the first transaction in + queue is started and subsequent ones queued up. + + On completion of each DMA operation, the next in queue is started and + a tasklet triggered. The tasklet will then call the client driver + completion callback routine for notification, if set. + + Interface: + void dma_async_issue_pending(struct dma_chan *chan); + +Further APIs: + +1. int dmaengine_terminate_all(struct dma_chan *chan) + + This causes all activity for the DMA channel to be stopped, and may + discard data in the DMA FIFO which hasn't been fully transferred. + No callback functions will be called for any incomplete transfers. + +2. int dmaengine_pause(struct dma_chan *chan) + + This pauses activity on the DMA channel without data loss. + +3. int dmaengine_resume(struct dma_chan *chan) + + Resume a previously paused DMA channel. It is invalid to resume a + channel which is not currently paused. + +4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan, + dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used) + + This can be used to check the status of the channel. Please see + the documentation in include/linux/dmaengine.h for a more complete + description of this API. + + This can be used in conjunction with dma_async_is_complete() and + the cookie returned from 'descriptor->submit()' to check for + completion of a specific DMA transaction. + + Note: + Not all DMA engine drivers can return reliable information for + a running DMA channel. It is recommended that DMA engine users + pause or stop (via dmaengine_terminate_all) the channel before + using this API.
PATCH v4 4/14 DMA: PL330: Add DMA_CYCLIC capability
Quoted 10 lines · Russell King - ARM Linux
Quoted 7 lines · Vinod Koul
Quoted 3 lines
I know that very well thank you. Please look at my previous post in the previous round of patches, and the response from Boojin Kim to see why I used this as an *EXAMPLE* to get this fixed.
Russell,
Sorry that was not intended for you but for the author of patch Boojin Kim... Agree on your EXAMPLE, just wanted to ensure authors have read it as going thru this patch made it clear that they haven't.That wasn't obvious because of the To: and the use of 'you' in your reply.
Laziness on a rainy monday evening caused me to miss that
Quoted 10 lines
In any case, let's fix up the documentation to be a little more complete and expansive about these conditions, and improve its formatting so it's easier to read.
A few points:
1. This really should describe the
dma_slave_configstructure in detail (or refer to the documentation indmaengine.h) especially describing what is mandatory there.
I think you missed mandatory fields here, Pls note I am dropping the direction field in this, as we have discussed it makes no sense
Quoted 152 lines
2. Note the filter function thing - I think this should be mandatory for slave and cyclic channels. These typically have a DMA request signal associated with each channel, and so 'any random channel' isn't really acceptable like it is for the
async_txAPIs.3. I think this should specify that
dmaengine_slave_config()should be specified as mandatory after obtaining the DMA engine channel.Any comments on this before I prepare this as a proper patch?
Documentation/dmaengine.txt +72
-42@@ -10,87 +10,163 @@ Below is a guide to device driver writers on how to use the Slave-DMA API of the DMA Engine. This is applicable only for slave DMA usage only. -The slave DMA usage consists of following steps +The slave DMA usage consists of following steps: 1. Allocate a DMA slave channel 2. Set slave and controller specific parameters 3. Get a descriptor for transaction 4. Submit the transaction and wait for callback notification +5. Issue pending requests 1. Allocate a DMA slave channel -Channel allocation is slightly different in the slave DMA context, client -drivers typically need a channel from a particular DMA controller only and even -in some cases a specific channel is desired. To request a channel -dma_request_channel() API is used. - -Interface: -struct dma_chan *dma_request_channel(dma_cap_mask_t mask, - dma_filter_fn filter_fn, - void *filter_param); -where dma_filter_fn is defined as: -typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); - -When the optional 'filter_fn' parameter is set to NULL dma_request_channel -simply returns the first channel that satisfies the capability mask. Otherwise, -when the mask parameter is insufficient for specifying the necessary channel, -the filter_fn routine can be used to disposition the available channels in the -system. The filter_fn routine is called once for each free channel in the -system. Upon seeing a suitable channel filter_fn returns DMA_ACK which flags -that channel to be the return value from dma_request_channel. A channel -allocated via this interface is exclusive to the caller, until -dma_release_channel() is called. + + Channel allocation is slightly different in the slave DMA context, + client drivers typically need a channel from a particular DMA + controller only and even in some cases a specific channel is desired. + To request a channel dma_request_channel() API is used. + + Interface: + struct dma_chan *dma_request_channel(dma_cap_mask_t mask, + dma_filter_fn filter_fn, + void *filter_param); + where dma_filter_fn is defined as: + typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); + + The 'filter_fn' parameter is optional, but highly recommended for + slave and cyclic channels as they typically need to obtain a specific + DMA channel. + + When the optional 'filter_fn' parameter is NULL, dma_request_channel() + simply returns the first channel that satisfies the capability mask. + + Otherwise, the 'filter_fn' routine will be called once for each free + channel which has a capability in 'mask'. 'filter_fn' is expected to + return 'true' when the desired DMA channel is found. + + A channel allocated via this interface is exclusive to the caller, + until dma_release_channel() is called. 2. Set slave and controller specific parameters -Next step is always to pass some specific information to the DMA driver. Most of -the generic information which a slave DMA can use is in struct dma_slave_config. -It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA -burst lengths etc. If some DMA controllers have more parameters to be sent then -they should try to embed struct dma_slave_config in their controller specific -structure. That gives flexibility to client to pass more parameters, if -required. - -Interface: -int dmaengine_slave_config(struct dma_chan *chan, - struct dma_slave_config *config) + + Next step is always to pass some specific information to the DMA + driver. Most of the generic information which a slave DMA can use + is in struct dma_slave_config. This allows the clients to specify + DMA direction, DMA addresses, bus widths, DMA burst lengths etc + for the peripheral. + + If some DMA controllers have more parameters to be sent then they + should try to embed struct dma_slave_config in their controller + specific structure. That gives flexibility to client to pass more + parameters, if required. + + Interface: + int dmaengine_slave_config(struct dma_chan *chan, + struct dma_slave_config *config) 3. Get a descriptor for transaction -For slave usage the various modes of slave transfers supported by the -DMA-engine are: -slave_sg - DMA a list of scatter gather buffers from/to a peripheral -dma_cyclic - Perform a cyclic DMA operation from/to a peripheral till the + + For slave usage the various modes of slave transfers supported by the + DMA-engine are: + + slave_sg - DMA a list of scatter gather buffers from/to a peripheral + dma_cyclic - Perform a cyclic DMA operation from/to a peripheral till the operation is explicitly stopped. -The non NULL return of this transfer API represents a "descriptor" for the given -transaction. -Interface: -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)( + A non-NULL return of this transfer API represents a "descriptor" for + the given transaction. + + Interface: + struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)( struct dma_chan *chan, struct scatterlist *dst_sg, unsigned int dst_nents, struct scatterlist *src_sg, unsigned int src_nents, unsigned long flags); -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)( + + struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_data_direction direction); + Once a descriptor has been obtained, the callback information can be + added and must then be submitted. Some DMA engine drivers may hold a + spinlock between a successful preparation and submission so it is + important that these two operations are closely paired. + + Note: + Although the async_tx API specifies that completion callback + routines cannot submit any new operations, this is not the + case for slave/cyclic DMA. + + For slave DMA, the subsequent transaction may not be available + for submission prior to callback function being invoked, so + slave DMA callbacks are permitted to prepare and submit a new + transaction. + + For cyclic DMA, a callback function may wish to terminate the
Documentation/dmaengine.txt line 113
Quoted 10 lines
Documentation/dmaengine.txt +9
-0+ DMA via dmaengine_terminate_all(). + + Therefore, it is important that DMA engine drivers drop any + locks before calling the callback function which may cause a + deadlock. + + Note that callbacks will always be invoked from the DMA + engines tasklet, never from interrupt context. + 4. Submit the transaction and wait for callback notification
As you are adding 5 for issue pending then this needs change
Quoted 26 lines
Documentation/dmaengine.txt +4
-22-To schedule the transaction to be scheduled by dma device, the "descriptor" -returned in above (3) needs to be submitted. -To tell the dma driver that a transaction is ready to be serviced, the -descriptor->submit() callback needs to be invoked. This chains the descriptor to -the pending queue. -The transactions in the pending queue can be activated by calling the -issue_pending API. If channel is idle then the first transaction in queue is -started and subsequent ones queued up. -On completion of the DMA operation the next in queue is submitted and a tasklet -triggered. The tasklet would then call the client driver completion callback -routine for notification, if set. -Interface: -void dma_async_issue_pending(struct dma_chan *chan); - -============================================================================== - -Additional usage notes for dma driver writers -1/ Although DMA engine specifies that completion callback routines cannot submit -any new operations, but typically for slave DMA subsequent transaction may not -be available for submit prior to callback routine being called. This requirement -is not a requirement for DMA-slave devices. But they should take care to drop -the spin-lock they might be holding before calling the callback routine + + Once the descriptor has been prepared and the callback information + added, it must be placed on the DMA engine drivers pending queue. +
Documentation/dmaengine.txt line 127
Quoted 10 lines
Documentation/dmaengine.txt +10
-0+ Interface: + dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc) + + This returns a cookie can be used to check the progress of DMA engine + activity via other DMA engine calls not covered in this document. + + dmaengine_submit() will not start the DMA operation, it merely adds + it to the pending queue. For this, see step 5, dma_async_issue_pending. + +5. Issue pending DMA requests
and getting callback notification
Quoted 46 lines
Documentation/dmaengine.txt +45
-0+ + The transactions in the pending queue can be activated by calling the + issue_pending API. If channel is idle then the first transaction in + queue is started and subsequent ones queued up. + + On completion of each DMA operation, the next in queue is started and + a tasklet triggered. The tasklet will then call the client driver + completion callback routine for notification, if set. + + Interface: + void dma_async_issue_pending(struct dma_chan *chan); + +Further APIs: + +1. int dmaengine_terminate_all(struct dma_chan *chan) + + This causes all activity for the DMA channel to be stopped, and may + discard data in the DMA FIFO which hasn't been fully transferred. + No callback functions will be called for any incomplete transfers. + +2. int dmaengine_pause(struct dma_chan *chan) + + This pauses activity on the DMA channel without data loss. + +3. int dmaengine_resume(struct dma_chan *chan) + + Resume a previously paused DMA channel. It is invalid to resume a + channel which is not currently paused. + +4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan, + dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used) + + This can be used to check the status of the channel. Please see + the documentation in include/linux/dmaengine.h for a more complete + description of this API. + + This can be used in conjunction with dma_async_is_complete() and + the cookie returned from 'descriptor->submit()' to check for + completion of a specific DMA transaction. + + Note: + Not all DMA engine drivers can return reliable information for + a running DMA channel. It is recommended that DMA engine users + pause or stop (via dmaengine_terminate_all) the channel before + using this API.
Signature · 2 lines
~Vinod Koul Intel Corp.
PATCH 1/1 Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
Here's an updated patch.
8<----------
From: Russell King <[email protected]>
DMAEngine: Improve slave/cyclic documentation
Improve the documentation for the slave and cyclic DMA engine support reformatting it for easier reading, adding further APIs, splitting it into five steps, and including references to the documentation in dmaengine.h.
--- Documentation/dmaengine.txt | 211 ++++++++++++++++++++++++++++++------------- 1 files changed, 146 insertions(+), 65 deletions(-)
Documentation/dmaengine.txt +146 -65
@@ -10,87 +10,168 @@ Below is a guide to device driver writers on how to use the Slave-DMA API of the DMA Engine. This is applicable only for slave DMA usage only. -The slave DMA usage consists of following steps +The slave DMA usage consists of following steps: 1. Allocate a DMA slave channel 2. Set slave and controller specific parameters 3. Get a descriptor for transaction 4. Submit the transaction and wait for callback notification +5. Issue pending requests 1. Allocate a DMA slave channel -Channel allocation is slightly different in the slave DMA context, client -drivers typically need a channel from a particular DMA controller only and even -in some cases a specific channel is desired. To request a channel -dma_request_channel() API is used. - -Interface: -struct dma_chan *dma_request_channel(dma_cap_mask_t mask, - dma_filter_fn filter_fn, - void *filter_param); -where dma_filter_fn is defined as: -typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); - -When the optional 'filter_fn' parameter is set to NULL dma_request_channel -simply returns the first channel that satisfies the capability mask. Otherwise, -when the mask parameter is insufficient for specifying the necessary channel, -the filter_fn routine can be used to disposition the available channels in the -system. The filter_fn routine is called once for each free channel in the -system. Upon seeing a suitable channel filter_fn returns DMA_ACK which flags -that channel to be the return value from dma_request_channel. A channel -allocated via this interface is exclusive to the caller, until -dma_release_channel() is called. + + Channel allocation is slightly different in the slave DMA context, + client drivers typically need a channel from a particular DMA + controller only and even in some cases a specific channel is desired. + To request a channel dma_request_channel() API is used. + + Interface: + struct dma_chan *dma_request_channel(dma_cap_mask_t mask, + dma_filter_fn filter_fn, + void *filter_param); + where dma_filter_fn is defined as: + typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); + + The 'filter_fn' parameter is optional, but highly recommended for + slave and cyclic channels as they typically need to obtain a specific + DMA channel. + + When the optional 'filter_fn' parameter is NULL, dma_request_channel() + simply returns the first channel that satisfies the capability mask. + + Otherwise, the 'filter_fn' routine will be called once for each free + channel which has a capability in 'mask'. 'filter_fn' is expected to + return 'true' when the desired DMA channel is found. + + A channel allocated via this interface is exclusive to the caller, + until dma_release_channel() is called. 2. Set slave and controller specific parameters -Next step is always to pass some specific information to the DMA driver. Most of -the generic information which a slave DMA can use is in struct dma_slave_config. -It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA -burst lengths etc. If some DMA controllers have more parameters to be sent then -they should try to embed struct dma_slave_config in their controller specific -structure. That gives flexibility to client to pass more parameters, if -required. - -Interface: -int dmaengine_slave_config(struct dma_chan *chan, - struct dma_slave_config *config) + + Next step is always to pass some specific information to the DMA + driver. Most of the generic information which a slave DMA can use + is in struct dma_slave_config. This allows the clients to specify + DMA direction, DMA addresses, bus widths, DMA burst lengths etc + for the peripheral. + + If some DMA controllers have more parameters to be sent then they + should try to embed struct dma_slave_config in their controller + specific structure. That gives flexibility to client to pass more + parameters, if required. + + Interface: + int dmaengine_slave_config(struct dma_chan *chan, + struct dma_slave_config *config) + + Please see the dma_slave_config structure definition in dmaengine.h + for a detailed explaination of the struct members. Please note + that the 'direction' member will be going away as it duplicates the + direction given in the prepare call. 3. Get a descriptor for transaction -For slave usage the various modes of slave transfers supported by the -DMA-engine are: -slave_sg - DMA a list of scatter gather buffers from/to a peripheral -dma_cyclic - Perform a cyclic DMA operation from/to a peripheral till the + + For slave usage the various modes of slave transfers supported by the + DMA-engine are: + + slave_sg - DMA a list of scatter gather buffers from/to a peripheral + dma_cyclic - Perform a cyclic DMA operation from/to a peripheral till the operation is explicitly stopped. -The non NULL return of this transfer API represents a "descriptor" for the given -transaction. -Interface: -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)( + A non-NULL return of this transfer API represents a "descriptor" for + the given transaction. + + Interface: + struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)( struct dma_chan *chan, struct scatterlist *dst_sg, unsigned int dst_nents, struct scatterlist *src_sg, unsigned int src_nents, unsigned long flags); -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)( + + struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_data_direction direction); -4. Submit the transaction and wait for callback notification -To schedule the transaction to be scheduled by dma device, the "descriptor" -returned in above (3) needs to be submitted. -To tell the dma driver that a transaction is ready to be serviced, the -descriptor->submit() callback needs to be invoked. This chains the descriptor to -the pending queue. -The transactions in the pending queue can be activated by calling the -issue_pending API. If channel is idle then the first transaction in queue is -started and subsequent ones queued up. -On completion of the DMA operation the next in queue is submitted and a tasklet -triggered. The tasklet would then call the client driver completion callback -routine for notification, if set. -Interface: -void dma_async_issue_pending(struct dma_chan *chan); - -============================================================================== - -Additional usage notes for dma driver writers -1/ Although DMA engine specifies that completion callback routines cannot submit -any new operations, but typically for slave DMA subsequent transaction may not -be available for submit prior to callback routine being called. This requirement -is not a requirement for DMA-slave devices. But they should take care to drop -the spin-lock they might be holding before calling the callback routine + Once a descriptor has been obtained, the callback information can be + added and must then be submitted. Some DMA engine drivers may hold a + spinlock between a successful preparation and submission so it is + important that these two operations are closely paired. + + Note: + Although the async_tx API specifies that completion callback + routines cannot submit any new operations, this is not the + case for slave/cyclic DMA. + + For slave DMA, the subsequent transaction may not be available + for submission prior to callback function being invoked, so + slave DMA callbacks are permitted to prepare and submit a new + transaction. + + For cyclic DMA, a callback function may wish to terminate the + DMA via dmaengine_terminate_all(). + + Therefore, it is important that DMA engine drivers drop any + locks before calling the callback function which may cause a + deadlock. + + Note that callbacks will always be invoked from the DMA + engines tasklet, never from interrupt context. + +4. Submit the transaction + + Once the descriptor has been prepared and the callback information + added, it must be placed on the DMA engine drivers pending queue. + + Interface: + dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc) + + This returns a cookie can be used to check the progress of DMA engine + activity via other DMA engine calls not covered in this document. + + dmaengine_submit() will not start the DMA operation, it merely adds + it to the pending queue. For this, see step 5, dma_async_issue_pending. + +5. Issue pending DMA requests and wait for callback notification + + The transactions in the pending queue can be activated by calling the + issue_pending API. If channel is idle then the first transaction in + queue is started and subsequent ones queued up. + + On completion of each DMA operation, the next in queue is started and + a tasklet triggered. The tasklet will then call the client driver + completion callback routine for notification, if set. + + Interface: + void dma_async_issue_pending(struct dma_chan *chan); + +Further APIs: + +1. int dmaengine_terminate_all(struct dma_chan *chan) + + This causes all activity for the DMA channel to be stopped, and may + discard data in the DMA FIFO which hasn't been fully transferred. + No callback functions will be called for any incomplete transfers. + +2. int dmaengine_pause(struct dma_chan *chan) + + This pauses activity on the DMA channel without data loss. + +3. int dmaengine_resume(struct dma_chan *chan) + + Resume a previously paused DMA channel. It is invalid to resume a + channel which is not currently paused. + +4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan, + dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used) + + This can be used to check the status of the channel. Please see + the documentation in include/linux/dmaengine.h for a more complete + description of this API. + + This can be used in conjunction with dma_async_is_complete() and + the cookie returned from 'descriptor->submit()' to check for + completion of a specific DMA transaction. + + Note: + Not all DMA engine drivers can return reliable information for + a running DMA channel. It is recommended that DMA engine users + pause or stop (via dmaengine_terminate_all) the channel before + using this API.
PATCH 1/1 Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
Quoted 21 lines · Russell King - ARM Linux
Here's an updated patch.
8<----------
From: Russell King <[email protected]>
DMAEngine: Improve slave/cyclic documentationImprove the documentation for the slave and cyclic DMA engine support reformatting it for easier reading, adding further APIs, splitting it into five steps, and including references to the documentation in
dmaengine.h.Signed-off-by Russell King <[email protected]>--- Documentation/dmaengine.txt | 211 ++++++++++++++++++++++++++++++------------- 1 files changed, 146 insertions(+), 65 deletions(-)Documentation/dmaengine.txt +0
-0
Documentation/dmaengine.txt line 18
Quoted 10 lines
Documentation/dmaengine.txt +2
-1@@ -10,87 +10,168 @@ Below is a guide to device driver writers on how to use the Slave-DMA API of the DMA Engine. This is applicable only for slave DMA usage only. -The slave DMA usage consists of following steps +The slave DMA usage consists of following steps: 1. Allocate a DMA slave channel 2. Set slave and controller specific parameters 3. Get a descriptor for transaction 4. Submit the transaction and wait for callback notification +5. Issue pending requests
Thanks Russell,
Applied with change to 4 above. Moved "and wait for callback notification" to 5.
Quoted 228 lines
Documentation/dmaengine.txt +144
-641. Allocate a DMA slave channel -Channel allocation is slightly different in the slave DMA context, client -drivers typically need a channel from a particular DMA controller only and even -in some cases a specific channel is desired. To request a channel -dma_request_channel() API is used. - -Interface: -struct dma_chan *dma_request_channel(dma_cap_mask_t mask, - dma_filter_fn filter_fn, - void *filter_param); -where dma_filter_fn is defined as: -typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); - -When the optional 'filter_fn' parameter is set to NULL dma_request_channel -simply returns the first channel that satisfies the capability mask. Otherwise, -when the mask parameter is insufficient for specifying the necessary channel, -the filter_fn routine can be used to disposition the available channels in the -system. The filter_fn routine is called once for each free channel in the -system. Upon seeing a suitable channel filter_fn returns DMA_ACK which flags -that channel to be the return value from dma_request_channel. A channel -allocated via this interface is exclusive to the caller, until -dma_release_channel() is called. + + Channel allocation is slightly different in the slave DMA context, + client drivers typically need a channel from a particular DMA + controller only and even in some cases a specific channel is desired. + To request a channel dma_request_channel() API is used. + + Interface: + struct dma_chan *dma_request_channel(dma_cap_mask_t mask, + dma_filter_fn filter_fn, + void *filter_param); + where dma_filter_fn is defined as: + typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); + + The 'filter_fn' parameter is optional, but highly recommended for + slave and cyclic channels as they typically need to obtain a specific + DMA channel. + + When the optional 'filter_fn' parameter is NULL, dma_request_channel() + simply returns the first channel that satisfies the capability mask. + + Otherwise, the 'filter_fn' routine will be called once for each free + channel which has a capability in 'mask'. 'filter_fn' is expected to + return 'true' when the desired DMA channel is found. + + A channel allocated via this interface is exclusive to the caller, + until dma_release_channel() is called. 2. Set slave and controller specific parameters -Next step is always to pass some specific information to the DMA driver. Most of -the generic information which a slave DMA can use is in struct dma_slave_config. -It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA -burst lengths etc. If some DMA controllers have more parameters to be sent then -they should try to embed struct dma_slave_config in their controller specific -structure. That gives flexibility to client to pass more parameters, if -required. - -Interface: -int dmaengine_slave_config(struct dma_chan *chan, - struct dma_slave_config *config) + + Next step is always to pass some specific information to the DMA + driver. Most of the generic information which a slave DMA can use + is in struct dma_slave_config. This allows the clients to specify + DMA direction, DMA addresses, bus widths, DMA burst lengths etc + for the peripheral. + + If some DMA controllers have more parameters to be sent then they + should try to embed struct dma_slave_config in their controller + specific structure. That gives flexibility to client to pass more + parameters, if required. + + Interface: + int dmaengine_slave_config(struct dma_chan *chan, + struct dma_slave_config *config) + + Please see the dma_slave_config structure definition in dmaengine.h + for a detailed explaination of the struct members. Please note + that the 'direction' member will be going away as it duplicates the + direction given in the prepare call. 3. Get a descriptor for transaction -For slave usage the various modes of slave transfers supported by the -DMA-engine are: -slave_sg - DMA a list of scatter gather buffers from/to a peripheral -dma_cyclic - Perform a cyclic DMA operation from/to a peripheral till the + + For slave usage the various modes of slave transfers supported by the + DMA-engine are: + + slave_sg - DMA a list of scatter gather buffers from/to a peripheral + dma_cyclic - Perform a cyclic DMA operation from/to a peripheral till the operation is explicitly stopped. -The non NULL return of this transfer API represents a "descriptor" for the given -transaction. -Interface: -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)( + A non-NULL return of this transfer API represents a "descriptor" for + the given transaction. + + Interface: + struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)( struct dma_chan *chan, struct scatterlist *dst_sg, unsigned int dst_nents, struct scatterlist *src_sg, unsigned int src_nents, unsigned long flags); -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)( + + struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_data_direction direction); -4. Submit the transaction and wait for callback notification -To schedule the transaction to be scheduled by dma device, the "descriptor" -returned in above (3) needs to be submitted. -To tell the dma driver that a transaction is ready to be serviced, the -descriptor->submit() callback needs to be invoked. This chains the descriptor to -the pending queue. -The transactions in the pending queue can be activated by calling the -issue_pending API. If channel is idle then the first transaction in queue is -started and subsequent ones queued up. -On completion of the DMA operation the next in queue is submitted and a tasklet -triggered. The tasklet would then call the client driver completion callback -routine for notification, if set. -Interface: -void dma_async_issue_pending(struct dma_chan *chan); - -============================================================================== - -Additional usage notes for dma driver writers -1/ Although DMA engine specifies that completion callback routines cannot submit -any new operations, but typically for slave DMA subsequent transaction may not -be available for submit prior to callback routine being called. This requirement -is not a requirement for DMA-slave devices. But they should take care to drop -the spin-lock they might be holding before calling the callback routine + Once a descriptor has been obtained, the callback information can be + added and must then be submitted. Some DMA engine drivers may hold a + spinlock between a successful preparation and submission so it is + important that these two operations are closely paired. + + Note: + Although the async_tx API specifies that completion callback + routines cannot submit any new operations, this is not the + case for slave/cyclic DMA. + + For slave DMA, the subsequent transaction may not be available + for submission prior to callback function being invoked, so + slave DMA callbacks are permitted to prepare and submit a new + transaction. + + For cyclic DMA, a callback function may wish to terminate the + DMA via dmaengine_terminate_all(). + + Therefore, it is important that DMA engine drivers drop any + locks before calling the callback function which may cause a + deadlock. + + Note that callbacks will always be invoked from the DMA + engines tasklet, never from interrupt context. + +4. Submit the transaction + + Once the descriptor has been prepared and the callback information + added, it must be placed on the DMA engine drivers pending queue. + + Interface: + dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc) + + This returns a cookie can be used to check the progress of DMA engine + activity via other DMA engine calls not covered in this document. + + dmaengine_submit() will not start the DMA operation, it merely adds + it to the pending queue. For this, see step 5, dma_async_issue_pending. + +5. Issue pending DMA requests and wait for callback notification + + The transactions in the pending queue can be activated by calling the + issue_pending API. If channel is idle then the first transaction in + queue is started and subsequent ones queued up. + + On completion of each DMA operation, the next in queue is started and + a tasklet triggered. The tasklet will then call the client driver + completion callback routine for notification, if set. + + Interface: + void dma_async_issue_pending(struct dma_chan *chan); + +Further APIs: + +1. int dmaengine_terminate_all(struct dma_chan *chan) + + This causes all activity for the DMA channel to be stopped, and may + discard data in the DMA FIFO which hasn't been fully transferred. + No callback functions will be called for any incomplete transfers. + +2. int dmaengine_pause(struct dma_chan *chan) + + This pauses activity on the DMA channel without data loss. + +3. int dmaengine_resume(struct dma_chan *chan) + + Resume a previously paused DMA channel. It is invalid to resume a + channel which is not currently paused. + +4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan, + dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used) + + This can be used to check the status of the channel. Please see + the documentation in include/linux/dmaengine.h for a more complete + description of this API. + + This can be used in conjunction with dma_async_is_complete() and + the cookie returned from 'descriptor->submit()' to check for + completion of a specific DMA transaction. + + Note: + Not all DMA engine drivers can return reliable information for + a running DMA channel. It is recommended that DMA engine users + pause or stop (via dmaengine_terminate_all) the channel before + using this API._______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Signature · 2 lines
~Vinod Koul Intel Corp.
PATCH 1/1 Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
Quoted 34 lines · Vinod Koul
Quoted 26 lines · Russell King - ARM Linux
Here's an updated patch.
8<----------
From: Russell King <[email protected]>
DMAEngine: Improve slave/cyclic documentationImprove the documentation for the slave and cyclic DMA engine support reformatting it for easier reading, adding further APIs, splitting it into five steps, and including references to the documentation in
dmaengine.h.Signed-off-by Russell King <[email protected]>---
?Documentation/dmaengine.txt | ?211 ++++++++++++++++++++++++++++++------------- ?1 files changed, 146 insertions(+), 65 deletions(-)Documentation/dmaengine.txt +0
-0@@ -10,87 +10,168 @@?Below is a guide to device driver writers on how to use the Slave-DMA API of the ?DMA Engine. This is applicable only for slave DMA usage only.
Documentation/dmaengine.txt +1
-1-The slave DMA usage consists of following steps +The slave DMA usage consists of following steps:Quoted 5 lines
?1. Allocate a DMA slave channel
?2. Set slave and controller specific parameters ?3. Get a descriptor for transaction
?4. Submit the transaction and wait for callback notification +5. Issue pending requestsThanks Russell,
Quoted 3 lines
Applied with change to 4 above. Moved "and wait for callback notification" to 5.
Dear Vinod,
Since it came from the RMK, most probably it'll be the best.
But applying patches upon personal timeout seems very dangerous.
People not responding doesn't mean only either people agree completely or they don't care. Some might be interested but too busy with current tasks that they need time to check... please make some policy for such cases.
It already happened with the patch from Rob, which you probably have to revert.
IMHO, if nobody replied, maybe you could first ack the patch and wait for, say a week, before applying?
That way people will know they have to hurry if they care otherwise the patch is going upstream as such.
Thanks
-Jassi
PATCH 1/1 Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
Quoted 5 lines · Jassi Brar
Dear Vinod,
Since it came from the RMK, most probably it'll be the best.
But applying patches upon personal timeout seems very dangerous.
Ehh what? Is there any contention over this documentation patch?
It's not adding anything new, it's just documenting the facts as they stand today about the API and its use.
Quoted 11 lines
People not responding doesn't mean only either people agree completely or they don't care. Some might be interested but too busy with current tasks that they need time to check... please make some policy for such cases.
It already happened with the patch from Rob, which you probably have to revert.
IMHO, if nobody replied, maybe you could first ack the patch and wait for, say a week, before applying?
That way people will know they have to hurry if they care otherwise the patch is going upstream as such.
A week is far too long. That's how patches get lost and missed.
PATCH 1/1 Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
Quoted 8 lines · Russell King - ARM Linux
Quoted 5 lines · Jassi Brar
Dear Vinod,
?Since it came from the RMK, most probably it'll be the best.
But applying patches upon personal timeout seems very dangerous.
Ehh what? ?Is there any contention over this documentation patch?
I haven't yet read it... even after reading I would object only if I found your patch disturbing enough to disrupt my bowel movements. Which I don't think would be the case.
I just observed it is second time that Vinod applied a patch without any ack or prior alert.
Quoted 8 lines
Quoted 8 lines
People not responding doesn't mean only either people agree completely or they don't care. Some might be interested but too busy with current tasks that they need time to check... please make some policy for such cases.
It already happened with the patch from Rob, which you probably have to revert.
Quoted 7 lines
Quoted 4 lines
IMHO, if nobody replied, maybe you could first ack the patch and wait for, say a week, before applying?
That way people will know they have to hurry if they care otherwise the patch is going upstream as such.A week is far too long. ?That's how patches get lost and missed.
He may decide to wait shorter, but imho a week after the first ack isn't that long.
PATCH 1/1 Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
Quoted 9 lines · Jassi Brar
Quoted 7 lines · Russell King - ARM Linux
Quoted 5 lines · Jassi Brar
Dear Vinod,
?Since it came from the RMK, most probably it'll be the best.
But applying patches upon personal timeout seems very dangerous.
Quoted 7 lines
Quoted 1 line
Ehh what? ?Is there any contention over this documentation patch?
I haven't yet read it... even after reading I would object only if I found your patch disturbing enough to disrupt my bowel movements. Which I don't think would be the case.
I just observed it is second time that Vinod applied a patch without any ack or prior alert.
Applying patches without waiting for other Acks is absolutely a reasonable thing for a maintainer to do. The job of maintainership is to apply good judgement on when patches can immediately be applied (and therefore no longer consuming limited attention) and when patches need further acks.
g.
PATCH 1/1 Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
In reply to Jassi BrarQuoted 9 lines · Jassi Brar
Quoted 7 lines · Russell King - ARM Linux
Quoted 5 lines · Jassi Brar
Dear Vinod,
?Since it came from the RMK, most probably it'll be the best.
But applying patches upon personal timeout seems very dangerous.
Quoted 7 lines
Quoted 1 line
Ehh what? ?Is there any contention over this documentation patch?
I haven't yet read it... even after reading I would object only if I found your patch disturbing enough to disrupt my bowel movements. Which I don't think would be the case.
I just observed it is second time that Vinod applied a patch without any ack or prior alert.
That's what happens - no one says "I'm going to apply this patch" before they apply it. They just apply it to their tree and move on. Vinod, being the nominated maintainer for the slave DMA engine support has the authority to do that for that area of code.
PATCH 1/1 Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
In reply to Jassi BrarQuoted 5 lines · Jassi Brar
Quoted 3 lines · Russell King - ARM Linux
Quoted 2 lines · Jassi Brar
Dear Vinod,
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
Since it came from the RMK, most probably it'll be the best.
But applying patches upon personal timeout seems very dangerous.
Ehh what? Is there any contention over this documentation patch?
I haven't yet read it... even after reading I would object only if I found your patch disturbing enough to disrupt my bowel movements. Which I don't think would be the case.
Jassi,
Since this was a doc patch, I applied it soon enough, doesn't sound dangerous to me !
If you have any updates you would like, pls feel free to send a patch.
Quoted 3 lines
I just observed it is second time that Vinod applied a patch without any ack or prior alert.
And you can't ignore the fact that you had almost _two_ weeks to ack the patch from Rob, but....
You will get ample time to ack a patch, if you don't you can always point out and I will do the right thing, which in this case was to revert.
Quoted 23 lines
Quoted 9 lines
Quoted 9 lines
People not responding doesn't mean only either people agree completely or they don't care. Some might be interested but too busy with current tasks that they need time to check... please make some policy for such cases.
It already happened with the patch from Rob, which you probably have to revert.
Quoted 7 lines
Quoted 4 lines
IMHO, if nobody replied, maybe you could first ack the patch and wait for, say a week, before applying?
That way people will know they have to hurry if they care otherwise the patch is going upstream as such.A week is far too long. That's how patches get lost and missed.
He may decide to wait shorter, but imho a week after the first ack isn't that long.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
PATCH 1/1 Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
In reply to Vinod KoulQuoted 34 lines · Vinod Koul
Quoted 21 lines · Russell King - ARM Linux
Here's an updated patch.
8<----------
From: Russell King <[email protected]>
DMAEngine: Improve slave/cyclic documentationImprove the documentation for the slave and cyclic DMA engine support reformatting it for easier reading, adding further APIs, splitting it into five steps, and including references to the documentation in
dmaengine.h.Signed-off-by Russell King <[email protected]>--- Documentation/dmaengine.txt | 211 ++++++++++++++++++++++++++++++------------- 1 files changed, 146 insertions(+), 65 deletions(-)Documentation/dmaengine.txt +0
-0Documentation/dmaengine.txt line 18
Quoted 10 lines
Documentation/dmaengine.txt +2
-1@@ -10,87 +10,168 @@ Below is a guide to device driver writers on how to use the Slave-DMA API of the DMA Engine. This is applicable only for slave DMA usage only. -The slave DMA usage consists of following steps +The slave DMA usage consists of following steps: 1. Allocate a DMA slave channel 2. Set slave and controller specific parameters 3. Get a descriptor for transaction 4. Submit the transaction and wait for callback notification +5. Issue pending requestsThanks Russell,
Quoted 2 lines
Applied with change to 4 above. Moved "and wait for callback notification" to 5.
BTW, did you apply this one or the later one with the improved documentation for dma mapping and fixed interface for slave transfers etc. ?
PATCH 1/1 Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
Quoted 35 lines · Russell King - ARM Linux
Quoted 34 lines · Vinod Koul
Quoted 21 lines · Russell King - ARM Linux
Here's an updated patch.
8<----------
From: Russell King <[email protected]>
DMAEngine: Improve slave/cyclic documentationImprove the documentation for the slave and cyclic DMA engine support reformatting it for easier reading, adding further APIs, splitting it into five steps, and including references to the documentation in
dmaengine.h.Signed-off-by Russell King <[email protected]>--- Documentation/dmaengine.txt | 211 ++++++++++++++++++++++++++++++------------- 1 files changed, 146 insertions(+), 65 deletions(-)Documentation/dmaengine.txt +0
-0Documentation/dmaengine.txt line 18
Quoted 10 lines
Documentation/dmaengine.txt +2
-1@@ -10,87 +10,168 @@ Below is a guide to device driver writers on how to use the Slave-DMA API of the DMA Engine. This is applicable only for slave DMA usage only. -The slave DMA usage consists of following steps +The slave DMA usage consists of following steps: 1. Allocate a DMA slave channel 2. Set slave and controller specific parameters 3. Get a descriptor for transaction 4. Submit the transaction and wait for callback notification +5. Issue pending requestsThanks Russell,
Quoted 6 lines
Quoted 2 lines
Applied with change to 4 above. Moved "and wait for callback notification" to 5.
BTW, did you apply this one or the later one with the improved documentation for dma mapping and fixed interface for slave transfers etc. ?
I changed it to second one, not pushed yet.
I am rebasing the tree to 3.0. You should see updated version in tree later in the evening today
Signature · 1 line
~Vinod
PATCH 1/1 Improve slave/cyclic DMA engine documentation (was: [PATCH V4 04/14] DMA: PL330: Add DMA_CYCLIC capability)
In reply to Russell King - ARM LinuxQuoted 1 line · Russell King - ARM Linux
Here's an updated patch.
Sorry, another one. I've corrected the slave_sg preparation interface, and added a paragraph on preparing the scatterlist for the DMA operation, including mentioning which struct device should be used for this.
8<----------
From: Russell King <[email protected]>
DMAEngine: Improve slave/cyclic documentation
Improve the documentation for the slave and cyclic DMA engine support reformatting it for easier reading, adding further APIs, splitting it into five steps, and including references to the documentation in dmaengine.h.
--- Documentation/dmaengine.txt | 232 ++++++++++++++++++++++++++++++------------- 1 files changed, 163 insertions(+), 69 deletions(-)
Documentation/dmaengine.txt +163 -69
@@ -10,87 +10,181 @@ Below is a guide to device driver writers on how to use the Slave-DMA API of the DMA Engine. This is applicable only for slave DMA usage only. -The slave DMA usage consists of following steps +The slave DMA usage consists of following steps: 1. Allocate a DMA slave channel 2. Set slave and controller specific parameters 3. Get a descriptor for transaction 4. Submit the transaction and wait for callback notification +5. Issue pending requests 1. Allocate a DMA slave channel -Channel allocation is slightly different in the slave DMA context, client -drivers typically need a channel from a particular DMA controller only and even -in some cases a specific channel is desired. To request a channel -dma_request_channel() API is used. - -Interface: -struct dma_chan *dma_request_channel(dma_cap_mask_t mask, - dma_filter_fn filter_fn, - void *filter_param); -where dma_filter_fn is defined as: -typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); - -When the optional 'filter_fn' parameter is set to NULL dma_request_channel -simply returns the first channel that satisfies the capability mask. Otherwise, -when the mask parameter is insufficient for specifying the necessary channel, -the filter_fn routine can be used to disposition the available channels in the -system. The filter_fn routine is called once for each free channel in the -system. Upon seeing a suitable channel filter_fn returns DMA_ACK which flags -that channel to be the return value from dma_request_channel. A channel -allocated via this interface is exclusive to the caller, until -dma_release_channel() is called. + + Channel allocation is slightly different in the slave DMA context, + client drivers typically need a channel from a particular DMA + controller only and even in some cases a specific channel is desired. + To request a channel dma_request_channel() API is used. + + Interface: + struct dma_chan *dma_request_channel(dma_cap_mask_t mask, + dma_filter_fn filter_fn, + void *filter_param); + where dma_filter_fn is defined as: + typedef bool (*dma_filter_fn)(struct dma_chan *chan, void *filter_param); + + The 'filter_fn' parameter is optional, but highly recommended for + slave and cyclic channels as they typically need to obtain a specific + DMA channel. + + When the optional 'filter_fn' parameter is NULL, dma_request_channel() + simply returns the first channel that satisfies the capability mask. + + Otherwise, the 'filter_fn' routine will be called once for each free + channel which has a capability in 'mask'. 'filter_fn' is expected to + return 'true' when the desired DMA channel is found. + + A channel allocated via this interface is exclusive to the caller, + until dma_release_channel() is called. 2. Set slave and controller specific parameters -Next step is always to pass some specific information to the DMA driver. Most of -the generic information which a slave DMA can use is in struct dma_slave_config. -It allows the clients to specify DMA direction, DMA addresses, bus widths, DMA -burst lengths etc. If some DMA controllers have more parameters to be sent then -they should try to embed struct dma_slave_config in their controller specific -structure. That gives flexibility to client to pass more parameters, if -required. - -Interface: -int dmaengine_slave_config(struct dma_chan *chan, - struct dma_slave_config *config) + + Next step is always to pass some specific information to the DMA + driver. Most of the generic information which a slave DMA can use + is in struct dma_slave_config. This allows the clients to specify + DMA direction, DMA addresses, bus widths, DMA burst lengths etc + for the peripheral. + + If some DMA controllers have more parameters to be sent then they + should try to embed struct dma_slave_config in their controller + specific structure. That gives flexibility to client to pass more + parameters, if required. + + Interface: + int dmaengine_slave_config(struct dma_chan *chan, + struct dma_slave_config *config) + + Please see the dma_slave_config structure definition in dmaengine.h + for a detailed explaination of the struct members. Please note + that the 'direction' member will be going away as it duplicates the + direction given in the prepare call. 3. Get a descriptor for transaction -For slave usage the various modes of slave transfers supported by the -DMA-engine are: -slave_sg - DMA a list of scatter gather buffers from/to a peripheral -dma_cyclic - Perform a cyclic DMA operation from/to a peripheral till the + + For slave usage the various modes of slave transfers supported by the + DMA-engine are: + + slave_sg - DMA a list of scatter gather buffers from/to a peripheral + dma_cyclic - Perform a cyclic DMA operation from/to a peripheral till the operation is explicitly stopped. -The non NULL return of this transfer API represents a "descriptor" for the given -transaction. - -Interface: -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_sg)( - struct dma_chan *chan, - struct scatterlist *dst_sg, unsigned int dst_nents, - struct scatterlist *src_sg, unsigned int src_nents, + + A non-NULL return of this transfer API represents a "descriptor" for + the given transaction. + + Interface: + struct dma_async_tx_descriptor *(*chan->device->device_prep_slave_sg)( + struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sg_len, enum dma_data_direction direction, unsigned long flags); -struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)( + + struct dma_async_tx_descriptor *(*chan->device->device_prep_dma_cyclic)( struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, size_t period_len, enum dma_data_direction direction); -4. Submit the transaction and wait for callback notification -To schedule the transaction to be scheduled by dma device, the "descriptor" -returned in above (3) needs to be submitted. -To tell the dma driver that a transaction is ready to be serviced, the -descriptor->submit() callback needs to be invoked. This chains the descriptor to -the pending queue. -The transactions in the pending queue can be activated by calling the -issue_pending API. If channel is idle then the first transaction in queue is -started and subsequent ones queued up. -On completion of the DMA operation the next in queue is submitted and a tasklet -triggered. The tasklet would then call the client driver completion callback -routine for notification, if set. -Interface: -void dma_async_issue_pending(struct dma_chan *chan); - -============================================================================== - -Additional usage notes for dma driver writers -1/ Although DMA engine specifies that completion callback routines cannot submit -any new operations, but typically for slave DMA subsequent transaction may not -be available for submit prior to callback routine being called. This requirement -is not a requirement for DMA-slave devices. But they should take care to drop -the spin-lock they might be holding before calling the callback routine + The peripheral driver is expected to have mapped the scatterlist for + the DMA operation prior to calling device_prep_slave_sg, and must + keep the scatterlist mapped until the DMA operation has completed. + The scatterlist must be mapped using the DMA struct device. So, + normal setup should look like this: + + nr_sg = dma_map_sg(chan->device->dev, sgl, sg_len); + if (nr_sg == 0) + /* error */ + + desc = chan->device->device_prep_slave_sg(chan, sgl, nr_sg, + direction, flags); + + Once a descriptor has been obtained, the callback information can be + added and the descriptor must then be submitted. Some DMA engine + drivers may hold a spinlock between a successful preparation and + submission so it is important that these two operations are closely + paired. + + Note: + Although the async_tx API specifies that completion callback + routines cannot submit any new operations, this is not the + case for slave/cyclic DMA. + + For slave DMA, the subsequent transaction may not be available + for submission prior to callback function being invoked, so + slave DMA callbacks are permitted to prepare and submit a new + transaction. + + For cyclic DMA, a callback function may wish to terminate the + DMA via dmaengine_terminate_all(). + + Therefore, it is important that DMA engine drivers drop any + locks before calling the callback function which may cause a + deadlock. + + Note that callbacks will always be invoked from the DMA + engines tasklet, never from interrupt context. + +4. Submit the transaction + + Once the descriptor has been prepared and the callback information + added, it must be placed on the DMA engine drivers pending queue. + + Interface: + dma_cookie_t dmaengine_submit(struct dma_async_tx_descriptor *desc) + + This returns a cookie can be used to check the progress of DMA engine + activity via other DMA engine calls not covered in this document. + + dmaengine_submit() will not start the DMA operation, it merely adds + it to the pending queue. For this, see step 5, dma_async_issue_pending. + +5. Issue pending DMA requests and wait for callback notification + + The transactions in the pending queue can be activated by calling the + issue_pending API. If channel is idle then the first transaction in + queue is started and subsequent ones queued up. + + On completion of each DMA operation, the next in queue is started and + a tasklet triggered. The tasklet will then call the client driver + completion callback routine for notification, if set. + + Interface: + void dma_async_issue_pending(struct dma_chan *chan); + +Further APIs: + +1. int dmaengine_terminate_all(struct dma_chan *chan) + + This causes all activity for the DMA channel to be stopped, and may + discard data in the DMA FIFO which hasn't been fully transferred. + No callback functions will be called for any incomplete transfers. + +2. int dmaengine_pause(struct dma_chan *chan) + + This pauses activity on the DMA channel without data loss. + +3. int dmaengine_resume(struct dma_chan *chan) + + Resume a previously paused DMA channel. It is invalid to resume a + channel which is not currently paused. + +4. enum dma_status dma_async_is_tx_complete(struct dma_chan *chan, + dma_cookie_t cookie, dma_cookie_t *last, dma_cookie_t *used) + + This can be used to check the status of the channel. Please see + the documentation in include/linux/dmaengine.h for a more complete + description of this API. + + This can be used in conjunction with dma_async_is_complete() and + the cookie returned from 'descriptor->submit()' to check for + completion of a specific DMA transaction. + + Note: + Not all DMA engine drivers can return reliable information for + a running DMA channel. It is recommended that DMA engine users + pause or stop (via dmaengine_terminate_all) the channel before + using this API.
PATCH v4 4/14 DMA: PL330: Add DMA_CYCLIC capability
In reply to Vinod KoulVinod Koul Wrote:
Quoted 33 lines
Sent: Monday, July 25, 2011 7:48 PM
To: Russell King - ARM Linux
Cc: vinod.koul at intel.com; Boojin Kim; 'Kukjin Kim'; 'Jassi Brar'; 'Grant Likely'; linux-samsung-soc at vger.kernel.org; 'Mark Brown'; 'Dan Williams'; linux-arm-kernel at lists.infradead.org
Subject: Re: [PATCH V4 04/14] DMA: PL330: AddDMA_CYCLICcapabilityQuoted 11 lines · Russell King - ARM Linux
Quoted 10 lines · Boojin Kim
Quoted 10 lines · Boojin Kim
Quoted 8 lines
drivers/dma/pl330.c +8
-0+static void pl330_tasklet_cyclic (unsigned long data) +{ +struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; +struct dma_pl330_desc *desc, *_dt; +unsigned long flags; +LIST_HEAD (list); + +spin_lock_irqsave (&pch->lock, flags);...
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
drivers/dma/pl330.c static inline void fill_queue(struct dma_pl330_chan *pch) · line 220
Quoted 3 lines
drivers/dma/pl330.c +3
-0+ callback = desc->txd.callback; +if (callback) +callback (desc->txd.callback_param);On this again - what if the callback wants to terminate the DMA
activity
Quoted 1 line
Quoted 1 line
Quoted 1 line
because there's no more audio data to be sent/received from the
device?
Quoted 2 lines
Quoted 2 lines
Do you mean what is happened if the
callback()is called afterchannel is
Quoted 2 lines
Quoted 2 lines
terminated ?
Or What is happened ifCallback()calls 'dma_release_channel()' toterminate
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
DMA?
No. I mean what if the callback wants to call
dmaengine_terminate_all().
you are supposed to drop the lock here, that way callback can call any DMA API, otherwise it will result in deadlock.
This make me wonder you haven't read the documentation at all, please ensure you have readDocumentation/dmaengine.txtbefore next posting
I found the deadlock problem that you post. I will fix it and read the document again.
Quoted 37 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
drivers/dma/pl330.c static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
Quoted 4 lines
drivers/dma/pl330.c +3
-0+if (!pch->cyclic_task) { + pch->cyclic_task = + kmalloc(sizeof(struct tasklet_struct),
GFP_KERNEL);Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
drivers/dma/pl330.c static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len) · line 649
Quoted 2 lines
drivers/dma/pl330.c +2
-0+tasklet_init (pch->cyclic_task, + pl330_tasklet_cyclic, (unsigned int )pch);Here you allocate memory for the cyclic task. Above you set this
pointer
Quoted 1 line
Quoted 1 line
Quoted 1 line
to NULL. That sounds like a memory leak to me. Why are you
kmallocing
Quoted 1 line
Quoted 1 line
Quoted 1 line
this memory - why can't it be part of the
dma_pl330_chanstructure? It's
Quoted 6 lines
Quoted 6 lines
Quoted 1 line
only 28 bytes.
It's my mistake. I should have been free of the memory.
And the reason why I use kmalloc for '
cyclic_task' is following. This memory size for 'cyclic_tasklet' is the 896 bytes ( = thenumber of
Quoted 1 line
Quoted 1 line
channel *
sizeof(struct tasklet_struct)= 32*28) for each DMAC. AndThis
Quoted 2 lines
Quoted 2 lines
memory size is increased according to the number of DMAC. And Samsung has the DMAC that is dedicated for Mem-to-Mem
operation. If I
Quoted 1 line
Quoted 1 line
make '
cyclic_task' be part ofdma_pl330_chan, this DMAC that isdedicated
Quoted 4 lines
Quoted 2 lines
for Mem-to-Mem operation should hold unused data.
So, I think it's loss that all dma channels hold own 'cyclic_task'.Could you re-use the tasklet that already exists?
--
~Vinod Koul
Intel Corp.
PATCH v4 4/14 DMA: PL330: Add DMA_CYCLIC capability
In reply to Russell King - ARM LinuxRussell King - ARM Linux Wrote:
Quoted 28 lines
Sent: Monday, July 25, 2011 7:36 PM
To: Boojin Kim
Cc: linux-arm-kernel at lists.infradead.org; linux-samsung- soc at vger.kernel.org; 'Kukjin Kim'; 'Vinod Koul'; 'Jassi Brar'; 'Grant Likely'; 'Mark Brown'; 'Dan Williams'
Subject: Re: [PATCH V4 04/14] DMA: PL330: AddDMA_CYCLICcapabilityQuoted 10 lines · Boojin Kim
Quoted 10 lines · Boojin Kim
Quoted 8 lines
drivers/dma/pl330.c +8
-0+static void pl330_tasklet_cyclic (unsigned long data) +{ +struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; +struct dma_pl330_desc *desc, *_dt; +unsigned long flags; +LIST_HEAD (list); + +spin_lock_irqsave (&pch->lock, flags);...
Quoted 5 lines
Quoted 5 lines
drivers/dma/pl330.c static inline void fill_queue(struct dma_pl330_chan *pch) · line 220
Quoted 3 lines
drivers/dma/pl330.c +3
-0+ callback = desc->txd.callback; +if (callback) +callback (desc->txd.callback_param);On this again - what if the callback wants to terminate the DMA
activity
Quoted 1 line
Quoted 1 line
because there's no more audio data to be sent/received from the
device?
Quoted 2 lines
Do you mean what is happened if the
callback()is called after
Quoted 8 lines
channel is
Quoted 2 lines
terminated ?
Or What is happened ifCallback()calls 'dma_release_channel()' toterminate
Quoted 1 line
DMA?
No. I mean what if the callback wants to call
dmaengine_terminate_all().
I found the deadlock problem that you and Vinod post. I will fix it.
Quoted 25 lines
Quoted 4 lines
Quoted 4 lines
drivers/dma/pl330.c static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len)
Quoted 4 lines
drivers/dma/pl330.c +3
-0+if (!pch->cyclic_task) { + pch->cyclic_task = + kmalloc(sizeof(struct tasklet_struct),
GFP_KERNEL);Quoted 4 lines
Quoted 4 lines
drivers/dma/pl330.c static inline int get_burst_len(struct dma_pl330_desc *desc, size_t len) · line 649
Quoted 2 lines
drivers/dma/pl330.c +2
-0+tasklet_init (pch->cyclic_task, + pl330_tasklet_cyclic, (unsigned int )pch);Here you allocate memory for the cyclic task. Above you set this
pointer
Quoted 1 line
Quoted 1 line
to NULL. That sounds like a memory leak to me. Why are you
kmallocing
Quoted 1 line
Quoted 1 line
this memory - why can't it be part of the
dma_pl330_chanstructure?It's
Quoted 6 lines
Quoted 1 line
only 28 bytes.
It's my mistake. I should have been free of the memory.
And the reason why I use kmalloc for '
cyclic_task' is following. This memory size for 'cyclic_tasklet' is the 896 bytes ( = thenumber of
Quoted 1 line
channel *
sizeof(struct tasklet_struct)= 32*28) for each DMAC. AndThis
Quoted 2 lines
memory size is increased according to the number of DMAC. And Samsung has the DMAC that is dedicated for Mem-to-Mem operation.
Quoted 7 lines
If I
Quoted 1 line
make '
cyclic_task' be part ofdma_pl330_chan, this DMAC that isdedicated
Quoted 2 lines
for Mem-to-Mem operation should hold unused data.
So, I think it's loss that all dma channels hold own 'cyclic_task'.Could you re-use the tasklet that already exists?
Yes, It can be re-used. But, This tasklet should be initialized on each request by using 'tasklet_init()' because it needs the own channel as its parameter.
PATCH v4 4/14 DMA: PL330: Add DMA_CYCLIC capability
In reply to Boojin KimQuoted 22 lines · Boojin Kim
This patch adds
DMA_CYCLICcapability that is used for audio driver. DMA driver withDMA_CYCLICcapability reuses the dma requests that were submitted throughtx_submit().Signed-off-by Boojin Kim <[email protected]>---
?drivers/dma/pl330.c | ?111 +++++++++++++++++++++++++++++++++++++++++++++++++++ ?1 files changed, 111 insertions(+), 0 deletions(-)drivers/dma/pl330.c +0
-0@@ -69,6 +69,11 @@ struct dma_pl330_chan {? ? ? ? * NULL if the channel is available to be acquired. ? ? ? ? */
? ? ? ?void*pl330_chid;drivers/dma/pl330.c +5
-0+ + ? ? ? /* taks for cyclic capability */ + ? ? ? struct tasklet_struct *cyclic_task; + + ? ? ? bool cyclic;
Quoted 1 line
?};
We already have a tasklet_struct member here.
This 'cyclic' flag can indicate if we are doing cyclic or serial transfers. So, this cyclic_task seems unnecessary.
Quoted 24 lines
drivers/dma/pl330.c +24
-0+static void pl330_tasklet_cyclic (unsigned long data) +{ + ? ? ? struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; + ? ? ? struct dma_pl330_desc *desc, *_dt; + ? ? ? unsigned long flags; + ? ? ? LIST_HEAD(list); + + ? ? ? spin_lock_irqsave(&pch->lock, flags); + + ? ? ? /* Pick up ripe tomatoes */ + ? ? ? list_for_each_entry_safe(desc, _dt, &pch->work_list, node) + ? ? ? ? ? ? ? if (desc->status == DONE) { + ? ? ? ? ? ? ? ? ? ? ? dma_async_tx_callback callback; + + ? ? ? ? ? ? ? ? ? ? ? list_move_tail(&desc->node, &pch->work_list); + ? ? ? ? ? ? ? ? ? ? ? pch->completed = desc->txd.cookie; + + ? ? ? ? ? ? ? ? ? ? ? desc->status = PREP; + + ? ? ? ? ? ? ? ? ? ? ? /* Try to submit a req imm. + ? ? ? ? ? ? ? ? ? ? ? next to the last completed cookie */ + ? ? ? ? ? ? ? ? ? ? ? fill_queue(pch); + + ? ? ? ? ? ? ? ? ? ? ? /* Make sure the PL330 Channel thread is active */
drivers/dma/pl330.c
Quoted 10 lines
drivers/dma/pl330.c +10
-0+ ? ? ? ? ? ? ? ? ? ? ? pl330_chan_ctrl(pch->pl330_chid, PL330_OP_START); + + ? ? ? ? ? ? ? ? ? ? ? callback = desc->txd.callback; + ? ? ? ? ? ? ? ? ? ? ? if (callback) + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? callback(desc->txd.callback_param); + + ? ? ? ? ? ? ? } + + ? ? ? spin_unlock_irqrestore(&pch->lock, flags); +}
Please merge this with pl330_tasklet and use 'cyclic' flag to differentiate.
drivers/dma/pl330.c static void dma_pl330_rqcb(void *token, enum pl330_op_err err) · line 273
Quoted 8 lines
drivers/dma/pl330.c +3
-0@@ -227,6 +267,9 @@ static void dma_pl330_rqcb(void *token, enum pl330_op_err err) ? ? ? ?spin_unlock_irqrestore(&pch->lock, flags); + ? ? ? if (pch->cyclic_task) + ? ? ? ? ? ? ? tasklet_schedule(pch->cyclic_task); + ? ? ? else ? ? ? ?tasklet_schedule(&pch->task);
A tab here please, and check for 'cyclic' flag.
Quoted 5 lines
drivers/dma/pl330.c +1
-0@@ -316,6 +359,15 @@ static void pl330_free_chan_resources(struct dma_chan *chan) ? ? ? ?pl330_release_channel(pch->pl330_chid); ? ? ? ?pch->pl330_chid = NULL; + ? ? ? if (pch->cyclic) {
drivers/dma/pl330.c static void pl330_free_chan_resources(struct dma_chan *chan) · line 372
Quoted 10 lines
drivers/dma/pl330.c +8
-0+ ? ? ? ? ? ? ? pch->cyclic = false; + ? ? ? ? ? ? ? list_splice_tail_init(&pch->work_list, &pch->dmac->desc_pool); + ? ? ? ? ? ? ? if (pch->cyclic_task) { + ? ? ? ? ? ? ? ? ? ? ? tasklet_kill(pch->cyclic_task); + ? ? ? ? ? ? ? ? ? ? ? pch->cyclic_task = NULL; + ? ? ? ? ? ? ? } + ? ? ? } + ? ? ? ?spin_unlock_irqrestore(&pch->lock, flags); ?}
To be explicit, please initialize 'cyclic' flag to false in pl330_alloc_chan_resources
PATCH v4 4/14 DMA: PL330: Add DMA_CYCLIC capability
Jassi Brar Wrote:
Quoted 28 lines
Sent: Monday, July 25, 2011 8:24 PM
To: Boojin Kim
Cc: linux-arm-kernel at lists.infradead.org; linux-samsung- soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant Likely; Mark Brown
Subject: Re: [PATCH V4 04/14] DMA: PL330: AddDMA_CYCLICcapabilityQuoted 7 lines · Boojin Kim
This patch adds
DMA_CYCLICcapability that is used for audio driver. DMA driver withDMA_CYCLICcapability reuses the dma requests that were submitted throughtx_submit().Signed-off-by Boojin Kim <[email protected]>--- drivers/dma/pl330.c | 111+++++++++++++++++++++++++++++++++++++++++++++++++++
Quoted 11 lines
1 files changed, 111 insertions(+), 0 deletions(-)drivers/dma/pl330.c +1
-0@@ -69,6 +69,11 @@ struct dma_pl330_chan {* NULL if the channel is available to be acquired. */ void *pl330_chid; +
Quoted 8 lines
drivers/dma/pl330.c struct dma_pl330_chan { · line 77
Quoted 5 lines
drivers/dma/pl330.c +4
-0+/* taks for cyclic capability */ +struct tasklet_struct *cyclic_task; + +bool cyclic; };We already have a
tasklet_structmember here.
This 'cyclic' flag can indicate if we are doing cyclic or serial transfers. So, thiscyclic_taskseems unnecessary.
I will change cyclic operation base on your comment. Cyclic_task will be removed.
Quoted 69 lines
Quoted 15 lines
drivers/dma/pl330.c +14
-0+static void pl330_tasklet_cyclic (unsigned long data) +{ +struct dma_pl330_chan *pch = (struct dma_pl330_chan *)data; +struct dma_pl330_desc *desc, *_dt; +unsigned long flags; +LIST_HEAD (list); + +spin_lock_irqsave (&pch->lock, flags); + +/* Pick up ripe tomatoes */ +list_for_each_entry_safe (desc, _dt, &pch->work_list, node) +if (desc->status ==DONE ) { +dma_async_tx_callback callback; +drivers/dma/pl330.c static inline void fill_queue(struct dma_pl330_chan *pch)
Quoted 10 lines
drivers/dma/pl330.c +10
-0+list_move_tail (&desc->node, &pch->work_list); + pch->completed = desc->txd.cookie; + + desc->status =PREP ; + +/* Try to submit a req imm. +next to the last completed cookie */ +fill_queue (pch); + +/* Make sure the PL330 Channel thread is active */
Quoted 1 line
+ pl330_chan_ctrl(pch->pl330_chid,
PL330_OP_START);drivers/dma/pl330.c static inline void fill_queue(struct dma_pl330_chan *pch) · line 225
Quoted 9 lines
drivers/dma/pl330.c +9
-0+ + callback = desc->txd.callback; +if (callback) +callback (desc->txd.callback_param); + + } + +spin_unlock_irqrestore (&pch->lock, flags); +}Please merge this with
pl330_taskletand use 'cyclic' flag to differentiate.drivers/dma/pl330.c static void dma_pl330_rqcb(void *token, enum
Quoted 1 line
drivers/dma/pl330.c +0
-0@@ -227,6 +267,9 @@ static void dma_pl330_rqcb(void *token, enum
pl330_op_errerr)drivers/dma/pl330.c static void dma_pl330_rqcb(void *token, enum pl330_op_err err) · line 273
Quoted 7 lines
drivers/dma/pl330.c +3
-0spin_unlock_irqrestore (&pch->lock, flags); +if (pch->cyclic_task) +tasklet_schedule (pch->cyclic_task); +else tasklet_schedule (&pch->task);A tab here please, and check for 'cyclic' flag.
drivers/dma/pl330.c static void pl330_free_chan_resources(struct
Quoted 1 line
drivers/dma/pl330.c +0
-0@@ -316,6 +359,15 @@ static void pl330_free_chan_resources(struct
dma_chan*chan)Quoted 5 lines
drivers/dma/pl330.c +2
-0pl330_release_channel (pch->pl330_chid); pch->pl330_chid =NULL ; +if (pch->cyclic) { + pch->cyclic = false;drivers/dma/pl330.c static void pl330_free_chan_resources(struct dma_chan *chan) · line 372
Quoted 10 lines
drivers/dma/pl330.c +7
-0+list_splice_tail_init (&pch->work_list, &pch->dmac- desc_pool); +if (pch->cyclic_task) { +tasklet_kill (pch->cyclic_task); + pch->cyclic_task =NULL ; + } + } +spin_unlock_irqrestore (&pch->lock, flags); }
Quoted 2 lines
To be explicit, please initialize 'cyclic' flag to false in
pl330_alloc_chan_resources
I will address your comment.
PATCH v4 5/14 ARM: SAMSUNG: Update to use PL330-DMA driver
In reply to Boojin KimThis patch adds to support PL330-DMA driver on DMADEVICE for S5P SoCs.
---
arch/arm/mach-exynos4/include/mach/dma.h | 4 +-
arch/arm/mach-s5p64x0/include/mach/dma.h | 2 +-
arch/arm/mach-s5pc100/include/mach/dma.h | 2 +-
arch/arm/mach-s5pv210/include/mach/dma.h | 2 +-
arch/arm/plat-samsung/Kconfig | 8 +++++++
.../include/plat/{s3c-dma-pl330.h => dma-pl330.h} | 21 +++++++++++++------
.../plat-samsung/include/plat/s3c-pl330-pdata.h | 2 +-
7 files changed, 28 insertions(+), 13 deletions(-)
rename arch/arm/plat-samsung/include/plat/{s3c-dma-pl330.h => dma-pl330.h} (84%)arch/arm/mach-exynos4/include/mach/dma.h +2 -2
@@ -20,7 +20,7 @@#ifndef __MACH_DMA_H#define __MACH_DMA_H -/* This platform uses the common S3C DMA API driver for PL330 */ -#include <plat/s3c-dma-pl330.h> +/* This platform uses the common DMA API driver for PL330 */ +#include <plat/dma-pl330.h> #endif /* __MACH_DMA_H */
arch/arm/mach-s5p64x0/include/mach/dma.h +1 -1
@@ -21,6 +21,6 @@#define __MACH_DMA_H/* This platform uses the common S3C DMA API driver for PL330 */ -#include <plat/s3c-dma-pl330.h> +#include <plat/dma-pl330.h> #endif /* __MACH_DMA_H */
arch/arm/mach-s5pc100/include/mach/dma.h +1 -1
@@ -21,6 +21,6 @@#define __MACH_DMA_H/* This platform uses the common S3C DMA API driver for PL330 */ -#include <plat/s3c-dma-pl330.h> +#include <plat/dma-pl330.h> #endif /* __MACH_DMA_H */
arch/arm/mach-s5pv210/include/mach/dma.h +1 -1
@@ -21,6 +21,6 @@#define __MACH_DMA_H/* This platform uses the common S3C DMA API driver for PL330 */ -#include <plat/s3c-dma-pl330.h> +#include <plat/dma-pl330.h> #endif /* __MACH_DMA_H */
arch/arm/plat-samsung/Kconfig +8 -0
@@ -300,6 +300,14 @@ config S3C_PL330_DMA help S3C DMA API Driver for PL330 DMAC. +config DMADEV_PL330 + bool + select DMADEVICES + select PL330_DMA + select ARM_AMBA + help + Use DMA device engine for PL330 DMAC. + comment "Power management" config SAMSUNG_PM_DEBUG
arch/arm/plat-samsung/include/plat/dma-pl330.h renamed from arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h +14 -7
@@ -8,19 +8,18 @@* (at your option) any later version. */ -#ifndef __S3C_DMA_PL330_H_ -#define __S3C_DMA_PL330_H_ - -#define S3C2410_DMAF_AUTOSTART (1 << 0) -#define S3C2410_DMAF_CIRCULAR (1 << 1) +#ifndef __DMA_PL330_H_ +#define __DMA_PL330_H_ __FILE__ +#define S3C2410_DMAF_AUTOSTART (1 << 0) +#define S3C2410_DMAF_CIRCULAR (1 << 1)/* * PL330 can assign any channel to communicate with * any of the peripherals attched to the DMAC. * For the sake of consistency across client drivers, * We keep the channel names unchanged and only add * missing peripherals are added. -* Order is not important since S3C PL330 API driver +* Order is not important since DMA PL330 API driver * use these just as IDs. */ enum dma_ch {
@@ -84,6 +83,14 @@ enum dma_ch {DMACH_SLIMBUS4_TX ,DMACH_SLIMBUS5_RX ,DMACH_SLIMBUS5_TX , +DMACH_MTOM_0 , +DMACH_MTOM_1 , +DMACH_MTOM_2 , +DMACH_MTOM_3 , +DMACH_MTOM_4 , +DMACH_MTOM_5 , +DMACH_MTOM_6 , +DMACH_MTOM_7 ,/* END Marker, also used to denote a reserved channel */ DMACH_MAX, };
@@ -95,4 +102,4 @@ static inline bool s3c_dma_has_circular(void)#include <plat/dma.h> -#endif /* __S3C_DMA_PL330_H_ */ +#endif /* __DMA_PL330_H_ */
arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h +1 -1
@@ -12,7 +12,7 @@#ifndef __S3C_PL330_PDATA_H#define __S3C_PL330_PDATA_H -#include <plat/s3c-dma-pl330.h> +#include <plat/dma-pl330.h> /* * Every PL330 DMAC has max 32 peripheral interfaces,
Signature · 1 line
1.7.1
PATCH v4 5/14 ARM: SAMSUNG: Update to use PL330-DMA driver
Quoted 95 lines · Boojin Kim
This patch adds to support PL330-DMA driver on DMADEVICE for S5P SoCs.
Signed-off-by Boojin Kim <[email protected]>Signed-off-by Kukjin Kim <[email protected]>--- arch/arm/mach-exynos4/include/mach/dma.h | 4 +- arch/arm/mach-s5p64x0/include/mach/dma.h | 2 +- arch/arm/mach-s5pc100/include/mach/dma.h | 2 +- arch/arm/mach-s5pv210/include/mach/dma.h | 2 +- arch/arm/plat-samsung/Kconfig | 8 +++++++ .../include/plat/{s3c-dma-pl330.h => dma-pl330.h} | 21 +++++++++++++------ .../plat-samsung/include/plat/s3c-pl330-pdata.h | 2 +- 7 files changed, 28 insertions(+), 13 deletions(-) rename arch/arm/plat-samsung/include/plat/{s3c-dma-pl330.h => dma-pl330.h} (84%)arch/arm/mach-exynos4/include/mach/dma.h +2
-2@@ -20,7 +20,7 @@#ifndef __MACH_DMA_H#define __MACH_DMA_H -/* This platform uses the common S3C DMA API driver for PL330 */ -#include <plat/s3c-dma-pl330.h> +/* This platform uses the common DMA API driver for PL330 */ +#include <plat/dma-pl330.h> #endif /* __MACH_DMA_H */ arch/arm/mach-s5p64x0/include/mach/dma.h +1
-1@@ -21,6 +21,6 @@#define __MACH_DMA_H/* This platform uses the common S3C DMA API driver for PL330 */ -#include <plat/s3c-dma-pl330.h> +#include <plat/dma-pl330.h> #endif /* __MACH_DMA_H */ arch/arm/mach-s5pc100/include/mach/dma.h +1
-1@@ -21,6 +21,6 @@#define __MACH_DMA_H/* This platform uses the common S3C DMA API driver for PL330 */ -#include <plat/s3c-dma-pl330.h> +#include <plat/dma-pl330.h> #endif /* __MACH_DMA_H */ arch/arm/mach-s5pv210/include/mach/dma.h +1
-1@@ -21,6 +21,6 @@#define __MACH_DMA_H/* This platform uses the common S3C DMA API driver for PL330 */ -#include <plat/s3c-dma-pl330.h> +#include <plat/dma-pl330.h> #endif /* __MACH_DMA_H */ arch/arm/plat-samsung/Kconfig +8
-0@@ -300,6 +300,14 @@ config S3C_PL330_DMA help S3C DMA API Driver for PL330 DMAC. +config DMADEV_PL330 + bool + select DMADEVICES + select PL330_DMA + select ARM_AMBA + help + Use DMA device engine for PL330 DMAC. + comment "Power management" config SAMSUNG_PM_DEBUGarch/arm/plat-samsung/include/plat/dma-pl330.h renamed from arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h +0
-0@@ -8,19 +8,18 @@* (at your option) any later version. */
arch/arm/plat-samsung/include/plat/dma-pl330.h line 15
Quoted 10 lines
arch/arm/plat-samsung/include/plat/dma-pl330.h renamed from arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h +4
-5-#ifndef __S3C_DMA_PL330_H_ -#define __S3C_DMA_PL330_H_ - -#define S3C2410_DMAF_AUTOSTART (1 << 0) -#define S3C2410_DMAF_CIRCULAR (1 << 1) +#ifndef __DMA_PL330_H_ +#define __DMA_PL330_H_ __FILE__ +#define S3C2410_DMAF_AUTOSTART (1 << 0) +#define S3C2410_DMAF_CIRCULAR (1 << 1)
this looks like bogus diff and can be avoided
Quoted 45 lines
arch/arm/plat-samsung/include/plat/dma-pl330.h renamed from arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h +10
-2/* * PL330 can assign any channel to communicate with * any of the peripherals attched to the DMAC. * For the sake of consistency across client drivers, * We keep the channel names unchanged and only add * missing peripherals are added. -* Order is not important since S3C PL330 API driver +* Order is not important since DMA PL330 API driver * use these just as IDs. */ enum dma_ch {@@ -84,6 +83,14 @@ enum dma_ch {DMACH_SLIMBUS4_TX ,DMACH_SLIMBUS5_RX ,DMACH_SLIMBUS5_TX , +DMACH_MTOM_0 , +DMACH_MTOM_1 , +DMACH_MTOM_2 , +DMACH_MTOM_3 , +DMACH_MTOM_4 , +DMACH_MTOM_5 , +DMACH_MTOM_6 , +DMACH_MTOM_7 ,/* END Marker, also used to denote a reserved channel */ DMACH_MAX, };@@ -95,4 +102,4 @@ static inline bool s3c_dma_has_circular(void)#include <plat/dma.h> -#endif /* __S3C_DMA_PL330_H_ */ +#endif /* __DMA_PL330_H_ */ arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h +1
-1@@ -12,7 +12,7 @@#ifndef __S3C_PL330_PDATA_H#define __S3C_PL330_PDATA_H -#include <plat/s3c-dma-pl330.h> +#include <plat/dma-pl330.h> /* * Every PL330 DMAC has max 32 peripheral interfaces,
Signature · 2 lines
~Vinod Koul Intel Corp.
PATCH v4 5/14 ARM: SAMSUNG: Update to use PL330-DMA driver
In reply to Boojin KimQuoted 8 lines · Boojin Kim
arch/arm/plat-samsung/Kconfig +0
-0@@ -300,6 +300,14 @@ config S3C_PL330_DMA? ? ? ?help
? ? ? ? ?S3C DMA API Driver for PL330 DMAC.
arch/arm/plat-samsung/Kconfig
Quoted 8 lines
arch/arm/plat-samsung/Kconfig +8
-0+config DMADEV_PL330 + ? ? ? bool + ? ? ? select DMADEVICES + ? ? ? select PL330_DMA + ? ? ? select ARM_AMBA + ? ? ? help + ? ? ? ? Use DMA device engine for PL330 DMAC. +
If this is for the 'wrapper' dma driver, please use S3C or similar prefix.
Quoted 11 lines
arch/arm/plat-samsung/include/plat/dma-pl330.h renamed from arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h +0
-0@@ -8,19 +8,18 @@?* (at your option) any later version.
?*/
arch/arm/plat-samsung/include/plat/dma-pl330.h
Quoted 7 lines
arch/arm/plat-samsung/include/plat/dma-pl330.h renamed from arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h +2
-5-#ifndef ? ? ? ?__S3C_DMA_PL330_H_ -#define ? ? ? ?__S3C_DMA_PL330_H_ - -#define S3C2410_DMAF_AUTOSTART ? ? ? ? (1 << 0) -#define S3C2410_DMAF_CIRCULAR ? ? ? ? ?(1 << 1) +#ifndef __DMA_PL330_H_ +#define __DMA_PL330_H_ __FILE__
To respect namespaces, please preserve S3C prefix because the file is Samsung specific.
Quoted 12 lines
arch/arm/plat-samsung/include/plat/dma-pl330.h renamed from arch/arm/plat-samsung/include/plat/s3c-dma-pl330.h +8
-0@@ -84,6 +83,14 @@ enum dma_ch { ? ? ? ?DMACH_SLIMBUS4_TX, ? ? ? ?DMACH_SLIMBUS5_RX, ? ? ? ?DMACH_SLIMBUS5_TX, + ? ? ? DMACH_MTOM_0, + ? ? ? DMACH_MTOM_1, + ? ? ? DMACH_MTOM_2, + ? ? ? DMACH_MTOM_3, + ? ? ? DMACH_MTOM_4, + ? ? ? DMACH_MTOM_5, + ? ? ? DMACH_MTOM_6, + ? ? ? DMACH_MTOM_7,
Quoted 3 lines
? ? ? ?/* END Marker, also used to denote a reserved channel */ ? ? ? ?DMACH_MAX,
?};
Naming mem->mem channels should be unnecessary.
Not sure what you have in mind.
PATCH v4 6/14 ARM: SAMSUNG: Add common DMA operations
In reply to Boojin KimThis patch adds common DMA operations which are used for Samsung DMA drivers. Currently there are two types of DMA driver for Samsung SoCs. The one is S3C-DMA for S3C SoCs and the other is PL330-DMA for S5P SoCs. This patch provides funcion pointers for common DMA operations to DMA client driver like SPI and Audio. It makes DMA client drivers support multi-platform.
In addition, this common DMA operations implement the shared actions that are needed for DMA client driver. For example shared actions are filter() function for dma_request_channel() and parameter passing for device_prep_slave_sg().
--- arch/arm/mach-s3c2410/include/mach/dma.h | 8 ++- arch/arm/mach-s3c64xx/include/mach/dma.h | 4 + arch/arm/plat-samsung/Makefile | 6 +- arch/arm/plat-samsung/dma-ops.c | 133 ++++++++++++++++++++++++ arch/arm/plat-samsung/include/plat/dma-ops.h | 64 +++++++++++ arch/arm/plat-samsung/include/plat/dma-pl330.h | 4 + arch/arm/plat-samsung/include/plat/dma.h | 1 + arch/arm/plat-samsung/s3c-dma-ops.c | 133 ++++++++++++++++++++++++ 8 files changed, 350 insertions(+), 3 deletions(-) create mode 100644 arch/arm/plat-samsung/dma-ops.c create mode 100644 arch/arm/plat-samsung/include/plat/dma-ops.h create mode 100644 arch/arm/plat-samsung/s3c-dma-ops.c
arch/arm/mach-s3c2410/include/mach/dma.h +7 -1
@@ -13,7 +13,6 @@#ifndef __ASM_ARCH_DMA_H#define __ASM_ARCH_DMA_H __FILE__ -#include <plat/dma.h> #include <linux/sysdev.h> #define MAX_DMA_TRANSFER_SIZE 0x100000/* Data Unit is half word */
@@ -51,6 +50,13 @@ enum dma_ch { DMACH_MAX, /* the end entry */ }; +static inline bool samsung_dma_is_dmadev (void ) +{ +return false; +} + +#include <plat/dma.h> +#define DMACH_LOW_LEVEL (1<<28)/* use this to specifiy hardware ch no */ /* we have 4 dma channels */
arch/arm/mach-s3c64xx/include/mach/dma.h +4 -0
@@ -63,6 +63,10 @@ static __inline__ bool s3c_dma_has_circular(void)return true; } +static inline bool samsung_dma_is_dmadev (void ) +{ +return false; +}#define S3C2410_DMAF_CIRCULAR (1 << 0)#include <plat/dma.h>
arch/arm/plat-samsung/Makefile +4 -2
@@ -62,9 +62,11 @@ obj-$(CONFIG_SAMSUNG_DEV_PWM) += dev-pwm.o # DMA support -obj-$(CONFIG_S3C_DMA) += dma.o +obj-$(CONFIG_S3C_DMA) += dma.o s3c-dma-ops.o -obj-$(CONFIG_S3C_PL330_DMA) += s3c-pl330.o +obj-$(CONFIG_DMADEV_PL330) += dma-ops.o + +obj-$(CONFIG_S3C_PL330_DMA) += s3c-pl330.o s3c-dma-ops.o # PM support
arch/arm/plat-samsung/dma-ops.c new file +133 -0
133 lines not on this page · raw message
arch/arm/plat-samsung/include/plat/dma-ops.h new file +64 -0
64 lines not on this page · raw message
arch/arm/plat-samsung/include/plat/dma-pl330.h +4 -0
@@ -100,6 +100,10 @@ static inline bool s3c_dma_has_circular(void) return true; } +static inline bool samsung_dma_is_dmadev (void ) +{ +return true; +}#include <plat/dma.h> #endif /* __DMA_PL330_H_ */
arch/arm/plat-samsung/include/plat/dma.h +1 -0
@@ -125,3 +125,4 @@ extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn);extern int s3c2410_dma_set_buffdone_fn (unsigned int ,s3c2410_dma_cbfn_t rtn); +#include <plat/dma-ops.h>
arch/arm/plat-samsung/s3c-dma-ops.c new file +133 -0
133 lines not on this page · raw message
Signature · 1 line
1.7.1
PATCH v4 6/14 ARM: SAMSUNG: Add common DMA operations
Quoted 7 lines · Boojin Kim
arch/arm/plat-samsung/dma-ops.c new file +7
-0+static unsigned samsung_dmadev_request (enum dma_ch dma_ch, +struct samsung_dma_info *info) +{ +struct dma_chan *chan; +dma_cap_mask_t mask; +struct dma_slave_config slave_config; +
arch/arm/plat-samsung/dma-ops.c line 46
Quoted 10 lines
arch/arm/plat-samsung/dma-ops.c new file +10
-0+dma_cap_zero (mask); +dma_cap_set (info->cap, mask); + + chan =dma_request_channel (mask, pl330_filter, (void *)dma_ch); + +if (info->direction ==DMA_FROM_DEVICE ) { +memset (&slave_config,0 ,sizeof (struct dma_slave_config )); + slave_config.direction = info->direction; + slave_config.src_addr = info->fifo; + slave_config.src_addr_width = info->width;
This should really set slave_config.src_maxburst to something sensible too, even if that's just '1'.
arch/arm/plat-samsung/dma-ops.c line 52
Quoted 6 lines
arch/arm/plat-samsung/dma-ops.c new file +6
-0+dmaengine_slave_config (chan, &slave_config); + }else if (info->direction ==DMA_TO_DEVICE ) { +memset (&slave_config,0 ,sizeof (struct dma_slave_config )); + slave_config.direction = info->direction; + slave_config.dst_addr = info->fifo; + slave_config.dst_addr_width = info->width;
Ditto for dst_maxburst.
arch/arm/plat-samsung/dma-ops.c line 56
Quoted 4 lines
arch/arm/plat-samsung/dma-ops.c new file +4
-0+dmaengine_slave_config (chan, &slave_config); + } + +return (unsigned )chan;
I hope these interfaces yet cleaned away soon so that these casts can be killed off.
arch/arm/plat-samsung/include/plat/dma-ops.h line 21
Quoted 4 lines
arch/arm/plat-samsung/include/plat/dma-ops.h new file +4
-0+struct samsung_dma_prep_info { +enum dma_transaction_type cap; +enum dma_data_direction direction; +unsigned buf;
dma_addr_t ?
arch/arm/plat-samsung/include/plat/dma-ops.h line 32
Quoted 11 lines
arch/arm/plat-samsung/include/plat/dma-ops.h new file +11
-0+unsigned long period; +unsigned long len; +void (*fp)(void *data); +void *fp_param; +}; + +struct samsung_dma_info { +enum dma_transaction_type cap; +enum dma_data_direction direction; +enum dma_slave_buswidth width; +unsigned fifo;
dma_addr_t ?
arch/arm/plat-samsung/include/plat/dma-ops.h line 37
Quoted 5 lines
arch/arm/plat-samsung/include/plat/dma-ops.h new file +5
-0+struct s3c2410_dma_client *client; +}; + +struct samsung_dma_ops { +bool init;
Unused?
PATCH v4 6/14 ARM: SAMSUNG: Add common DMA operations
Russell King - ARM Linux Wrote:
Quoted 3 lines
Sent: Monday, July 25, 2011 6:36 PM
To: Boojin Kim
Cc: linux-arm-kernel at lists.infradead.org;
linux-samsung-soc at vger.kernel.org;
Quoted 15 lines
Kukjin Kim; Vinod Koul; Jassi Brar; Grant Likely; Mark Brown; Dan Williams
Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operationsQuoted 11 lines · Boojin Kim
arch/arm/plat-samsung/dma-ops.c new file +11
-0+static unsigned samsung_dmadev_request (enum dma_ch dma_ch, +struct samsung_dma_info *info) +{ +struct dma_chan *chan; +dma_cap_mask_t mask; +struct dma_slave_config slave_config; + +dma_cap_zero (mask); +dma_cap_set (info->cap, mask); + + chan =dma_request_channel (mask, pl330_filter, (void *)dma_ch);
Quoted 8 lines
arch/arm/plat-samsung/dma-ops.c line 46
Quoted 6 lines
arch/arm/plat-samsung/dma-ops.c new file +6
-0+ +if (info->direction ==DMA_FROM_DEVICE ) { +memset (&slave_config,0 ,sizeof (struct dma_slave_config )); + slave_config.direction = info->direction; + slave_config.src_addr = info->fifo; + slave_config.src_addr_width = info->width;This should really set slave_config.src_maxburst to something sensible
too,
Quoted 1 line
even if that's just '1'.
I will address your comment.
Quoted 39 lines
arch/arm/plat-samsung/dma-ops.c line 52
Quoted 7 lines
arch/arm/plat-samsung/dma-ops.c new file +6
-0+dmaengine_slave_config (chan, &slave_config); + }else if (info->direction ==DMA_TO_DEVICE ) { +memset (&slave_config,0 ,sizeof (struct dma_slave_config )); + slave_config.direction = info->direction; + slave_config.dst_addr = info->fifo; + slave_config.dst_addr_width = info->width;Ditto for
dst_maxburst.arch/arm/plat-samsung/dma-ops.c line 56
Quoted 4 lines
arch/arm/plat-samsung/dma-ops.c new file +4
-0+dmaengine_slave_config (chan, &slave_config); + } + +return (unsigned )chan;I hope these interfaces yet cleaned away soon so that these casts can be killed off.
arch/arm/plat-samsung/include/plat/dma-ops.h line 21
Quoted 4 lines
arch/arm/plat-samsung/include/plat/dma-ops.h new file +4
-0+struct samsung_dma_prep_info { +enum dma_transaction_type cap; +enum dma_data_direction direction; +unsigned buf;
dma_addr_t?arch/arm/plat-samsung/include/plat/dma-ops.h line 32
Quoted 11 lines
arch/arm/plat-samsung/include/plat/dma-ops.h new file +11
-0+unsigned long period; +unsigned long len; +void (*fp)(void *data); +void *fp_param; +}; + +struct samsung_dma_info { +enum dma_transaction_type cap; +enum dma_data_direction direction; +enum dma_slave_buswidth width; +unsigned fifo;
dma_addr_t?
Quoted 7 lines
arch/arm/plat-samsung/include/plat/dma-ops.h line 37
Quoted 5 lines
arch/arm/plat-samsung/include/plat/dma-ops.h new file +5
-0+struct s3c2410_dma_client *client; +}; + +struct samsung_dma_ops { +bool init;Unused?
Yes, It's my mistake. I will address your comment.
PATCH v4 6/14 ARM: SAMSUNG: Add common DMA operations
In reply to Boojin Kimarch/arm/plat-samsung/dma-ops.c line 28
Quoted 11 lines · Boojin Kim
arch/arm/plat-samsung/dma-ops.c new file +11
-0+ +static bool pl330_filter (struct dma_chan *chan,void *param) +{ + ? ? ? struct dma_pl330_peri *peri = (struct dma_pl330_peri *)chan->private; + ? ? ? unsigned dma_ch = (unsigned)param; + + ? ? ? if (peri->peri_id != dma_ch) + ? ? ? ? ? ? ? return false; + + ? ? ? return true; +}
This is what I meant... if we keep chan_id for paltform assigned IDs, these filter functions could simply become
static bool pl330_filter(struct dma_chan *chan, void *param)
{
return chan->chan_id == param
}And ideally in the long run, we could just drop the filter callback and add expected channel ID to the request_channel call.
Quoted 19 lines
arch/arm/plat-samsung/s3c-dma-ops.c new file +19
-0+ +static inline int s3c_dma_trigger (unsigned ch) +{ + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START); +} + +static inline int s3c_dma_started (unsigned ch) +{ + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED); +} + +static inline int s3c_dma_flush (unsigned ch) +{ + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH); +} + +static inline int s3c_dma_stop (unsigned ch) +{ + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP);
arch/arm/plat-samsung/s3c-dma-ops.c
Quoted 10 lines
arch/arm/plat-samsung/s3c-dma-ops.c new file +10
-0+} + +static struct samsung_dma_ops s3c_dma_ops = { + ? ? ? .request ? ? ? ?= s3c_dma_request, + ? ? ? .release ? ? ? ?= s3c_dma_release, + ? ? ? .prepare ? ? ? ?= s3c_dma_prepare, + ? ? ? .trigger ? ? ? ?= s3c_dma_trigger, + ? ? ? .started ? ? ? ?= s3c_dma_started, + ? ? ? .flush ? ? ? ? ?= s3c_dma_flush, + ? ? ? .stop ? ? ? ? ? = s3c_dma_stop,
These last 4 should be gnereallized into one callback with OP argument.
PATCH v4 6/14 ARM: SAMSUNG: Add common DMA operations
Quoted 16 lines · Jassi Brar
arch/arm/plat-samsung/dma-ops.c line 28
Quoted 11 lines · Boojin Kim
arch/arm/plat-samsung/dma-ops.c new file +11
-0+ +static bool pl330_filter (struct dma_chan *chan,void *param) +{ + ? ? ? struct dma_pl330_peri *peri = (struct dma_pl330_peri *)chan->private; + ? ? ? unsigned dma_ch = (unsigned)param; + + ? ? ? if (peri->peri_id != dma_ch) + ? ? ? ? ? ? ? return false; + + ? ? ? return true; +}This is what I meant... if we keep
chan_idfor paltform assigned IDs, these filter functions could simply become
Quoted 7 lines
static bool
pl330_filter(struct dma_chan *chan, void *param){ return chan->chan_id == param }And ideally in the long run, we could just drop the filter callback and add expected channel ID to the
request_channelcall.
So what if you have a PL080 and PL330 drivers registered with the DMA engine code, and you need to match a specific PL330 channel?
PATCH v4 6/14 ARM: SAMSUNG: Add common DMA operations
Quoted 22 lines · Russell King - ARM Linux
Quoted 21 lines · Jassi Brar
arch/arm/plat-samsung/dma-ops.c line 28
Quoted 11 lines · Boojin Kim
arch/arm/plat-samsung/dma-ops.c new file +11
-0+ +static bool pl330_filter (struct dma_chan *chan,void *param) +{ + ? ? ? struct dma_pl330_peri *peri = (struct dma_pl330_peri *)chan->private; + ? ? ? unsigned dma_ch = (unsigned)param; + + ? ? ? if (peri->peri_id != dma_ch) + ? ? ? ? ? ? ? return false; + + ? ? ? return true; +}This is what I meant... if we keep
chan_idfor paltform assigned IDs, these filter functions could simply becomestatic bool
pl330_filter(struct dma_chan *chan, void *param){
? ? ? ? returnchan->chan_id== param
}
Quoted 6 lines
Quoted 2 lines
And ideally in the long run, we could just drop the filter callback and add expected channel ID to the
request_channelcall.So what if you have a PL080 and PL330 drivers registered with the DMA engine code, and you need to match a specific PL330 channel?
Before we start, let me be clear that I don't say it's all possible today as such.
We will need changes to the API and modifications to the damc/client drivers (which are already misusing the API as it turns out).
I hope we agree, clients (esp 'generic' ones of the future) should not ask for channels from a particular dmac. They should simply tell DMA API, what capabilities they expect from the allocated channel - of whatever index on whichever dmac. And the platform should have specified capabilities of a channel
while introducing it to the DMA API. Yes, imho, DMA API should
only work with a pool of channels and not dmacs - it shouldn't matter from which dmac a channel comes.
So when a client asks for a channel, the dmaengine would return the first free channel that has just as much the requested capability.
That is, the generic filter function would look equivalent of :-
return is_free(chan) && (cap_requested == cap_of(chan) & cap_requested)
Now it all boils down to defining the set of _practically_ possible capabilities and a method to exchange them between the API, Client and DMAC drivers.
The above is the overall approach.
The following is my idea of implementing it as of now, I am open to suggestions.
Assuming :-
***********
There are no more than 256 types of DMA'able devices
(MMC, USB, SPI etc) -- [8bits]
A type of device never has more than 16 instances in a platform
(MMC-0, MMC-1, MMC-2 etc) -- [4bits]
Mem->Mem, Mem->Dev, Dev->Mem, Dev->Dev capability in [4bits]
Max_Burst_Len for any channel is less than 64KB, in power of two [4bits] Support programmable Max_Burst_Len(tunable in geometric steps of 2) [1bit]
Max_RW_width/fifo_width is less than 128, in power of two -- [3bits] Support programmable Max_RW_Width(tunable in geometric steps of 2) [1bit]
Finally, No platform has more than 128 channels with identicial capabilities [7bits]
For a channel, when specific values of these fields are appended together, we get a unqiue 32-bits value called 'chan_id'
Though we can use 64-bits to store the capabilities if we think number or size of these fields need to be increased.
Thanks,
Jassi
PATCH v4 6/14 ARM: SAMSUNG: Add common DMA operations
Quoted 2 lines · Jassi Brar
Before we start, let me be clear that I don't say it's all possible today as such.
It _is_ possible today.
1. Arrange for individual DMA engine drivers to provide a filter function - eg, pl08x_filter_id() for pl08x channels.
2. Have the filter function check chan->device->dev->driver == its own struct driver as the very first thing, and reject on failure.
3. Have its own matching algorithm using whatever data is appropriate for the DMA engine driver.
4. Platforms (or SoC code) provide the match function plus match data via platform data to each driver.
That is essentially (except for (2)) how we deal with differing DMA engine drivers with AMBA peripherals, and it seems to work remarkably well.
Quoted 8 lines
I hope we agree, clients (esp 'generic' ones of the future) should not ask for channels from a particular dmac. They should simply tell DMA API, what capabilities they expect from the allocated channel - of whatever index on whichever dmac. And the platform should have specified capabilities of a channel
while introducing it to the DMA API. Yes, imho, DMA API should
only work with a pool of channels and not dmacs - it shouldn't matter from which dmac a channel comes.
You're quite clearly confused. "DMA API" has not very much to do with the subject we're discussing. The "DMA API" is the API for mapping and unmapping buffers for DMA. It has not much to do with the DMA engine API. So I'm not going to bother trying to decode what you said above until you start using the right terminology. I'm a stickler for that, get used to it.
No point talking about how round bananas are when you're actually discussing orange fruit.
Quoted 2 lines
So when a client asks for a channel, the dmaengine would return the first free channel that has just as much the requested capability.
No. For slave DMA, peripheral drivers normally need a specific channel on the DMA controller. Peripheral drivers normally do not know which channel they need, or even which DMA controller they require. That information is specific to the platform and SoC.
So, returning the "first free channel that matches the capability" is senseless - insane - for slave DMA.
Quoted 7 lines
That is, the generic filter function would look equivalent of :-
return is_free(chan) && (cap_requested == cap_of(chan) & cap_requested)Now it all boils down to defining the set of _practically_ possible capabilities and a method to exchange them between the API, Client and DMAC drivers.
What are these capabilities?
Quoted 9 lines
The above is the overall approach.
The following is my idea of implementing it as of now, I am open to suggestions.
Assuming :-
***********
There are no more than 256 types of DMA'able devices
(MMC, USB, SPI etc) -- [8bits]
Quoted 4 lines
A type of device never has more than 16 instances in a platform
(MMC-0, MMC-1, MMC-2 etc) -- [4bits]
Mem->Mem,Mem->Dev,Dev->Mem,Dev->Devcapability in [4bits]
No. You're being far too specific to your own DMA controller. Many DMA controllers (eg, PL08x) have a number of physical channels, all of which can be programmed for M2M, M2P, P2M and P2P. There is nothing in the design which restricts what a channel can do.
So to put that as the basis for a generic match algorithm is absolutely senseless.
Quoted 8 lines
Max_Burst_Lenfor any channel is less than 64KB, in power of two [4bits] Support programmableMax_Burst_Len(tunable in geometric steps of 2)[1bit]Max_RW_width/fifo_width is less than 128, in power of two -- [3bits] Support programmable
Max_RW_Width(tunable in geometric steps of 2)[1bit]Finally, No platform has more than 128 channels with identicial capabilities [7bits]
There is absolutely no way that this will work in reality - are you on a different planet? As has already been described to you, MMCI can use one DMA channel, and programs it according to the DMA direction, and has in the past adjusted the burst size according to what's going on with the driver.
With your model, it would have to claim N channels from the DMA engine for all possible different configurations.
That's utterly unworkable and unrealistic.
So no, I don't think your idea of 'capabilities' is any solution. It just creates yet more problems - more than it solves.
PATCH v4 6/14 ARM: SAMSUNG: Add common DMA operations
Quoted 9 lines · Russell King - ARM Linux
1. Arrange for individual DMA engine drivers to provide a filter ? function - eg,
pl08x_filter_id()for pl08x channels.2. Have the filter function check
chan->device->dev->driver== its ? own struct driver as the very first thing, and reject on failure.3. Have its own matching algorithm using whatever data is appropriate ? for the DMA engine driver.
IMHO it should be possible to have client drivers not use platform specific details while choosing a channel. Otherwise, they are not really 'generic' 'platform-independent' client drivers.
Quoted 16 lines
Quoted 8 lines
I hope we agree, clients (esp 'generic' ones of the future) should not ask for channels from a particular dmac. They should simply tell DMA API, what capabilities they expect from the allocated channel - of whatever index on whichever dmac. And the platform should have specified capabilities of a channel while introducing it to the DMA API. ? Yes, imho, DMA API should only work with a pool of channels and not dmacs - it shouldn't matter from which dmac a channel comes.
You're quite clearly confused. ?"DMA API" has not very much to do with the subject we're discussing. ?The "DMA API" is the API for mapping and unmapping buffers for DMA. ?It has not much to do with the DMA engine API. ?So I'm not going to bother trying to decode what you said above until you start using the right terminology. ?I'm a stickler for that, get used to it.
Quoted 2 lines
No point talking about how round bananas are when you're actually discussing orange fruit.
Sorry, my carelessness.
I should have written DMAENGINE API, instead of DMA API.
If you want I can repost with s/DMA API/DMAENGINE API/
Quoted 6 lines
Quoted 3 lines
So when a client asks for a channel, the dmaengine would return the first free channel that has just as much the requested capability.
No. ?For slave DMA, peripheral drivers normally need a specific channel on the DMA controller.
Of course they do.
And It is the responsibility of platform to encode such information as a 'capability' of the channel. Capability to reach a particular peripheral, say.
Quoted 3 lines
?Peripheral drivers normally do not
know which channel they need, or even which DMA controller they require. ?That information is specific to the platform and SoC.
For that very reason I proposed, say, if MMC client driver is probed for 2nd instance
of MMC controller, it should ask for the following capabilities
(MMC << TYPE_SHFT) | (2 << INST_SHFT) //I don't show other
fields for simplicity
It is the job of _platform_ to set TYPE and INSTANCE fields to 'MMC' and 2 resp _only_ for the channel(s) that can reach its MMC_2 controller.
That way, when the client 'generically' asks for DMA_MMC_2, it will be given only one of those channels that can talk to second instance of MMC controller.
Quoted 9 lines
Quoted 7 lines
That is, the generic filter function would look equivalent of :-
? ? ? return
is_free(chan)&& (cap_requested==cap_of(chan)&cap_requested)Now it all boils down to defining the set of _practically_ possible capabilities and a method to exchange them between the API, Client and DMAC drivers.
What are these capabilities?
I had mentioned the list below under 'Assuming'. We may add more.
Quoted 13 lines
Quoted 13 lines
The above is the overall approach.
The following is my idea of implementing it as of now, I am open to suggestions.
Assuming :-
***********
There are no more than 256 types of DMA'able devices ?(MMC, USB, SPI etc) -- ?[8bits]A type of device never has more than 16 instances in a platform ?(MMC-0, MMC-1, MMC-2 etc) -- ?[4bits]
Quoted 6 lines
Quoted 1 line
Mem->Mem,Mem->Dev,Dev->Mem,Dev->Devcapability in [4bits]No. ?You're being far too specific to your own DMA controller. ?Many DMA controllers (eg, PL08x) have a number of physical channels, all of which can be programmed for M2M, M2P, P2M and P2P. ?There is nothing in the design which restricts what a channel can do.
I am not being specific, at least not on this point. Btw, I have worked on pl080 as well and I have tried to be not specific to not only pl330 but also pl080.
If you notice I have assigned 4bits to the field. Each of the 4 bits can be set independently.
So, a capable pl08x channel can set all 4 bits to indicate that it can do all 4 types
- M2M, M2P, P2M and P2P.
Quoted 9 lines
Quoted 8 lines
Max_Burst_Lenfor any channel is less than 64KB, in power of two [4bits] Support programmableMax_Burst_Len(tunable in geometric steps of 2)?[1bit]Max_RW_width/fifo_width is less than 128, in power of two -- [3bits] Support programmable
Max_RW_Width(tunable in geometric steps of 2)?[1bit]Finally, No platform has more than 128 channels with identicial capabilities [7bits]
Quoted 8 lines
There is absolutely no way that this will work in reality - are you on a different planet? ?As has already been described to you, MMCI can use one DMA channel, and programs it according to the DMA direction, and has in the past adjusted the burst size according to what's going on with the driver.
With your model, it would have to claim N channels from the DMA engine for all possible different configurations.
I don't think so.
What I proposed is only a list of capabilities and method to _select_ a suitable channel in a platform independent way.
For example, if MMCI driver wants to be able to change directions, it should specify Mem->Dev and Dev->Mem capability while requesting a channel. And use slave_config call to switch directions. (and yes we have to modify slave_config call and maybe some other parts too)
For being able to change burst size, it could set some 'ignore' bit + default value
to the 'fifo_width' field so that DMAENGINE ignores checking the fifo_width capability and upon slave_config either set requested burst_size if supported or return error if the requested burst size is not supported. That is implementation detail.
Sincerely, I would to know other capabilities that are more flexible than I have assumed here or missed altogether.
I have not yet written any code. I just wanted to share my belief that it is possible
to have client drivers truly independent of the platform they run on. And by not using platform_data of DMA channels.
Probably you don't, but if you do want, I can send rudimentary implementation of what I propose, in a few days.
Thanks
PATCH v4 6/14 ARM: SAMSUNG: Add common DMA operations
In reply to Jassi BrarJassi Brar Wrote:
Quoted 25 lines
Sent: Monday, July 25, 2011 8:52 PM
To: Boojin Kim
Cc: linux-arm-kernel at lists.infradead.org; linux-samsung- soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant Likely; Mark Brown
Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operationsarch/arm/plat-samsung/dma-ops.c line 28
Quoted 12 lines · Boojin Kim
arch/arm/plat-samsung/dma-ops.c new file +4
-0+ +static bool pl330_filter (struct dma_chan *chan,void *param) +{ + struct dma_pl330_peri *peri = (struct dma_pl330_peri *)chan-private;
arch/arm/plat-samsung/dma-ops.c new file +7
-0+unsigned dma_ch = (unsigned )param; + +if (peri->peri_id != dma_ch) +return false; + +return true; +}This is what I meant... if we keep
chan_idfor paltform assigned IDs, these filter functions could simply become
Quoted 7 lines
static bool
pl330_filter(struct dma_chan *chan, void *param){ return chan->chan_id == param }And ideally in the long run, we could just drop the filter callback and add expected channel ID to the
request_channelcall.
The chan_id is set by dmaengine. So, We don't use it to hold the user specific Id.
Quoted 26 lines
Quoted 26 lines
arch/arm/plat-samsung/s3c-dma-ops.c new file +23
-0+ +static inline int s3c_dma_trigger (unsigned ch) +{ +return s3c2410_dma_ctrl (ch,S3C2410_DMAOP_START ); +} + +static inline int s3c_dma_started (unsigned ch) +{ +return s3c2410_dma_ctrl (ch,S3C2410_DMAOP_STARTED ); +} + +static inline int s3c_dma_flush (unsigned ch) +{ +return s3c2410_dma_ctrl (ch,S3C2410_DMAOP_FLUSH ); +} + +static inline int s3c_dma_stop (unsigned ch) +{ +return s3c2410_dma_ctrl (ch,S3C2410_DMAOP_STOP ); +} + +static struct samsung_dma_ops s3c_dma_ops = { + .request = s3c_dma_request,
Quoted 8 lines
arch/arm/plat-samsung/s3c-dma-ops.c line 126
Quoted 6 lines
arch/arm/plat-samsung/s3c-dma-ops.c new file +6
-0+ .release = s3c_dma_release, + .prepare = s3c_dma_prepare, + .trigger = s3c_dma_trigger, + .started = s3c_dma_started, + .flush = s3c_dma_flush, + .stop = s3c_dma_stop,These last 4 should be gnereallized into one callback with OP argument.
I don't have any idea about it. Can you explain it in more detail?
PATCH v4 6/14 ARM: SAMSUNG: Add common DMA operations
Quoted 31 lines · Boojin Kim
Jassi Brar Wrote:
Quoted 30 lines
Sent: Monday, July 25, 2011 8:52 PM
To: Boojin Kim
Cc: linux-arm-kernel at lists.infradead.org; linux-samsung- soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant Likely; Mark Brown
Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operationsarch/arm/plat-samsung/dma-ops.c line 28
Quoted 12 lines · Boojin Kim
arch/arm/plat-samsung/dma-ops.c new file +4
-0+ +static bool pl330_filter (struct dma_chan *chan,void *param) +{ + ? ? ? struct dma_pl330_peri *peri = (struct dma_pl330_peri *)chan-private;
+ ? ? ? unsigneddma_ch= (unsigned)param;arch/arm/plat-samsung/dma-ops.c new file +6
-0+ + ? ? ? if (peri->peri_id != dma_ch) + ? ? ? ? ? ? ? return false; + + ? ? ? return true; +}This is what I meant... if we keep
chan_idfor paltform assigned IDs, these filter functions could simply becomestatic bool
pl330_filter(struct dma_chan *chan, void *param){
? ? ? ? returnchan->chan_id== param
}
Quoted 4 lines
Quoted 2 lines
And ideally in the long run, we could just drop the filter callback and add expected channel ID to the
request_channelcall.The
chan_idis set by dmaengine. So, We don't use it to hold the user specific Id.
Not for long.
See https://lkml.org/lkml/2011/7/26/245
Quoted 31 lines
Quoted 23 lines
Quoted 23 lines
arch/arm/plat-samsung/s3c-dma-ops.c new file +23
-0+ +static inline int s3c_dma_trigger (unsigned ch) +{ + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START); +} + +static inline int s3c_dma_started (unsigned ch) +{ + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED); +} + +static inline int s3c_dma_flush (unsigned ch) +{ + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH); +} + +static inline int s3c_dma_stop (unsigned ch) +{ + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP); +} + +static struct samsung_dma_ops s3c_dma_ops = { + ? ? ? .request ? ? ? ?= s3c_dma_request,Quoted 8 lines
Quoted 6 lines
+ ? ? ? .release ? ? ? ?=
s3c_dma_release,
+ ? ? ? .prepare ? ? ? ?=s3c_dma_prepare,
+ ? ? ? .trigger ? ? ? ?=s3c_dma_trigger,
+ ? ? ? .started ? ? ? ?=s3c_dma_started,
+ ? ? ? .flush ? ? ? ? ?=s3c_dma_flush,
+ ? ? ? .stop ? ? ? ? ? =s3c_dma_stop,These last 4 should be gnereallized into one callback with OP argument.
Quoted 1 line
I don't have any idea about it. Can you explain it in more detail?
static int s3c_dma_control(unsigned ch, enum s3c2410_chan_op/*or similar*/ op)
{
return s3c2410_dma_ctrl(ch, op);}
static struct samsung_dma_ops s3c_dma_ops = {
.request = s3c_dma_request,
.release = s3c_dma_release,
.prepare = s3c_dma_prepare,
.control = s3c_dma_control,PATCH v4 6/14 ARM: SAMSUNG: Add common DMA operations
Quoted 91 lines · Jassi Brar
Sent: Wednesday, July 27, 2011 10:34 AM
To: Boojin Kim
Cc: linux-arm-kernel at lists.infradead.org; linux-samsung- soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant Likely; Mark Brown
Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operationsQuoted 7 lines · Boojin Kim
Jassi Brar Wrote:
Quoted 6 lines
Sent: Monday, July 25, 2011 8:52 PM
To: Boojin Kim
Cc: linux-arm-kernel at lists.infradead.org; linux-samsung- soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant Likely; Mark Brown
Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMAoperations
Quoted 2 lines
Quoted 2 lines
On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim
Quoted 6 lines
Quoted 6 lines
arch/arm/plat-samsung/dma-ops.c
Quoted 4 lines · wrote:
arch/arm/plat-samsung/dma-ops.c new file +4
-0+ +static bool pl330_filter (struct dma_chan *chan,void *param) +{ + struct dma_pl330_peri *peri = (struct dma_pl330_peri*)chan-
Quoted 9 lines
Quoted 9 lines
arch/arm/plat-samsung/dma-ops.c line 28
Quoted 8 lines
private;
arch/arm/plat-samsung/dma-ops.c new file +7
-0+unsigned dma_ch = (unsigned )param; + +if (peri->peri_id != dma_ch) +return false; + +return true; +}This is what I meant... if we keep
chan_idfor paltform assignedIDs,
Quoted 10 lines
Quoted 9 lines
these filter functions could simply become
static bool
pl330_filter(struct dma_chan *chan, void *param){ return chan->chan_id == param }And ideally in the long run, we could just drop the filter callback and add expected channel ID to the
request_channelcall.The
chan_idis set by dmaengine. So, We don't use it to hold theuser specific
Quoted 1 line
Id.
Not for long.
See https://lkml.org/lkml/2011/7/26/245Quoted 23 lines
Quoted 23 lines
Quoted 23 lines
arch/arm/plat-samsung/s3c-dma-ops.c new file +23
-0+ +static inline int s3c_dma_trigger (unsigned ch) +{ +return s3c2410_dma_ctrl (ch,S3C2410_DMAOP_START ); +} + +static inline int s3c_dma_started (unsigned ch) +{ +return s3c2410_dma_ctrl (ch,S3C2410_DMAOP_STARTED ); +} + +static inline int s3c_dma_flush (unsigned ch) +{ +return s3c2410_dma_ctrl (ch,S3C2410_DMAOP_FLUSH ); +} + +static inline int s3c_dma_stop (unsigned ch) +{ +return s3c2410_dma_ctrl (ch,S3C2410_DMAOP_STOP ); +} + +static struct samsung_dma_ops s3c_dma_ops = { + .request = s3c_dma_request,Quoted 8 lines
Quoted 8 lines
arch/arm/plat-samsung/s3c-dma-ops.c line 126
Quoted 6 lines
arch/arm/plat-samsung/s3c-dma-ops.c new file +6
-0+ .release = s3c_dma_release, + .prepare = s3c_dma_prepare, + .trigger = s3c_dma_trigger, + .started = s3c_dma_started, + .flush = s3c_dma_flush, + .stop = s3c_dma_stop,These last 4 should be gnereallized into one callback with OP
argument.
Quoted 1 line
I don't have any idea about it. Can you explain it in more detail?
static int
s3c_dma_control(unsigned ch, enum s3c2410_chan_op/*or similar*/ op){ return s3c2410_dma_ctrl(ch, op);
Quoted 7 lines
}
static struct
samsung_dma_opss3c_dma_ops= {.request = s3c_dma_request, .release = s3c_dma_release, .prepare = s3c_dma_prepare, .control = s3c_dma_control,
'Struct samsung_dma_ops' is used for both 'S3C-DMA-OPS' for 's3c dma' and 'DMA-OPS' for 'dmaengine'.
If I modify "Struct samsung_dma_ops" as your guide, It gives un-expectable effect to DMA-OPS.
Actually, We don't want the client with 'DMA-OPS' uses 'enum s3c2410_chan_op' operation anymore.
PATCH v4 6/14 ARM: SAMSUNG: Add common DMA operations
Quoted 99 lines · Boojin Kim
Quoted 93 lines · Jassi Brar
Sent: Wednesday, July 27, 2011 10:34 AM
To: Boojin Kim
Cc: linux-arm-kernel at lists.infradead.org; linux-samsung- soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant Likely; Mark Brown
Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operationsQuoted 7 lines · Boojin Kim
Jassi Brar Wrote:
Quoted 6 lines
Sent: Monday, July 25, 2011 8:52 PM
To: Boojin Kim
Cc: linux-arm-kernel at lists.infradead.org; linux-samsung- soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant Likely; Mark Brown
Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMAoperations
Quoted 2 lines
Quoted 2 lines
On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim
Quoted 6 lines
Quoted 6 lines
arch/arm/plat-samsung/dma-ops.c
Quoted 4 lines · wrote:
arch/arm/plat-samsung/dma-ops.c new file +4
-0+ +static bool pl330_filter (struct dma_chan *chan,void *param) +{ + ? ? ? struct dma_pl330_peri *peri = (struct dma_pl330_peri*)chan-
Quoted 9 lines
Quoted 9 lines
arch/arm/plat-samsung/dma-ops.c line 28
Quoted 8 lines
private;
+ ? ? ? unsigneddma_ch= (unsigned)param;arch/arm/plat-samsung/dma-ops.c new file +6
-0+ + ? ? ? if (peri->peri_id != dma_ch) + ? ? ? ? ? ? ? return false; + + ? ? ? return true; +}This is what I meant... if we keep
chan_idfor paltform assignedIDs,
Quoted 10 lines
Quoted 9 lines
these filter functions could simply become
static bool
pl330_filter(struct dma_chan *chan, void *param){
? ? ? ? returnchan->chan_id== param
}And ideally in the long run, we could just drop the filter callback and add expected channel ID to the
request_channelcall.The
chan_idis set by dmaengine. So, We don't use it to hold theuser specific
Quoted 1 line
Id.
Not for long.
See ?https://lkml.org/lkml/2011/7/26/245Quoted 23 lines
Quoted 23 lines
Quoted 23 lines
arch/arm/plat-samsung/s3c-dma-ops.c new file +23
-0+ +static inline int s3c_dma_trigger (unsigned ch) +{ + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_START); +} + +static inline int s3c_dma_started (unsigned ch) +{ + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STARTED); +} + +static inline int s3c_dma_flush (unsigned ch) +{ + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_FLUSH); +} + +static inline int s3c_dma_stop (unsigned ch) +{ + ? ? ? return s3c2410_dma_ctrl(ch, S3C2410_DMAOP_STOP); +} + +static struct samsung_dma_ops s3c_dma_ops = { + ? ? ? .request ? ? ? ?= s3c_dma_request,Quoted 8 lines
Quoted 8 lines
Quoted 6 lines
+ ? ? ? .release ? ? ? ?=
s3c_dma_release,
+ ? ? ? .prepare ? ? ? ?=s3c_dma_prepare,
+ ? ? ? .trigger ? ? ? ?=s3c_dma_trigger,
+ ? ? ? .started ? ? ? ?=s3c_dma_started,
+ ? ? ? .flush ? ? ? ? ?=s3c_dma_flush,
+ ? ? ? .stop ? ? ? ? ? =s3c_dma_stop,These last 4 should be gnereallized into one callback with OP
argument.
Quoted 1 line
I don't have any idea about it. Can you explain it in more detail?
static int
s3c_dma_control(unsigned ch, enum s3c2410_chan_op/*or similar*/ op)
?{
? ? ? ? returns3c2410_dma_ctrl(ch, op);
?}Quoted 5 lines
static struct
samsung_dma_opss3c_dma_ops= {
? ? ? ? .request ? ? ? ?=s3c_dma_request,
? ? ? ? .release ? ? ? ?=s3c_dma_release,
? ? ? ? .prepare ? ? ? ?=s3c_dma_prepare,
? ? ? ? .control ? ? ? ?=s3c_dma_control,
Quoted 6 lines
'Struct
samsung_dma_ops' is used for both 'S3C-DMA-OPS' for 's3c dma' and 'DMA-OPS' for 'dmaengine'.
If I modify "Structsamsung_dma_ops" as your guide, It gives un-expectable effect to DMA-OPS.
Actually, We don't want the client with 'DMA-OPS' uses 'enums3c2410_chan_op' operation anymore.
" enum s3c2410_chan_op /* or similar */ " <<<< note 'or similar'
Defining a callback for each value of the argument doesn't make sense.
PATCH v4 6/14 ARM: SAMSUNG: Add common DMA operations
Quoted 116 lines · Jassi Brar
Sent: Wednesday, July 27, 2011 4:58 PM
To: Boojin Kim
Cc: Kukjin Kim; Vinod Koul; Mark Brown; Grant Likely; linux-samsung- soc at vger.kernel.org; Dan Williams; linux-arm-
kernel at lists.infradead.org
Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operationsQuoted 7 lines · Boojin Kim
Quoted 6 lines · Jassi Brar
Sent: Wednesday, July 27, 2011 10:34 AM
To: Boojin Kim
Cc: linux-arm-kernel at lists.infradead.org; linux-samsung- soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant Likely; Mark Brown
Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMAoperations
Quoted 2 lines
Quoted 2 lines
On Tue, Jul 26, 2011 at 3:05 PM, Boojin Kim
Quoted 29 lines
Quoted 29 lines
Quoted 7 lines · wrote:
Jassi Brar Wrote:
Quoted 6 lines
Sent: Monday, July 25, 2011 8:52 PM
To: Boojin Kim
Cc: linux-arm-kernel at lists.infradead.org; linux-samsung- soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant Likely; Mark Brown
Subject: Re: [PATCH V4 06/14] ARM: SAMSUNG: Add common DMAoperations
Quoted 2 lines
Quoted 2 lines
On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim
Quoted 6 lines
Quoted 6 lines
arch/arm/plat-samsung/dma-ops.c
Quoted 4 lines · wrote:
arch/arm/plat-samsung/dma-ops.c new file +4
-0+ +static bool pl330_filter (struct dma_chan *chan,void *param) +{ + struct dma_pl330_peri *peri = (struct dma_pl330_peri*)chan-
Quoted 9 lines
Quoted 9 lines
arch/arm/plat-samsung/dma-ops.c line 28
Quoted 8 lines
private;
arch/arm/plat-samsung/dma-ops.c new file +7
-0+unsigned dma_ch = (unsigned )param; + +if (peri->peri_id != dma_ch) +return false; + +return true; +}This is what I meant... if we keep
chan_idfor paltform assignedIDs,
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
Quoted 8 lines
these filter functions could simply become
static bool
pl330_filter(struct dma_chan *chan, void *param){ return chan->chan_id == param }And ideally in the long run, we could just drop the filter
callback
Quoted 48 lines
Quoted 48 lines
Quoted 2 lines
Quoted 1 line
and add expected channel ID to the
request_channelcall.The
chan_idis set by dmaengine. So, We don't use it to hold theuser specific
Quoted 1 line
Id.
Not for long.
See https://lkml.org/lkml/2011/7/26/245Quoted 23 lines
Quoted 23 lines
Quoted 23 lines
arch/arm/plat-samsung/s3c-dma-ops.c new file +23
-0+ +static inline int s3c_dma_trigger (unsigned ch) +{ +return s3c2410_dma_ctrl (ch,S3C2410_DMAOP_START ); +} + +static inline int s3c_dma_started (unsigned ch) +{ +return s3c2410_dma_ctrl (ch,S3C2410_DMAOP_STARTED ); +} + +static inline int s3c_dma_flush (unsigned ch) +{ +return s3c2410_dma_ctrl (ch,S3C2410_DMAOP_FLUSH ); +} + +static inline int s3c_dma_stop (unsigned ch) +{ +return s3c2410_dma_ctrl (ch,S3C2410_DMAOP_STOP ); +} + +static struct samsung_dma_ops s3c_dma_ops = { + .request = s3c_dma_request,Quoted 8 lines
Quoted 8 lines
arch/arm/plat-samsung/s3c-dma-ops.c line 126
Quoted 6 lines
arch/arm/plat-samsung/s3c-dma-ops.c new file +6
-0+ .release = s3c_dma_release, + .prepare = s3c_dma_prepare, + .trigger = s3c_dma_trigger, + .started = s3c_dma_started, + .flush = s3c_dma_flush, + .stop = s3c_dma_stop,These last 4 should be gnereallized into one callback with OP
argument.
Quoted 1 line
I don't have any idea about it. Can you explain it in more detail?
static int
s3c_dma_control(unsigned ch, enum s3c2410_chan_op/*or similar*/ op){ return s3c2410_dma_ctrl(ch, op);}
Quoted 6 lines
Quoted 5 lines
static struct
samsung_dma_opss3c_dma_ops= {.request = s3c_dma_request, .release = s3c_dma_release, .prepare = s3c_dma_prepare, .control = s3c_dma_control,'Struct
samsung_dma_ops' is used for both 'S3C-DMA-OPS' for 's3cdma' and
Quoted 2 lines
'DMA-OPS' for 'dmaengine'.
If I modify "Structsamsung_dma_ops" as your guide, It gives un-expectable
Quoted 8 lines
Quoted 2 lines
effect to DMA-OPS.
Actually, We don't want the client with 'DMA-OPS' uses 'enum
s3c2410_chan_op'Quoted 1 line
operation anymore.
" enum
s3c2410_chan_op/* or similar */ " <<<< note 'or similar'Defining a callback for each value of the argument doesn't make sense.
Yes, The command may not be 'enum s3c2410_chan_op'. But it's very similar with 'enum s3c2410_chan_op'.
So, It brings same result that I sad.
Actually, I quietly agree with your comment. If the 'struct samsung_dma_ops' is only used for 's3c-dma-ops', I would address your comment. But, 'struct samsung_dma_ops' is used for all Samsung dma clients. I aim that 'struct samsung_dma_ops' provide the DMA clients with 'dmaengine' friendly DMA interface without any other command.
PATCH v4 7/14 ARM: EXYNOS4: Use generic DMA PL330 driver
In reply to Boojin KimThis patch makes Samsung EXYNOS4 to use DMA PL330 driver on DMADEVICE. The EXYNOS4 uses DMA generic APIs instead of SAMSUNG specific S3C-PL330 APIs.
--- arch/arm/mach-exynos4/Kconfig | 2 +- arch/arm/mach-exynos4/clock.c | 16 +- arch/arm/mach-exynos4/dma.c | 323 +++++++++++++++++++++++++++-------------- 3 files changed, 221 insertions(+), 120 deletions(-)
arch/arm/mach-exynos4/Kconfig +1 -1
@@ -11,7 +11,7 @@ if ARCH_EXYNOS4 config CPU_EXYNOS4210 bool - select S3C_PL330_DMA + select DMADEV_PL330 help Enable EXYNOS4210 CPU support
arch/arm/mach-exynos4/clock.c +9 -7
@@ -47,6 +47,11 @@ static struct clk clk_sclk_usbphy1 = { .id = -1, }; +static struct clk dummy_apb_pclk = { + .name ="apb_pclk" , + .id =-1 , +}; +static int exynos4_clksrc_mask_top_ctrl (struct clk *clk,int enable) {return s5p_gatectrl (S5P_CLKSRC_MASK_TOP , clk, enable);
@@ -485,16 +490,11 @@ static struct clk init_clocks_off[] = { .enable = exynos4_clk_ip_fsys_ctrl, .ctrlbit = (1 << 10), }, { - .name = "pdma", - .id = 0, + .name = "dma", + .id = -1, .enable = exynos4_clk_ip_fsys_ctrl, .ctrlbit = (1 << 0), }, { - .name = "pdma", - .id = 1, - .enable = exynos4_clk_ip_fsys_ctrl, - .ctrlbit = (1 << 1), - }, { .name = "adc", .id = -1, .enable = exynos4_clk_ip_peril_ctrl,
@@ -1212,5 +1212,7 @@ void __init exynos4_register_clocks(void)s3c_register_clocks (init_clocks_off,ARRAY_SIZE (init_clocks_off));s3c_disable_clocks (init_clocks_off,ARRAY_SIZE (init_clocks_off)); +s3c24xx_register_clock (&dummy_apb_pclk); +s3c_pwmclk_init (); }
arch/arm/mach-exynos4/dma.c +211 -112
362 lines not on this page · raw message
Signature · 1 line
1.7.1
PATCH v4 7/14 ARM: EXYNOS4: Use generic DMA PL330 driver
Quoted 26 lines · Boojin Kim
arch/arm/mach-exynos4/dma.c +0
-0@@ -21,151 +21,250 @@?* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ?*/
-#include <
linux/platform_device.h>
?#include <linux/dma-mapping.h>arch/arm/mach-exynos4/dma.c +3
-0+#include <linux/amba/bus.h> +#include <linux/amba/pl330.h> +#include <asm/irq.h> ?#include <
plat/devs.h>
?#include <plat/irqs.h>?#include <
mach/map.h>
?#include <mach/irqs.h>arch/arm/mach-exynos4/dma.c +1
-2- -#include <plat/s3c-pl330-pdata.h> +#include <mach/dma.h> ?static u64
dma_dmamask=DMA_BIT_MASK(32);arch/arm/mach-exynos4/dma.c +0
-1-static struct resource exynos4_pdma0_resource[] = {
arch/arm/mach-exynos4/dma.c
Quoted 10 lines
arch/arm/mach-exynos4/dma.c +1
-9- ? ? ? [0] = { - ? ? ? ? ? ? ? .start ?= EXYNOS4_PA_PDMA0, - ? ? ? ? ? ? ? .end ? ?= EXYNOS4_PA_PDMA0 + SZ_4K, - ? ? ? ? ? ? ? .flags ?= IORESOURCE_MEM, - ? ? ? }, - ? ? ? [1] = { - ? ? ? ? ? ? ? .start ?= IRQ_PDMA0, - ? ? ? ? ? ? ? .end ? ?= IRQ_PDMA0, - ? ? ? ? ? ? ? .flags ?= IORESOURCE_IRQ, +struct dma_pl330_peri pdma0_peri[32 ] = {
Please remove 32 from the list (it seems you don't always pass 32 elements) Also for completeness, please explicitly write element indices below because it's not some array of randomly placed elements.
Same for every other such occurance.
Quoted 128 lines
+ ? ? ? {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_PCM0_RX,
+ ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_PCM0_TX,
+ ? ? ? ? ? ? ? .rqtype = MEMTODEV,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_PCM2_RX,
+ ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_PCM2_TX,
+ ? ? ? ? ? ? ? .rqtype = MEMTODEV,
+ ? ? ? ? ? ? ? .burst_sz = 4,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_MSM_REQ0,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_MSM_REQ2,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SPI0_RX,
+ ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
+ ? ? ? ? ? ? ? .burst_sz = 1,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SPI0_TX,
+ ? ? ? ? ? ? ? .rqtype = MEMTODEV,
+ ? ? ? ? ? ? ? .burst_sz = 1,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SPI2_RX,
+ ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
+ ? ? ? ? ? ? ? .burst_sz = 1,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SPI2_TX,
+ ? ? ? ? ? ? ? .rqtype = MEMTODEV,
+ ? ? ? ? ? ? ? .burst_sz = 1,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_I2S0S_TX,
+ ? ? ? ? ? ? ? .rqtype = MEMTODEV,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_I2S0_RX,
+ ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_I2S0_TX,
+ ? ? ? ? ? ? ? .rqtype = MEMTODEV,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_UART0_RX,
+ ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
+ ? ? ? ? ? ? ? .burst_sz = 4,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_UART0_TX,
+ ? ? ? ? ? ? ? .rqtype = MEMTODEV,
+ ? ? ? ? ? ? ? .burst_sz = 4,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_UART2_RX,
+ ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
+ ? ? ? ? ? ? ? .burst_sz = 4,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_UART2_TX,
+ ? ? ? ? ? ? ? .rqtype = MEMTODEV,
+ ? ? ? ? ? ? ? .burst_sz = 4,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_UART4_RX,
+ ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
+ ? ? ? ? ? ? ? .burst_sz = 4,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_UART4_TX,
+ ? ? ? ? ? ? ? .rqtype = MEMTODEV,
+ ? ? ? ? ? ? ? .burst_sz = 4,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SLIMBUS0_RX,
+ ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SLIMBUS0_TX,
+ ? ? ? ? ? ? ? .rqtype = MEMTODEV,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SLIMBUS2_RX,
+ ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SLIMBUS2_TX,
+ ? ? ? ? ? ? ? .rqtype = MEMTODEV,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SLIMBUS4_RX,
+ ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_SLIMBUS4_TX,
+ ? ? ? ? ? ? ? .rqtype = MEMTODEV,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_AC97_MICIN,
+ ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
+ ? ? ? ? ? ? ? .burst_sz = 4,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_AC97_PCMIN,
+ ? ? ? ? ? ? ? .rqtype = DEVTOMEM,
+ ? ? ? ? ? ? ? .burst_sz = 4,
+ ? ? ? }, {
+ ? ? ? ? ? ? ? .peri_id = (u8)DMACH_AC97_PCMOUT,
+ ? ? ? ? ? ? ? .rqtype = MEMTODEV,
+ ? ? ? ? ? ? ? .burst_sz = 4,
? ? ? ?},
?};arch/arm/mach-exynos4/dma.c +0
-27-static struct s3c_pl330_platdata exynos4_pdma0_pdata = { - ? ? ? .peri = { - ? ? ? ? ? ? ? [0] = DMACH_PCM0_RX, - ? ? ? ? ? ? ? [1] = DMACH_PCM0_TX, - ? ? ? ? ? ? ? [2] = DMACH_PCM2_RX, - ? ? ? ? ? ? ? [3] = DMACH_PCM2_TX, - ? ? ? ? ? ? ? [4] = DMACH_MSM_REQ0, - ? ? ? ? ? ? ? [5] = DMACH_MSM_REQ2, - ? ? ? ? ? ? ? [6] = DMACH_SPI0_RX, - ? ? ? ? ? ? ? [7] = DMACH_SPI0_TX, - ? ? ? ? ? ? ? [8] = DMACH_SPI2_RX, - ? ? ? ? ? ? ? [9] = DMACH_SPI2_TX, - ? ? ? ? ? ? ? [10] = DMACH_I2S0S_TX, - ? ? ? ? ? ? ? [11] = DMACH_I2S0_RX, - ? ? ? ? ? ? ? [12] = DMACH_I2S0_TX, - ? ? ? ? ? ? ? [13] = DMACH_I2S2_RX, - ? ? ? ? ? ? ? [14] = DMACH_I2S2_TX, - ? ? ? ? ? ? ? [15] = DMACH_UART0_RX, - ? ? ? ? ? ? ? [16] = DMACH_UART0_TX, - ? ? ? ? ? ? ? [17] = DMACH_UART2_RX, - ? ? ? ? ? ? ? [18] = DMACH_UART2_TX, - ? ? ? ? ? ? ? [19] = DMACH_UART4_RX, - ? ? ? ? ? ? ? [20] = DMACH_UART4_TX, - ? ? ? ? ? ? ? [21] = DMACH_SLIMBUS0_RX, - ? ? ? ? ? ? ? [22] = DMACH_SLIMBUS0_TX, - ? ? ? ? ? ? ? [23] = DMACH_SLIMBUS2_RX, - ? ? ? ? ? ? ? [24] = DMACH_SLIMBUS2_TX,
arch/arm/mach-exynos4/dma.c
Quoted 10 lines
arch/arm/mach-exynos4/dma.c +2
-8- ? ? ? ? ? ? ? [25] = DMACH_SLIMBUS4_RX, - ? ? ? ? ? ? ? [26] = DMACH_SLIMBUS4_TX, - ? ? ? ? ? ? ? [27] = DMACH_AC97_MICIN, - ? ? ? ? ? ? ? [28] = DMACH_AC97_PCMIN, - ? ? ? ? ? ? ? [29] = DMACH_AC97_PCMOUT, - ? ? ? ? ? ? ? [30] = DMACH_MAX, - ? ? ? ? ? ? ? [31] = DMACH_MAX, - ? ? ? }, +struct dma_pl330_platdata exynos4_pdma0_pdata = { + ? ? ? .nr_valid_peri = 32,
Perhaps, this is why you had to add the NULL peri check. Please use ARRAY_SIZE here.
Same for every other such occurance.
PATCH v4 7/14 ARM: EXYNOS4: Use generic DMA PL330 driver
Jassi Brar Wrote:
Quoted 46 lines
Sent: Monday, July 25, 2011 9:00 PM
To: Boojin Kim
Cc: linux-arm-kernel at lists.infradead.org; linux-samsung- soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Grant Likely; Mark Brown
Subject: Re: [PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330 driverarch/arm/mach-
Quoted 1 line · Boojin Kim
arch/arm/mach- renamed from arch/arm/mach-exynos4/dma.c +0
-0
exynos4/dma.cQuoted 33 lines
index 564bb53..e1c00cf 100644
arch/arm/mach-exynos4/dma.c +4
-12@@ -21,151 +21,250 @@* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include <linux/platform_device.h> #include <linux/dma-mapping.h> +#include <linux/amba/bus.h> +#include <linux/amba/pl330.h> +#include <asm/irq.h> #include <plat/devs.h> #include <plat/irqs.h> #include <mach/map.h> #include <mach/irqs.h> - -#include <plat/s3c-pl330-pdata.h> +#include <mach/dma.h> static u64 dma_dmamask =DMA_BIT_MASK (32 ); -static struct resource exynos4_pdma0_resource[] = { - [0 ] = { - .start =EXYNOS4_PA_PDMA0 , - .end =EXYNOS4_PA_PDMA0 +SZ_4K , - .flags =IORESOURCE_MEM , - }, - [1 ] = { - .start =IRQ_PDMA0 , - .end =IRQ_PDMA0 ,
Quoted 8 lines
arch/arm/mach-exynos4/dma.c line 38
Quoted 2 lines
arch/arm/mach-exynos4/dma.c +1
-1- .flags = IORESOURCE_IRQ, +struct dma_pl330_peri pdma0_peri[32 ] = {Please remove 32 from the list (it seems you don't always pass 32 elements)
Also for completeness, please explicitly write element indices below because
it's not some array of randomly placed elements.
Same for every other such occurance.
I will address your comment.
Quoted 134 lines
Quoted 134 lines
arch/arm/mach-exynos4/dma.c +96
-32+ { + .peri_id = (u8)DMACH_PCM0_RX, + .rqtype = DEVTOMEM, + }, { + .peri_id = (u8)DMACH_PCM0_TX, + .rqtype = MEMTODEV, + }, { + .peri_id = (u8)DMACH_PCM2_RX, + .rqtype = DEVTOMEM, + }, { + .peri_id = (u8)DMACH_PCM2_TX, + .rqtype = MEMTODEV, + .burst_sz = 4, + }, { + .peri_id = (u8)DMACH_MSM_REQ0, + }, { + .peri_id = (u8)DMACH_MSM_REQ2, + }, { + .peri_id = (u8)DMACH_SPI0_RX, + .rqtype = DEVTOMEM, + .burst_sz = 1, + }, { + .peri_id = (u8)DMACH_SPI0_TX, + .rqtype = MEMTODEV, + .burst_sz = 1, + }, { + .peri_id = (u8)DMACH_SPI2_RX, + .rqtype = DEVTOMEM, + .burst_sz = 1, + }, { + .peri_id = (u8)DMACH_SPI2_TX, + .rqtype = MEMTODEV, + .burst_sz = 1, + }, { + .peri_id = (u8)DMACH_I2S0S_TX, + .rqtype = MEMTODEV, + }, { + .peri_id = (u8)DMACH_I2S0_RX, + .rqtype = DEVTOMEM, + }, { + .peri_id = (u8)DMACH_I2S0_TX, + .rqtype = MEMTODEV, + }, { + .peri_id = (u8)DMACH_UART0_RX, + .rqtype = DEVTOMEM, + .burst_sz = 4, + }, { + .peri_id = (u8)DMACH_UART0_TX, + .rqtype = MEMTODEV, + .burst_sz = 4, + }, { + .peri_id = (u8)DMACH_UART2_RX, + .rqtype = DEVTOMEM, + .burst_sz = 4, + }, { + .peri_id = (u8)DMACH_UART2_TX, + .rqtype = MEMTODEV, + .burst_sz = 4, + }, { + .peri_id = (u8)DMACH_UART4_RX, + .rqtype = DEVTOMEM, + .burst_sz = 4, + }, { + .peri_id = (u8)DMACH_UART4_TX, + .rqtype = MEMTODEV, + .burst_sz = 4, + }, { + .peri_id = (u8)DMACH_SLIMBUS0_RX, + .rqtype = DEVTOMEM, + }, { + .peri_id = (u8)DMACH_SLIMBUS0_TX, + .rqtype = MEMTODEV, + }, { + .peri_id = (u8)DMACH_SLIMBUS2_RX, + .rqtype = DEVTOMEM, + }, { + .peri_id = (u8)DMACH_SLIMBUS2_TX, + .rqtype = MEMTODEV, + }, { + .peri_id = (u8)DMACH_SLIMBUS4_RX, + .rqtype = DEVTOMEM, + }, { + .peri_id = (u8)DMACH_SLIMBUS4_TX, + .rqtype = MEMTODEV, + }, { + .peri_id = (u8)DMACH_AC97_MICIN, + .rqtype = DEVTOMEM, + .burst_sz = 4, + }, { + .peri_id = (u8)DMACH_AC97_PCMIN, + .rqtype = DEVTOMEM, + .burst_sz = 4, + }, { + .peri_id = (u8)DMACH_AC97_PCMOUT, + .rqtype = MEMTODEV, + .burst_sz = 4, }, }; -static struct s3c_pl330_platdata exynos4_pdma0_pdata = { - .peri = { - [0 ] =DMACH_PCM0_RX , - [1 ] =DMACH_PCM0_TX , - [2 ] =DMACH_PCM2_RX , - [3 ] =DMACH_PCM2_TX , - [4 ] =DMACH_MSM_REQ0 , - [5 ] =DMACH_MSM_REQ2 , - [6 ] =DMACH_SPI0_RX , - [7 ] =DMACH_SPI0_TX , - [8 ] =DMACH_SPI2_RX , - [9 ] =DMACH_SPI2_TX , - [10 ] =DMACH_I2S0S_TX , - [11 ] =DMACH_I2S0_RX , - [12 ] =DMACH_I2S0_TX , - [13 ] =DMACH_I2S2_RX , - [14 ] =DMACH_I2S2_TX , - [15 ] =DMACH_UART0_RX , - [16 ] =DMACH_UART0_TX , - [17 ] =DMACH_UART2_RX , - [18 ] =DMACH_UART2_TX , - [19 ] =DMACH_UART4_RX , - [20 ] =DMACH_UART4_TX , - [21 ] =DMACH_SLIMBUS0_RX , - [22 ] =DMACH_SLIMBUS0_TX , - [23 ] =DMACH_SLIMBUS2_RX , - [24 ] =DMACH_SLIMBUS2_TX , - [25 ] =DMACH_SLIMBUS4_RX , - [26 ] =DMACH_SLIMBUS4_TX , - [27 ] =DMACH_AC97_MICIN , - [28 ] =DMACH_AC97_PCMIN , - [29 ] =DMACH_AC97_PCMOUT ,
Quoted 8 lines
arch/arm/mach-exynos4/dma.c line 139
Quoted 5 lines
arch/arm/mach-exynos4/dma.c +2
-3- [30] = DMACH_MAX, - [31] = DMACH_MAX, - }, +struct dma_pl330_platdata exynos4_pdma0_pdata = { + .nr_valid_peri =32 ,Perhaps, this is why you had to add the NULL peri check. Please use
ARRAY_SIZEhere.
Same for every other such occurance.
I will address your comment.
PATCH v4 8/14 ARM: S5PV210: Use generic DMA PL330 driver
In reply to Boojin KimThis patch makes Samsung S5PV210 to use DMA PL330 driver on DMADEVICE. The S5PV210 uses DMA generic APIs instead of SAMSUNG specific S3C-PL330 APIs.
--- arch/arm/mach-s5pv210/Kconfig | 2 +- arch/arm/mach-s5pv210/clock.c | 16 +- arch/arm/mach-s5pv210/dma.c | 346 +++++++++++++++++++++++++++-------------- 3 files changed, 241 insertions(+), 123 deletions(-)
arch/arm/mach-s5pv210/Kconfig +1 -1
@@ -11,7 +11,7 @@ if ARCH_S5PV210 config CPU_S5PV210 bool - select S3C_PL330_DMA + select DMADEV_PL330 select S5P_EXT_INT select S5P_HRT select S5PV210_PM if PM
arch/arm/mach-s5pv210/clock.c +8 -8
@@ -221,6 +221,11 @@ static struct clk clk_pcmcdclk2 = { .id = -1, }; +static struct clk dummy_apb_pclk = { + .name ="apb_pclk" , + .id =-1 , +}; +static struct clk *clkset_vpllsrc_list[] = { [0 ] = &clk_fin_vpll, [1 ] = &clk_sclk_hdmi27m,
@@ -311,18 +316,12 @@ static struct clk_ops clk_fout_apll_ops = {static struct clk init_clocks_off[] = { { - .name ="pdma" , - .id =0 , + .name ="dma" , + .id =-1 , .parent = &clk_hclk_psys.clk, .enable = s5pv210_clk_ip0_ctrl, .ctrlbit = (1 <<3 ), }, { - .name ="pdma" , - .id =1 , - .parent = &clk_hclk_psys.clk, - .enable = s5pv210_clk_ip0_ctrl, - .ctrlbit = (1 <<4 ), - }, { .name ="rot" , .id =-1 , .parent = &clk_hclk_dsys.clk,
@@ -1239,5 +1238,6 @@ void __init s5pv210_register_clocks(void)s3c_register_clocks (init_clocks_off,ARRAY_SIZE (init_clocks_off));s3c_disable_clocks (init_clocks_off,ARRAY_SIZE (init_clocks_off)); +s3c24xx_register_clock (&dummy_apb_pclk);s3c_pwmclk_init (); }
arch/arm/mach-s5pv210/dma.c +232 -114
387 lines not on this page · raw message
Signature · 1 line
1.7.1
PATCH v4 9/14 ARM: S5PC100: Use generic DMA PL330 driver
In reply to Boojin KimThis patch makes Samsung S5PC100 to use DMA PL330 driver on DMADEVICE. The S5PC100 uses DMA generic APIs instead of SAMSUNG specific S3C-PL330 APIs.
--- arch/arm/mach-s5pc100/Kconfig | 2 +- arch/arm/mach-s5pc100/clock.c | 23 +-- arch/arm/mach-s5pc100/dma.c | 357 ++++++++++++++++++++++++++++------------- 3 files changed, 253 insertions(+), 129 deletions(-)
arch/arm/mach-s5pc100/Kconfig +1 -1
@@ -10,7 +10,7 @@ if ARCH_S5PC100 config CPU_S5PC100 bool select S5P_EXT_INT - select S3C_PL330_DMA + select DMADEV_PL330 help Enable S5PC100 CPU support
arch/arm/mach-s5pc100/clock.c +9 -14
@@ -34,6 +34,11 @@ static struct clk s5p_clk_otgphy = { .id = -1, }; +static struct clk dummy_apb_pclk = { + .name ="apb_pclk" , + .id =-1 , +}; +static struct clk *clk_src_mout_href_list[] = { [0 ] = &s5p_clk_27m, [1 ] = &clk_fin_hpll,
@@ -416,12 +421,6 @@ static struct clk init_clocks_off[] = { .enable = s5pc100_d0_0_ctrl, .ctrlbit = (1 << 4), }, { - .name = "mdma", - .id = -1, - .parent = &clk_div_d0_bus.clk, - .enable = s5pc100_d0_0_ctrl, - .ctrlbit = (1 << 3), - }, { .name = "cfcon", .id = -1, .parent = &clk_div_d0_bus.clk,
@@ -488,14 +487,8 @@ static struct clk init_clocks_off[] = { .enable = s5pc100_d1_0_ctrl, .ctrlbit = (1 << 2), }, { - .name = "pdma", - .id = 1, - .parent = &clk_div_d1_bus.clk, - .enable = s5pc100_d1_0_ctrl, - .ctrlbit = (1 << 1), - }, { - .name = "pdma", - .id = 0, + .name = "dma", + .id = -1, .parent = &clk_div_d1_bus.clk, .enable = s5pc100_d1_0_ctrl, .ctrlbit = (1 << 0),
@@ -1394,5 +1387,7 @@ void __init s5pc100_register_clocks(void)s3c_register_clocks (init_clocks_off,ARRAY_SIZE (init_clocks_off));s3c_disable_clocks (init_clocks_off,ARRAY_SIZE (init_clocks_off)); +s3c24xx_register_clock (&dummy_apb_pclk); +s3c_pwmclk_init (); }
arch/arm/mach-s5pc100/dma.c +243 -114
397 lines not on this page · raw message
Signature · 1 line
1.7.1
PATCH v4 10/14 ARM: S5P64X0: Use generic DMA PL330 driver
In reply to Boojin KimThis patch makes Samsung S5P64X0 to use DMA PL330 driver on DMADEVICE. The S5P64X0 uses DMA generic APIs instead of SAMSUNG specific S3C-PL330 APIs.
--- arch/arm/mach-s5p64x0/Kconfig | 4 +- arch/arm/mach-s5p64x0/clock-s5p6440.c | 9 +- arch/arm/mach-s5p64x0/clock-s5p6450.c | 9 +- arch/arm/mach-s5p64x0/dma.c | 317 +++++++++++++++++++++++---------- 4 files changed, 242 insertions(+), 97 deletions(-)
arch/arm/mach-s5p64x0/Kconfig +2 -2
@@ -9,14 +9,14 @@ if ARCH_S5P64X0 config CPU_S5P6440 bool - select S3C_PL330_DMA + select DMADEV_PL330 select S5P_HRT help Enable S5P6440 CPU support config CPU_S5P6450 bool - select S3C_PL330_DMA + select DMADEV_PL330 select S5P_HRT help Enable S5P6450 CPU support
arch/arm/mach-s5p64x0/clock-s5p6440.c +8 -1
@@ -153,7 +153,7 @@ static struct clk init_clocks_off[] = { .enable = s5p64x0_hclk0_ctrl, .ctrlbit = (1 << 8), }, { - .name = "pdma", + .name = "dma", .id = -1, .parent = &clk_hclk_low.clk, .enable = s5p64x0_hclk0_ctrl,
@@ -533,6 +533,11 @@ static struct clksrc_clk *sysclks[] = { &clk_pclk_low, }; +static struct clk dummy_apb_pclk = { + .name ="apb_pclk" , + .id =-1 , +}; + void __init_or_cpufreq s5p6440_setup_clocks(void) {struct clk *xtal_clk;
@@ -615,5 +620,7 @@ void __init s5p6440_register_clocks(void)s3c_register_clocks (init_clocks_off,ARRAY_SIZE (init_clocks_off));s3c_disable_clocks (init_clocks_off,ARRAY_SIZE (init_clocks_off)); +s3c24xx_register_clock (&dummy_apb_pclk); +s3c_pwmclk_init (); }
arch/arm/mach-s5p64x0/clock-s5p6450.c +8 -1
@@ -189,7 +189,7 @@ static struct clk init_clocks_off[] = { .enable = s5p64x0_hclk0_ctrl, .ctrlbit = (1 << 3), }, { - .name = "pdma", + .name = "dma", .id = -1, .parent = &clk_hclk_low.clk, .enable = s5p64x0_hclk0_ctrl,
@@ -583,6 +583,11 @@ static struct clksrc_clk *sysclks[] = { &clk_sclk_audio0, }; +static struct clk dummy_apb_pclk = { + .name ="apb_pclk" , + .id =-1 , +}; + void __init_or_cpufreq s5p6450_setup_clocks(void) {struct clk *xtal_clk;
@@ -662,5 +667,7 @@ void __init s5p6450_register_clocks(void)s3c_register_clocks (init_clocks_off,ARRAY_SIZE (init_clocks_off));s3c_disable_clocks (init_clocks_off,ARRAY_SIZE (init_clocks_off)); +s3c24xx_register_clock (&dummy_apb_pclk); +s3c_pwmclk_init (); }
arch/arm/mach-s5p64x0/dma.c +224 -93
354 lines not on this page · raw message
Signature · 1 line
1.7.1
PATCH v4 11/14 ARM: SAMSUNG: Remove S3C-PL330-DMA driver
In reply to Boojin KimSince DMA generic APIs can be used for Samsung DMA now so that the s3c-pl330 which includes Samsung specific DMA APIs can be removed.
--- arch/arm/plat-samsung/Kconfig | 6 - arch/arm/plat-samsung/Makefile | 2 - arch/arm/plat-samsung/include/plat/dma-pl330.h | 9 +- .../plat-samsung/include/plat/s3c-pl330-pdata.h | 32 - arch/arm/plat-samsung/s3c-pl330.c | 1244 -------------------- 5 files changed, 6 insertions(+), 1287 deletions(-) delete mode 100644 arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h delete mode 100644 arch/arm/plat-samsung/s3c-pl330.c
arch/arm/plat-samsung/Kconfig +0 -6
@@ -294,12 +294,6 @@ config S3C_DMA help Internal configuration for S3C DMA core -config S3C_PL330_DMA - bool - select PL330 - help - S3C DMA API Driver for PL330 DMAC. - config DMADEV_PL330 bool select DMADEVICES
arch/arm/plat-samsung/Makefile +0 -2
@@ -66,8 +66,6 @@ obj-$(CONFIG_S3C_DMA) += dma.o s3c-dma-ops.o obj-$(CONFIG_DMADEV_PL330) += dma-ops.o -obj-$(CONFIG_S3C_PL330_DMA) += s3c-pl330.o s3c-dma-ops.o - # PM support obj-$(CONFIG_PM) += pm.o
arch/arm/plat-samsung/include/plat/dma-pl330.h +6 -3
@@ -11,8 +11,6 @@#ifndef __DMA_PL330_H_#define __DMA_PL330_H_ __FILE__ -#define S3C2410_DMAF_AUTOSTART (1 << 0) -#define S3C2410_DMAF_CIRCULAR (1 << 1)/* * PL330 can assign any channel to communicate with * any of the peripherals attched to the DMAC.
@@ -95,6 +93,10 @@ enum dma_ch { DMACH_MAX, }; +struct s3c2410_dma_client { +char *name; +}; +static inline bool s3c_dma_has_circular (void ) {return true;
@@ -104,6 +106,7 @@ static inline bool samsung_dma_is_dmadev(void) {return true; } -#include <plat/dma.h> + +#include <plat/dma-ops.h> #endif /* __DMA_PL330_H_ */
arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h deleted +0 -32
@@ -1,32 +0,0 @@ -/* linux/arch/arm/plat-samsung/include/plat/s3c-pl330-pdata.h -* -* Copyright (C) 2010 Samsung Electronics Co. Ltd. -* Jaswinder Singh <[email protected]> -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -*/ - -#ifndef __S3C_PL330_PDATA_H -#define __S3C_PL330_PDATA_H - -#include <plat/dma-pl330.h> - -/* -* Every PL330 DMAC has max 32 peripheral interfaces, -* of which some may be not be really used in your -* DMAC's configuration. -* Populate this array of 32 peri i/fs with relevant -* channel IDs for used peri i/f and DMACH_MAX for -* those unused. -* -* The platforms just need to provide this info -* to the S3C DMA API driver for PL330. -*/ -struct s3c_pl330_platdata { -enum dma_ch peri[32 ]; -}; - -#endif /* __S3C_PL330_PDATA_H */
arch/arm/plat-samsung/s3c-pl330.c deleted +0 -1244
1,244 lines not on this page · raw message
Signature · 1 line
1.7.1
PATCH v4 12/14 spi/s3c64xx: Add support DMA engine API
In reply to Boojin KimThis patch adds to support DMA generic API to transfer raw SPI data. Basiclly the spi driver uses DMA generic API if architecture supports it. Otherwise, uses Samsung specific S3C-PL330 APIs.
--- drivers/spi/spi_s3c64xx.c | 141 ++++++++++++++++++++++----------------------- 1 files changed, 69 insertions(+), 72 deletions(-)
drivers/spi/spi_s3c64xx.c +69 -72
@@ -172,6 +172,9 @@ struct s3c64xx_spi_driver_data {unsigned state;unsigned cur_mode, cur_bpw;unsigned cur_speed; +unsigned rx_ch; +unsigned tx_ch; +struct samsung_dma_ops *ops; };static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
@@ -227,6 +230,38 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)writel (val, regs +S3C64XX_SPI_CH_CFG ); } +static void s3c64xx_spi_dma_rxcb (void *data) +{ +struct s3c64xx_spi_driver_data *sdd + = (struct s3c64xx_spi_driver_data *)data; +unsigned long flags; + +spin_lock_irqsave (&sdd->lock, flags); + + sdd->state &= ~RXBUSY ; +/* If the other done */ +if (!(sdd->state &TXBUSY )) +complete (&sdd->xfer_completion); + +spin_unlock_irqrestore (&sdd->lock, flags); +} + +static void s3c64xx_spi_dma_txcb (void *data) +{ +struct s3c64xx_spi_driver_data *sdd + = (struct s3c64xx_spi_driver_data *)data; +unsigned long flags; + +spin_lock_irqsave (&sdd->lock, flags); + + sdd->state &= ~TXBUSY ; +/* If the other done */ +if (!(sdd->state &RXBUSY )) +complete (&sdd->xfer_completion); + +spin_unlock_irqrestore (&sdd->lock, flags); +} +static void enable_datapath (struct s3c64xx_spi_driver_data *sdd,struct spi_device *spi,struct spi_transfer *xfer,int dma_mode)
@@ -234,6 +269,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,struct s3c64xx_spi_info *sci = sdd->cntrlr_info;void __iomem *regs = sdd->regs;u32 modecfg, chcfg; +struct samsung_dma_prep_info info; modecfg =readl (regs +S3C64XX_SPI_MODE_CFG ); modecfg &= ~(S3C64XX_SPI_MODE_TXDMA_ON |S3C64XX_SPI_MODE_RXDMA_ON );
@@ -259,10 +295,14 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, chcfg |=S3C64XX_SPI_CH_TXCH_ON ;if (dma_mode) { modecfg |=S3C64XX_SPI_MODE_TXDMA_ON ; -s3c2410_dma_config (sdd->tx_dmach, sdd->cur_bpw /8 ); -s3c2410_dma_enqueue (sdd->tx_dmach, (void *)sdd, - xfer->tx_dma, xfer->len); -s3c2410_dma_ctrl (sdd->tx_dmach,S3C2410_DMAOP_START ); + info.cap =DMA_SLAVE ; + info.direction =DMA_TO_DEVICE ; + info.buf = xfer->tx_dma; + info.len = xfer->len; + info.fp = s3c64xx_spi_dma_txcb; + info.fp_param = sdd; + sdd->ops->prepare (sdd->tx_ch, &info); + sdd->ops->trigger (sdd->tx_ch); }else {switch (sdd->cur_bpw) {case 32 :
@@ -294,10 +334,14 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,writel (((xfer->len *8 / sdd->cur_bpw) &0xffff ) |S3C64XX_SPI_PACKET_CNT_EN , regs +S3C64XX_SPI_PACKET_CNT ); -s3c2410_dma_config (sdd->rx_dmach, sdd->cur_bpw /8 ); -s3c2410_dma_enqueue (sdd->rx_dmach, (void *)sdd, - xfer->rx_dma, xfer->len); -s3c2410_dma_ctrl (sdd->rx_dmach,S3C2410_DMAOP_START ); + info.cap =DMA_SLAVE ; + info.direction =DMA_FROM_DEVICE ; + info.buf = xfer->rx_dma; + info.len = xfer->len; + info.fp = s3c64xx_spi_dma_rxcb; + info.fp_param = sdd; + sdd->ops->prepare (sdd->rx_ch, &info); + sdd->ops->trigger (sdd->rx_ch); } }
@@ -483,46 +527,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) } } -static void s3c64xx_spi_dma_rxcb (struct s3c2410_dma_chan *chan,void *buf_id, -int size,enum s3c2410_dma_buffresult res) -{ -struct s3c64xx_spi_driver_data *sdd = buf_id; -unsigned long flags; - -spin_lock_irqsave (&sdd->lock, flags); - -if (res ==S3C2410_RES_OK ) - sdd->state &= ~RXBUSY ; -else -dev_err (&sdd->pdev->dev,"DmaAbrtRx-%d\n" , size); - -/* If the other done */ -if (!(sdd->state &TXBUSY )) -complete (&sdd->xfer_completion); - -spin_unlock_irqrestore (&sdd->lock, flags); -} - -static void s3c64xx_spi_dma_txcb (struct s3c2410_dma_chan *chan,void *buf_id, -int size,enum s3c2410_dma_buffresult res) -{ -struct s3c64xx_spi_driver_data *sdd = buf_id; -unsigned long flags; - -spin_lock_irqsave (&sdd->lock, flags); - -if (res ==S3C2410_RES_OK ) - sdd->state &= ~TXBUSY ; -else -dev_err (&sdd->pdev->dev,"DmaAbrtTx-%d \n" , size); - -/* If the other done */ -if (!(sdd->state &RXBUSY )) -complete (&sdd->xfer_completion); - -spin_unlock_irqrestore (&sdd->lock, flags); -} -#define XFER_DMAADDR_INVALID DMA_BIT_MASK(32) static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
@@ -697,12 +701,10 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,if (use_dma) {if (xfer->tx_buf !=NULL && (sdd->state &TXBUSY )) -s3c2410_dma_ctrl (sdd->tx_dmach, -S3C2410_DMAOP_FLUSH ); + sdd->ops->stop (sdd->tx_ch);if (xfer->rx_buf !=NULL && (sdd->state &RXBUSY )) -s3c2410_dma_ctrl (sdd->rx_dmach, -S3C2410_DMAOP_FLUSH ); + sdd->ops->stop (sdd->rx_ch); } goto out;
@@ -742,24 +744,19 @@ out:static int acquire_dma (struct s3c64xx_spi_driver_data *sdd) { -if (s3c2410_dma_request (sdd->rx_dmach, - &s3c64xx_spi_dma_client,NULL ) <0 ) { -dev_err (&sdd->pdev->dev,"cannot get RxDMA\n" ); -return 0 ; - } -s3c2410_dma_set_buffdone_fn (sdd->rx_dmach, s3c64xx_spi_dma_rxcb); -s3c2410_dma_devconfig (sdd->rx_dmach,S3C2410_DMASRC_HW , - sdd->sfr_start +S3C64XX_SPI_RX_DATA ); - -if (s3c2410_dma_request (sdd->tx_dmach, - &s3c64xx_spi_dma_client,NULL ) <0 ) { -dev_err (&sdd->pdev->dev,"cannot get TxDMA\n" ); -s3c2410_dma_free (sdd->rx_dmach, &s3c64xx_spi_dma_client); -return 0 ; - } -s3c2410_dma_set_buffdone_fn (sdd->tx_dmach, s3c64xx_spi_dma_txcb); -s3c2410_dma_devconfig (sdd->tx_dmach,S3C2410_DMASRC_MEM , - sdd->sfr_start +S3C64XX_SPI_TX_DATA ); + +struct samsung_dma_info info; + sdd->ops =samsung_dma_get_ops (); + + info.cap =DMA_SLAVE ; + info.client = &s3c64xx_spi_dma_client; + info.direction =DMA_FROM_DEVICE ; + info.fifo = sdd->sfr_start +S3C64XX_SPI_RX_DATA ; + info.width = sdd->cur_bpw /8 ; + sdd->rx_ch = sdd->ops->request (sdd->rx_dmach, &info); + info.direction =DMA_TO_DEVICE ; + info.fifo = sdd->sfr_start +S3C64XX_SPI_TX_DATA ; + sdd->tx_ch = sdd->ops->request (sdd->tx_dmach, &info);return 1 ; }
@@ -800,8 +797,8 @@ static void s3c64xx_spi_work(struct work_struct *work)spin_unlock_irqrestore (&sdd->lock, flags);/* Free DMA channels */ -s3c2410_dma_free (sdd->tx_dmach, &s3c64xx_spi_dma_client); -s3c2410_dma_free (sdd->rx_dmach, &s3c64xx_spi_dma_client); + sdd->ops->release (sdd->rx_ch, &s3c64xx_spi_dma_client); + sdd->ops->release (sdd->tx_ch, &s3c64xx_spi_dma_client); } static int s3c64xx_spi_transfer(struct spi_device *spi,
Signature · 1 line
1.7.1
PATCH v4 12/14 spi/s3c64xx: Add support DMA engine API
drivers/spi/spi_s3c64xx.c static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) · line 236
Quoted 4 lines · Boojin Kim
drivers/spi/spi_s3c64xx.c +4
-0+static void s3c64xx_spi_dma_rxcb (void *data) +{ +struct s3c64xx_spi_driver_data *sdd + = (struct s3c64xx_spi_driver_data *)data;
You never need explicit casts from void * or to void *. Please remove these.
PATCH v4 12/14 spi/s3c64xx: Add support DMA engine API
Russell King - ARM Linux Wrote:
Quoted 3 lines
Sent: Monday, July 25, 2011 6:40 PM
To: Boojin Kim
Cc: linux-arm-kernel at lists.infradead.org;
linux-samsung-soc at vger.kernel.org;
Quoted 11 lines
Kukjin Kim; Vinod Koul; Jassi Brar; Grant Likely; Mark Brown; Dan Williams
Subject: Re: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine APIdrivers/spi/spi_s3c64xx.c static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) · line 236
Quoted 4 lines · Boojin Kim
drivers/spi/spi_s3c64xx.c +4
-0+static void s3c64xx_spi_dma_rxcb (void *data) +{ +struct s3c64xx_spi_driver_data *sdd + = (struct s3c64xx_spi_driver_data *)data;You never need explicit casts from void * or to void *. Please remove these.
I will address your comment.
PATCH v4 12/14 spi/s3c64xx: Add support DMA engine API
In reply to Boojin KimQuoted 51 lines · Boojin Kim
This patch adds to support DMA generic API to transfer raw SPI data. Basiclly the spi driver uses DMA generic API if architecture supports it. Otherwise, uses Samsung specific S3C-PL330 APIs.
Signed-off-by Boojin Kim <[email protected]>Cc Grant Likely <[email protected]>Signed-off-by Kukjin Kim <[email protected]>--- drivers/spi/spi_s3c64xx.c | 141 ++++++++++++++++++++++----------------------- 1 files changed, 69 insertions(+), 72 deletions(-)drivers/spi/spi_s3c64xx.c +24
-0@@ -172,6 +172,9 @@ struct s3c64xx_spi_driver_data {unsigned state;unsigned cur_mode, cur_bpw;unsigned cur_speed; +unsigned rx_ch; +unsigned tx_ch; +struct samsung_dma_ops *ops; };static struct s3c2410_dma_client s3c64xx_spi_dma_client = {@@ -227,6 +230,38 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)writel (val, regs +S3C64XX_SPI_CH_CFG ); } +static void s3c64xx_spi_dma_rxcb (void *data) +{ +struct s3c64xx_spi_driver_data *sdd + = (struct s3c64xx_spi_driver_data *)data; +unsigned long flags; + +spin_lock_irqsave (&sdd->lock, flags); + + sdd->state &= ~RXBUSY ; +/* If the other done */ +if (!(sdd->state &TXBUSY )) +complete (&sdd->xfer_completion); + +spin_unlock_irqrestore (&sdd->lock, flags); +} + +static void s3c64xx_spi_dma_txcb (void *data) +{ +struct s3c64xx_spi_driver_data *sdd + = (struct s3c64xx_spi_driver_data *)data; +unsigned long flags;
drivers/spi/spi_s3c64xx.c static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) · line 263
Quoted 10 lines
drivers/spi/spi_s3c64xx.c +10
-0+ +spin_lock_irqsave (&sdd->lock, flags); + + sdd->state &= ~TXBUSY ; +/* If the other done */ +if (!(sdd->state &RXBUSY )) +complete (&sdd->xfer_completion); + +spin_unlock_irqrestore (&sdd->lock, flags); +}
I don't see much diff in these two functions and you should be able to use a generic one which takes care of both TX and RX, does your callback data know if the channel is for TX or RX? If not then a helper to do above should take care well and making code simpler
Quoted 161 lines
drivers/spi/spi_s3c64xx.c +35
-72+static void enable_datapath (struct s3c64xx_spi_driver_data *sdd,struct spi_device *spi,struct spi_transfer *xfer,int dma_mode)@@ -234,6 +269,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,struct s3c64xx_spi_info *sci = sdd->cntrlr_info;void __iomem *regs = sdd->regs;u32 modecfg, chcfg; +struct samsung_dma_prep_info info; modecfg =readl (regs +S3C64XX_SPI_MODE_CFG ); modecfg &= ~(S3C64XX_SPI_MODE_TXDMA_ON |S3C64XX_SPI_MODE_RXDMA_ON );@@ -259,10 +295,14 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd, chcfg |=S3C64XX_SPI_CH_TXCH_ON ;if (dma_mode) { modecfg |=S3C64XX_SPI_MODE_TXDMA_ON ; -s3c2410_dma_config (sdd->tx_dmach, sdd->cur_bpw /8 ); -s3c2410_dma_enqueue (sdd->tx_dmach, (void *)sdd, - xfer->tx_dma, xfer->len); -s3c2410_dma_ctrl (sdd->tx_dmach,S3C2410_DMAOP_START ); + info.cap =DMA_SLAVE ; + info.direction =DMA_TO_DEVICE ; + info.buf = xfer->tx_dma; + info.len = xfer->len; + info.fp = s3c64xx_spi_dma_txcb; + info.fp_param = sdd; + sdd->ops->prepare (sdd->tx_ch, &info); + sdd->ops->trigger (sdd->tx_ch); }else {switch (sdd->cur_bpw) {case 32 :@@ -294,10 +334,14 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,writel (((xfer->len *8 / sdd->cur_bpw) &0xffff ) |S3C64XX_SPI_PACKET_CNT_EN , regs +S3C64XX_SPI_PACKET_CNT ); -s3c2410_dma_config (sdd->rx_dmach, sdd->cur_bpw /8 ); -s3c2410_dma_enqueue (sdd->rx_dmach, (void *)sdd, - xfer->rx_dma, xfer->len); -s3c2410_dma_ctrl (sdd->rx_dmach,S3C2410_DMAOP_START ); + info.cap =DMA_SLAVE ; + info.direction =DMA_FROM_DEVICE ; + info.buf = xfer->rx_dma; + info.len = xfer->len; + info.fp = s3c64xx_spi_dma_rxcb; + info.fp_param = sdd; + sdd->ops->prepare (sdd->rx_ch, &info); + sdd->ops->trigger (sdd->rx_ch); } }@@ -483,46 +527,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd) } } -static void s3c64xx_spi_dma_rxcb (struct s3c2410_dma_chan *chan,void *buf_id, -int size,enum s3c2410_dma_buffresult res) -{ -struct s3c64xx_spi_driver_data *sdd = buf_id; -unsigned long flags; - -spin_lock_irqsave (&sdd->lock, flags); - -if (res ==S3C2410_RES_OK ) - sdd->state &= ~RXBUSY ; -else -dev_err (&sdd->pdev->dev,"DmaAbrtRx-%d\n" , size); - -/* If the other done */ -if (!(sdd->state &TXBUSY )) -complete (&sdd->xfer_completion); - -spin_unlock_irqrestore (&sdd->lock, flags); -} - -static void s3c64xx_spi_dma_txcb (struct s3c2410_dma_chan *chan,void *buf_id, -int size,enum s3c2410_dma_buffresult res) -{ -struct s3c64xx_spi_driver_data *sdd = buf_id; -unsigned long flags; - -spin_lock_irqsave (&sdd->lock, flags); - -if (res ==S3C2410_RES_OK ) - sdd->state &= ~TXBUSY ; -else -dev_err (&sdd->pdev->dev,"DmaAbrtTx-%d \n" , size); - -/* If the other done */ -if (!(sdd->state &RXBUSY )) -complete (&sdd->xfer_completion); - -spin_unlock_irqrestore (&sdd->lock, flags); -} -#define XFER_DMAADDR_INVALID DMA_BIT_MASK(32) static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,@@ -697,12 +701,10 @@ static void handle_msg(struct s3c64xx_spi_driver_data *sdd,if (use_dma) {if (xfer->tx_buf !=NULL && (sdd->state &TXBUSY )) -s3c2410_dma_ctrl (sdd->tx_dmach, -S3C2410_DMAOP_FLUSH ); + sdd->ops->stop (sdd->tx_ch);if (xfer->rx_buf !=NULL && (sdd->state &RXBUSY )) -s3c2410_dma_ctrl (sdd->rx_dmach, -S3C2410_DMAOP_FLUSH ); + sdd->ops->stop (sdd->rx_ch); } goto out;@@ -742,24 +744,19 @@ out:static int acquire_dma (struct s3c64xx_spi_driver_data *sdd) { -if (s3c2410_dma_request (sdd->rx_dmach, - &s3c64xx_spi_dma_client,NULL ) <0 ) { -dev_err (&sdd->pdev->dev,"cannot get RxDMA\n" ); -return 0 ; - } -s3c2410_dma_set_buffdone_fn (sdd->rx_dmach, s3c64xx_spi_dma_rxcb); -s3c2410_dma_devconfig (sdd->rx_dmach,S3C2410_DMASRC_HW , - sdd->sfr_start +S3C64XX_SPI_RX_DATA ); - -if (s3c2410_dma_request (sdd->tx_dmach, - &s3c64xx_spi_dma_client,NULL ) <0 ) { -dev_err (&sdd->pdev->dev,"cannot get TxDMA\n" ); -s3c2410_dma_free (sdd->rx_dmach, &s3c64xx_spi_dma_client); -return 0 ; - } -s3c2410_dma_set_buffdone_fn (sdd->tx_dmach, s3c64xx_spi_dma_txcb); -s3c2410_dma_devconfig (sdd->tx_dmach,S3C2410_DMASRC_MEM , - sdd->sfr_start +S3C64XX_SPI_TX_DATA ); + +struct samsung_dma_info info; + sdd->ops =samsung_dma_get_ops (); + + info.cap =DMA_SLAVE ; + info.client = &s3c64xx_spi_dma_client; + info.direction =DMA_FROM_DEVICE ; + info.fifo = sdd->sfr_start +S3C64XX_SPI_RX_DATA ; + info.width = sdd->cur_bpw /8 ; + sdd->rx_ch = sdd->ops->request (sdd->rx_dmach, &info); + info.direction =DMA_TO_DEVICE ; + info.fifo = sdd->sfr_start +S3C64XX_SPI_TX_DATA ; + sdd->tx_ch = sdd->ops->request (sdd->tx_dmach, &info);return 1 ; }@@ -800,8 +797,8 @@ static void s3c64xx_spi_work(struct work_struct *work)spin_unlock_irqrestore (&sdd->lock, flags);/* Free DMA channels */ -s3c2410_dma_free (sdd->tx_dmach, &s3c64xx_spi_dma_client); -s3c2410_dma_free (sdd->rx_dmach, &s3c64xx_spi_dma_client); + sdd->ops->release (sdd->rx_ch, &s3c64xx_spi_dma_client); + sdd->ops->release (sdd->tx_ch, &s3c64xx_spi_dma_client); } static int s3c64xx_spi_transfer(struct spi_device *spi,
Signature · 2 lines
~Vinod Koul Intel Corp.
PATCH v4 12/14 spi/s3c64xx: Add support DMA engine API
Vinod Koul Wrote:
Quoted 68 lines
Sent: Monday, July 25, 2011 8:17 PM
To: Boojin Kim
Cc: vinod.koul at intel.com; linux-arm-kernel at lists.infradead.org; linux- samsung-soc at vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely; Mark Brown; Dan Williams
Subject: Re: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine APIQuoted 10 lines · Boojin Kim
This patch adds to support DMA generic API to transfer raw SPI data. Basiclly the spi driver uses DMA generic API if architecture supports it. Otherwise, uses Samsung specific S3C-PL330 APIs.
Signed-off-by Boojin Kim <[email protected]>Cc Grant Likely <[email protected]>Signed-off-by Kukjin Kim <[email protected]>--- drivers/spi/spi_s3c64xx.c | 141 ++++++++++++++++++++++-----------------------
drivers/spi/spi_s3c64xx.c static void flush_fifo(struct
Quoted 17 lines
1 files changed, 69 insertions(+), 72 deletions(-)drivers/spi/spi_s3c64xx.c +3
-0@@ -172,6 +172,9 @@ struct s3c64xx_spi_driver_data {unsigned state;unsigned cur_mode, cur_bpw;unsigned cur_speed; +unsigned rx_ch; +unsigned tx_ch; +struct samsung_dma_ops *ops; };static struct s3c2410_dma_client s3c64xx_spi_dma_client = {@@ -227,6 +230,38 @@ static void flush_fifo(struct
s3c64xx_spi_driver_data*sdd)Quoted 31 lines
drivers/spi/spi_s3c64xx.c +28
-0writel (val, regs +S3C64XX_SPI_CH_CFG ); } +static void s3c64xx_spi_dma_rxcb (void *data) +{ +struct s3c64xx_spi_driver_data *sdd + = (struct s3c64xx_spi_driver_data *)data; +unsigned long flags; + +spin_lock_irqsave (&sdd->lock, flags); + + sdd->state &= ~RXBUSY ; +/* If the other done */ +if (!(sdd->state &TXBUSY )) +complete (&sdd->xfer_completion); + +spin_unlock_irqrestore (&sdd->lock, flags); +} + +static void s3c64xx_spi_dma_txcb (void *data) +{ +struct s3c64xx_spi_driver_data *sdd + = (struct s3c64xx_spi_driver_data *)data; +unsigned long flags; + +spin_lock_irqsave (&sdd->lock, flags); + + sdd->state &= ~TXBUSY ; +/* If the other done */ +if (!(sdd->state &RXBUSY )) +complete (&sdd->xfer_completion);
Quoted 8 lines
drivers/spi/spi_s3c64xx.c static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) · line 247
Quoted 3 lines
drivers/spi/spi_s3c64xx.c +3
-0+ +spin_unlock_irqrestore (&sdd->lock, flags); +}I don't see much diff in these two functions and you should be able to use a generic one which takes care of both TX and RX, does your callback
data know if the channel is for TX or RX? If not then a helper to do above should take care well and making code simpler
I'm very agree with you.
But, I think it isn't deeply related to this patch series. So, I wish to make and submit it after this patch series is finished.
Quoted 177 lines
drivers/spi/spi_s3c64xx.c static void enable_datapath(struct
Quoted 6 lines
drivers/spi/spi_s3c64xx.c +1
-0+static void enable_datapath (struct s3c64xx_spi_driver_data *sdd,struct spi_device *spi,struct spi_transfer *xfer,int dma_mode)@@ -234,6 +269,7 @@ static void enable_datapath(struct
s3c64xx_spi_driver_data*sdd,drivers/spi/spi_s3c64xx.c static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
Quoted 7 lines
drivers/spi/spi_s3c64xx.c +1
-0struct s3c64xx_spi_info *sci = sdd->cntrlr_info;void __iomem *regs = sdd->regs;u32 modecfg, chcfg; +struct samsung_dma_prep_info info; modecfg =readl (regs +S3C64XX_SPI_MODE_CFG ); modecfg &= ~(S3C64XX_SPI_MODE_TXDMA_ON |
S3C64XX_SPI_MODE_RXDMA_ON);drivers/spi/spi_s3c64xx.c static void enable_datapath(struct
Quoted 1 line
drivers/spi/spi_s3c64xx.c +0
-0@@ -259,10 +295,14 @@ static void enable_datapath(struct
s3c64xx_spi_driver_data*sdd,drivers/spi/spi_s3c64xx.c static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
Quoted 7 lines
drivers/spi/spi_s3c64xx.c +0
-4chcfg |=S3C64XX_SPI_CH_TXCH_ON ;if (dma_mode) { modecfg |=S3C64XX_SPI_MODE_TXDMA_ON ; -s3c2410_dma_config (sdd->tx_dmach, sdd->cur_bpw /8 ); -s3c2410_dma_enqueue (sdd->tx_dmach, (void *)sdd, - xfer->tx_dma, xfer->len); - s3c2410_dma_ctrl(sdd->tx_dmach,
S3C2410_DMAOP_START);drivers/spi/spi_s3c64xx.c static void enable_datapath(struct
Quoted 12 lines
drivers/spi/spi_s3c64xx.c +8
-0+ info.cap =DMA_SLAVE ; + info.direction =DMA_TO_DEVICE ; + info.buf = xfer->tx_dma; + info.len = xfer->len; + info.fp = s3c64xx_spi_dma_txcb; + info.fp_param = sdd; + sdd->ops->prepare (sdd->tx_ch, &info); + sdd->ops->trigger (sdd->tx_ch); }else {switch (sdd->cur_bpw) {case 32 :@@ -294,10 +334,14 @@ static void enable_datapath(struct
s3c64xx_spi_driver_data*sdd,drivers/spi/spi_s3c64xx.c static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
Quoted 7 lines
drivers/spi/spi_s3c64xx.c +0
-4writel (((xfer->len *8 / sdd->cur_bpw) &0xffff ) |S3C64XX_SPI_PACKET_CNT_EN , regs +S3C64XX_SPI_PACKET_CNT ); -s3c2410_dma_config (sdd->rx_dmach, sdd->cur_bpw /8 ); -s3c2410_dma_enqueue (sdd->rx_dmach, (void *)sdd, - xfer->rx_dma, xfer->len); - s3c2410_dma_ctrl(sdd->rx_dmach,
S3C2410_DMAOP_START);drivers/spi/spi_s3c64xx.c static void s3c64xx_spi_config(struct
Quoted 12 lines
drivers/spi/spi_s3c64xx.c +8
-0+ info.cap =DMA_SLAVE ; + info.direction =DMA_FROM_DEVICE ; + info.buf = xfer->rx_dma; + info.len = xfer->len; + info.fp = s3c64xx_spi_dma_rxcb; + info.fp_param = sdd; + sdd->ops->prepare (sdd->rx_ch, &info); + sdd->ops->trigger (sdd->rx_ch); } }@@ -483,46 +527,6 @@ static void s3c64xx_spi_config(struct
s3c64xx_spi_driver_data*sdd)drivers/spi/spi_s3c64xx.c static void s3c64xx_spi_config(struct · line 486
Quoted 4 lines
drivers/spi/spi_s3c64xx.c +0
-1} } -static void s3c64xx_spi_dma_rxcb(struct s3c2410_dma_chan *chan,void
*buf_id,Quoted 10 lines
drivers/spi/spi_s3c64xx.c +0
-10- int size, enum s3c2410_dma_buffresult res) -{ -struct s3c64xx_spi_driver_data *sdd = buf_id; -unsigned long flags; - -spin_lock_irqsave (&sdd->lock, flags); - -if (res ==S3C2410_RES_OK ) - sdd->state &= ~RXBUSY ; -else drivers/spi/spi_s3c64xx.c static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
Quoted 10 lines
drivers/spi/spi_s3c64xx.c +0
-10-dev_err (&sdd->pdev->dev,"DmaAbrtRx-%d\n" , size); - -/* If the other done */ -if (!(sdd->state &TXBUSY )) -complete (&sdd->xfer_completion); - -spin_unlock_irqrestore (&sdd->lock, flags); -} - -static void s3c64xx_spi_dma_txcb(struct s3c2410_dma_chan *chan,void
*buf_id,drivers/spi/spi_s3c64xx.c static void handle_msg(struct
Quoted 23 lines
drivers/spi/spi_s3c64xx.c +0
-19- int size, enum s3c2410_dma_buffresult res) -{ -struct s3c64xx_spi_driver_data *sdd = buf_id; -unsigned long flags; - -spin_lock_irqsave (&sdd->lock, flags); - -if (res ==S3C2410_RES_OK ) - sdd->state &= ~TXBUSY ; -else -dev_err (&sdd->pdev->dev,"DmaAbrtTx-%d \n" , size); - -/* If the other done */ -if (!(sdd->state &RXBUSY )) -complete (&sdd->xfer_completion); - -spin_unlock_irqrestore (&sdd->lock, flags); -} -#define XFER_DMAADDR_INVALID DMA_BIT_MASK(32) static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,@@ -697,12 +701,10 @@ static void handle_msg(struct
s3c64xx_spi_driver_data*sdd,drivers/spi/spi_s3c64xx.c static void s3c64xx_spi_work(struct work_struct
Quoted 53 lines
drivers/spi/spi_s3c64xx.c +15
-22if (use_dma) {if (xfer->tx_buf !=NULL && (sdd->state &TXBUSY )) -s3c2410_dma_ctrl (sdd->tx_dmach, -S3C2410_DMAOP_FLUSH ); + sdd->ops->stop (sdd->tx_ch);if (xfer->rx_buf !=NULL && (sdd->state &RXBUSY )) -s3c2410_dma_ctrl (sdd->rx_dmach, -S3C2410_DMAOP_FLUSH ); + sdd->ops->stop (sdd->rx_ch); } goto out;@@ -742,24 +744,19 @@ out:static int acquire_dma (struct s3c64xx_spi_driver_data *sdd) { -if (s3c2410_dma_request (sdd->rx_dmach, - &s3c64xx_spi_dma_client,NULL ) <0 ) { -dev_err (&sdd->pdev->dev,"cannot get RxDMA\n" ); -return 0 ; - } -s3c2410_dma_set_buffdone_fn (sdd->rx_dmach, s3c64xx_spi_dma_rxcb); -s3c2410_dma_devconfig (sdd->rx_dmach,S3C2410_DMASRC_HW , - sdd->sfr_start +S3C64XX_SPI_RX_DATA ); - -if (s3c2410_dma_request (sdd->tx_dmach, - &s3c64xx_spi_dma_client,NULL ) <0 ) { -dev_err (&sdd->pdev->dev,"cannot get TxDMA\n" ); -s3c2410_dma_free (sdd->rx_dmach, &s3c64xx_spi_dma_client); -return 0 ; - } -s3c2410_dma_set_buffdone_fn (sdd->tx_dmach, s3c64xx_spi_dma_txcb); -s3c2410_dma_devconfig (sdd->tx_dmach,S3C2410_DMASRC_MEM , - sdd->sfr_start +S3C64XX_SPI_TX_DATA ); + +struct samsung_dma_info info; + sdd->ops =samsung_dma_get_ops (); + + info.cap =DMA_SLAVE ; + info.client = &s3c64xx_spi_dma_client; + info.direction =DMA_FROM_DEVICE ; + info.fifo = sdd->sfr_start +S3C64XX_SPI_RX_DATA ; + info.width = sdd->cur_bpw /8 ; + sdd->rx_ch = sdd->ops->request (sdd->rx_dmach, &info); + info.direction =DMA_TO_DEVICE ; + info.fifo = sdd->sfr_start +S3C64XX_SPI_TX_DATA ; + sdd->tx_ch = sdd->ops->request (sdd->tx_dmach, &info);return 1 ; }@@ -800,8 +797,8 @@ static void s3c64xx_spi_work(struct work_struct*work)
drivers/spi/spi_s3c64xx.c static void s3c64xx_spi_work(struct work_struct *work) · line 804
Quoted 10 lines
drivers/spi/spi_s3c64xx.c +2
-2spin_unlock_irqrestore (&sdd->lock, flags);/* Free DMA channels */ -s3c2410_dma_free (sdd->tx_dmach, &s3c64xx_spi_dma_client); -s3c2410_dma_free (sdd->rx_dmach, &s3c64xx_spi_dma_client); + sdd->ops->release (sdd->rx_ch, &s3c64xx_spi_dma_client); + sdd->ops->release (sdd->tx_ch, &s3c64xx_spi_dma_client); } static int s3c64xx_spi_transfer(struct spi_device *spi,--
~Vinod Koul
Intel Corp.
PATCH v4 12/14 spi/s3c64xx: Add support DMA engine API
Quoted 77 lines · Boojin Kim
Vinod Koul Wrote:
Quoted 68 lines
Sent: Monday, July 25, 2011 8:17 PM
To: Boojin Kim
Cc: vinod.koul at intel.com; linux-arm-kernel at lists.infradead.org; linux- samsung-soc at vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely; Mark Brown; Dan Williams
Subject: Re: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine APIQuoted 10 lines · Boojin Kim
This patch adds to support DMA generic API to transfer raw SPI data. Basiclly the spi driver uses DMA generic API if architecture supports it. Otherwise, uses Samsung specific S3C-PL330 APIs.
Signed-off-by Boojin Kim <[email protected]>Cc Grant Likely <[email protected]>Signed-off-by Kukjin Kim <[email protected]>--- drivers/spi/spi_s3c64xx.c | 141 ++++++++++++++++++++++-----------------------
drivers/spi/spi_s3c64xx.c static void flush_fifo(struct
Quoted 17 lines
1 files changed, 69 insertions(+), 72 deletions(-)drivers/spi/spi_s3c64xx.c +3
-0@@ -172,6 +172,9 @@ struct s3c64xx_spi_driver_data {unsigned state;unsigned cur_mode, cur_bpw;unsigned cur_speed; +unsigned rx_ch; +unsigned tx_ch; +struct samsung_dma_ops *ops; };static struct s3c2410_dma_client s3c64xx_spi_dma_client = {@@ -227,6 +230,38 @@ static void flush_fifo(struct
s3c64xx_spi_driver_data*sdd)Quoted 31 lines
drivers/spi/spi_s3c64xx.c +28
-0writel (val, regs +S3C64XX_SPI_CH_CFG ); } +static void s3c64xx_spi_dma_rxcb (void *data) +{ +struct s3c64xx_spi_driver_data *sdd + = (struct s3c64xx_spi_driver_data *)data; +unsigned long flags; + +spin_lock_irqsave (&sdd->lock, flags); + + sdd->state &= ~RXBUSY ; +/* If the other done */ +if (!(sdd->state &TXBUSY )) +complete (&sdd->xfer_completion); + +spin_unlock_irqrestore (&sdd->lock, flags); +} + +static void s3c64xx_spi_dma_txcb (void *data) +{ +struct s3c64xx_spi_driver_data *sdd + = (struct s3c64xx_spi_driver_data *)data; +unsigned long flags; + +spin_lock_irqsave (&sdd->lock, flags); + + sdd->state &= ~TXBUSY ; +/* If the other done */ +if (!(sdd->state &RXBUSY )) +complete (&sdd->xfer_completion);Quoted 8 lines
drivers/spi/spi_s3c64xx.c static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) · line 247
Quoted 3 lines
drivers/spi/spi_s3c64xx.c +3
-0+ +spin_unlock_irqrestore (&sdd->lock, flags); +}I don't see much diff in these two functions and you should be able to use a generic one which takes care of both TX and RX, does your callback
data know if the channel is for TX or RX? If not then a helper to do above should take care well and making code simpler
Quoted 4 lines
I'm very agree with you.
But, I think it isn't deeply related to this patch series. So, I wish to make and submit it after this patch series is finished.
Since you are reworking this driver would make sense to do now, it doesn't sound to be a big change.
Signature · 2 lines
~Vinod Koul Intel Corp.
PATCH v4 12/14 spi/s3c64xx: Add support DMA engine API
Vinod Koul Wrote:
Quoted 90 lines
Sent: Tuesday, July 26, 2011 7:15 PM
To: Boojin Kim
Cc: vinod.koul at intel.com; 'Kukjin Kim'; 'Jassi Brar'; 'Grant Likely'; linux-samsung-soc at vger.kernel.org; 'Mark Brown'; 'Dan Williams'; linux-arm-kernel at lists.infradead.org
Subject: RE: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engine APIQuoted 4 lines · Boojin Kim
Vinod Koul Wrote:
Quoted 3 lines
Sent: Monday, July 25, 2011 8:17 PM
To: Boojin Kim
Cc: vinod.koul at intel.com; linux-arm-kernel at lists.infradead.org;linux-
Quoted 3 lines
Quoted 3 lines
samsung-soc at vger.kernel.org; Kukjin Kim; Jassi Brar; Grant Likely; Mark Brown; Dan Williams
Subject: Re: [PATCH V4 12/14] spi/s3c64xx: Add support DMA engineAPI
Quoted 7 lines
Quoted 7 lines · Boojin Kim
Quoted 5 lines
This patch adds to support DMA generic API to transfer raw SPI data. Basiclly the spi driver uses DMA generic API if architecture supports it. Otherwise, uses Samsung specific S3C-PL330 APIs.
Quoted 5 lines
Quoted 5 lines
Quoted 5 lines
Signed-off-by Boojin Kim <[email protected]>Cc Grant Likely <[email protected]>Signed-off-by Kukjin Kim <[email protected]>--- drivers/spi/spi_s3c64xx.c | 141 ++++++++++++++++++++++-------------
Quoted 4 lines
Quoted 4 lines
----------
Review
Quoted 3 lines
1 files changed, 69 insertions(+), 72 deletions(-)(quoted diff) +0
-0
b/drivers/spi/spi_s3c64xx.cQuoted 42 lines
Quoted 42 lines
drivers/spi/spi_s3c64xx.c static void flush_fifo(struct
Quoted 14 lines
index 8945e20..a4cf76a 100644
drivers/spi/spi_s3c64xx.c +3
-0@@ -172,6 +172,9 @@ struct s3c64xx_spi_driver_data {unsigned state;unsigned cur_mode, cur_bpw;unsigned cur_speed; +unsigned rx_ch; +unsigned tx_ch; +struct samsung_dma_ops *ops; };static struct s3c2410_dma_client s3c64xx_spi_dma_client = {@@ -227,6 +230,38 @@ static void flush_fifo(struct
s3c64xx_spi_driver_data*sdd)Quoted 27 lines
drivers/spi/spi_s3c64xx.c +24
-0writel (val, regs +S3C64XX_SPI_CH_CFG ); } +static void s3c64xx_spi_dma_rxcb (void *data) +{ +struct s3c64xx_spi_driver_data *sdd + = (struct s3c64xx_spi_driver_data *)data; +unsigned long flags; + +spin_lock_irqsave (&sdd->lock, flags); + + sdd->state &= ~RXBUSY ; +/* If the other done */ +if (!(sdd->state &TXBUSY )) +complete (&sdd->xfer_completion); + +spin_unlock_irqrestore (&sdd->lock, flags); +} + +static void s3c64xx_spi_dma_txcb (void *data) +{ +struct s3c64xx_spi_driver_data *sdd + = (struct s3c64xx_spi_driver_data *)data; +unsigned long flags; + +spin_lock_irqsave (&sdd->lock, flags); +Quoted 8 lines
Quoted 8 lines
drivers/spi/spi_s3c64xx.c static void flush_fifo(struct s3c64xx_spi_driver_data *sdd) · line 263
Quoted 7 lines
drivers/spi/spi_s3c64xx.c +7
-0+ sdd->state &= ~TXBUSY ; +/* If the other done */ +if (!(sdd->state &RXBUSY )) +complete (&sdd->xfer_completion); + +spin_unlock_irqrestore (&sdd->lock, flags); +}I don't see much diff in these two functions and you should be
able to
Quoted 3 lines
Quoted 3 lines
use a generic one which takes care of both TX and RX, does your callback
data know if the channel is for TX or RX? If not then a helper todo
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
above should take care well and making code simpler
I'm very agree with you.
But, I think it isn't deeply related to this patch series. So, Iwish to make
Quoted 2 lines
and submit it after this patch series is finished.
Since you are reworking this driver would make sense to do now, it doesn't sound to be a big change.
Ok. I will follow your request.
I will make new patch for it and send it with V5 patchset.
Quoted 4 lines
--
~Vinod Koul
Intel Corp.
PATCH v4 13/14 ASoC: Samsung: Update DMA interface
In reply to Boojin KimThis patch adds to support the DMA PL330 driver that uses DMA generic API. Samsung sound driver uses DMA generic API if architecture supports it. Otherwise, use samsung specific S3C-PL330 API driver to transfer PCM data.
--- arch/arm/mach-s3c2410/include/mach/dma.h | 10 +- arch/arm/mach-s3c64xx/include/mach/dma.h | 2 +- arch/arm/plat-samsung/include/plat/dma-pl330.h | 2 +- sound/soc/samsung/ac97.c | 10 ++- sound/soc/samsung/dma.c | 144 ++++++++++-------------- sound/soc/samsung/dma.h | 4 +- 6 files changed, 78 insertions(+), 94 deletions(-)
arch/arm/mach-s3c2410/include/mach/dma.h +5 -5
@@ -50,6 +50,11 @@ enum dma_ch { DMACH_MAX, /* the end entry */ }; +static inline bool samsung_dma_has_circular (void ) +{ +return false; +} +static inline bool samsung_dma_is_dmadev (void ) {return false;
@@ -202,9 +207,4 @@ struct s3c2410_dma_chan {typedef unsigned long dma_device_t ; -static inline bool s3c_dma_has_circular (void ) -{ -return false; -} -#endif /* __ASM_ARCH_DMA_H */
arch/arm/mach-s3c64xx/include/mach/dma.h +1 -1
@@ -58,7 +58,7 @@ enum dma_ch { DMACH_MAX /* the end */ }; -static __inline__bool s3c_dma_has_circular (void ) +static inline bool samsung_dma_has_circular (void ) {return true; }
arch/arm/plat-samsung/include/plat/dma-pl330.h +1 -1
@@ -97,7 +97,7 @@ struct s3c2410_dma_client {char *name; }; -static inline bool s3c_dma_has_circular (void ) +static inline bool samsung_dma_has_circular (void ) {return true; }
sound/soc/samsung/ac97.c +8 -2
@@ -271,7 +271,10 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,writel (ac_glbctrl, s3c_ac97.regs +S3C_AC97_GLBCTRL ); -s3c2410_dma_ctrl (dma_data->channel,S3C2410_DMAOP_STARTED ); +if (!dma_data->ops) + dma_data->ops =samsung_dma_get_ops (); + + dma_data->ops->started (dma_data->channel);return 0 ; }
@@ -317,7 +320,10 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,writel (ac_glbctrl, s3c_ac97.regs +S3C_AC97_GLBCTRL ); -s3c2410_dma_ctrl (dma_data->channel,S3C2410_DMAOP_STARTED ); +if (!dma_data->ops) + dma_data->ops =samsung_dma_get_ops (); + + dma_data->ops->started (dma_data->channel);return 0 ; }
sound/soc/samsung/dma.c +60 -84
233 lines not on this page · raw message
sound/soc/samsung/dma.h +3 -1
@@ -6,7 +6,7 @@* Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * -* ALSA PCM interface for the Samsung S3C24xx CPU +* ALSA PCM interface for the Samsung SoC */ #ifndef _S3C_AUDIO_H
@@ -17,6 +17,8 @@ struct s3c_dma_params {int channel;/* Channel ID */ dma_addr_t dma_addr;int dma_size;/* Size of the DMA transfer */ +unsigned ch; + struct samsung_dma_ops *ops; };#endif
Signature · 1 line
1.7.1
PATCH v4 14/14 ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
In reply to Boojin KimThis patch removes the samsung specific enum type 's3c2410_dmasrc' and uses 'dma_data_direction' instead.
--- arch/arm/mach-s3c2410/include/mach/dma.h | 2 +- arch/arm/mach-s3c2412/dma.c | 4 ++-- arch/arm/mach-s3c64xx/dma.c | 10 +++++----- arch/arm/mach-s3c64xx/include/mach/dma.h | 2 +- arch/arm/plat-s3c24xx/dma.c | 10 +++++----- arch/arm/plat-samsung/include/plat/dma-s3c24xx.h | 2 +- arch/arm/plat-samsung/include/plat/dma.h | 9 +++------ arch/arm/plat-samsung/s3c-dma-ops.c | 5 +---- drivers/mmc/host/s3cmci.c | 6 +++--- 9 files changed, 22 insertions(+), 28 deletions(-)
arch/arm/mach-s3c2410/include/mach/dma.h +1 -1
@@ -174,7 +174,7 @@ struct s3c2410_dma_chan {struct s3c2410_dma_client *client;/* channel configuration */ -enum s3c2410_dmasrc source; +enum dma_data_direction source;enum dma_ch req_ch;unsigned long dev_addr;unsigned long load_timeout;
arch/arm/mach-s3c2412/dma.c +2 -2
@@ -148,11 +148,11 @@ static struct s3c24xx_dma_map __initdata s3c2412_dma_mappings[] = {static void s3c2412_dma_direction (struct s3c2410_dma_chan *chan,struct s3c24xx_dma_map *map, -enum s3c2410_dmasrc dir) +enum dma_data_direction dir) {unsigned long chsel; -if (dir ==S3C2410_DMASRC_HW ) +if (dir ==DMA_FROM_DEVICE ) chsel = map->channels_rx[0 ];else chsel = map->channels[0 ];
arch/arm/mach-s3c64xx/dma.c +5 -5
@@ -147,14 +147,14 @@ static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,u32 control0, control1;switch (chan->source) { -case S3C2410_DMASRC_HW : +case DMA_FROM_DEVICE : src = chan->dev_addr; dst = data; control0 =PL080_CONTROL_SRC_AHB2 ; control0 |=PL080_CONTROL_DST_INCR ;break ; -case S3C2410_DMASRC_MEM : +case DMA_TO_DEVICE : src = data; dst = chan->dev_addr; control0 =PL080_CONTROL_DST_AHB2 ;
@@ -416,7 +416,7 @@ EXPORT_SYMBOL(s3c2410_dma_enqueue);int s3c2410_dma_devconfig (unsigned int channel, -enum s3c2410_dmasrc source, +enum dma_data_direction source,unsigned long devaddr) {struct s3c2410_dma_chan *chan =s3c_dma_lookup_channel (channel);
@@ -437,11 +437,11 @@ int s3c2410_dma_devconfig(unsigned int channel,pr_debug ("%s: peripheral %d\n" , __func__, peripheral);switch (source) { -case S3C2410_DMASRC_HW : +case DMA_FROM_DEVICE : config =2 <<PL080_CONFIG_FLOW_CONTROL_SHIFT ; config |= peripheral <<PL080_CONFIG_SRC_SEL_SHIFT ;break ; -case S3C2410_DMASRC_MEM : +case DMA_TO_DEVICE : config =1 <<PL080_CONFIG_FLOW_CONTROL_SHIFT ; config |= peripheral <<PL080_CONFIG_DST_SEL_SHIFT ;break ;
arch/arm/mach-s3c64xx/include/mach/dma.h +1 -1
@@ -99,7 +99,7 @@ struct s3c2410_dma_chan {unsigned char peripheral;unsigned int flags; -enum s3c2410_dmasrc source; +enum dma_data_direction source;dma_addr_t dev_addr;
arch/arm/plat-s3c24xx/dma.c +5 -5
@@ -1094,14 +1094,14 @@ EXPORT_SYMBOL(s3c2410_dma_config);* * configure the dma source/destination hardware type and address * -* source: S3C2410_DMASRC_HW: source is hardware -* S3C2410_DMASRC_MEM: source is memory +* source: DMA_FROM_DEVICE: source is hardware +* DMA_TO_DEVICE: source is memory * * devaddr: physical address of the source */ int s3c2410_dma_devconfig (unsigned int channel, -enum s3c2410_dmasrc source, +enum dma_data_direction source,unsigned long devaddr) {struct s3c2410_dma_chan *chan =s3c_dma_lookup_channel (channel);
@@ -1131,7 +1131,7 @@ int s3c2410_dma_devconfig(unsigned int channel, hwcfg |=S3C2410_DISRCC_INC ;switch (source) { -case S3C2410_DMASRC_HW : +case DMA_FROME_DEVICE :/* source is hardware */ pr_debug ("%s: hw source, devaddr=%08lx, hwcfg=%d\n" , __func__, devaddr, hwcfg);
@@ -1142,7 +1142,7 @@ int s3c2410_dma_devconfig(unsigned int channel, chan->addr_reg =dma_regaddr (chan,S3C2410_DMA_DIDST );break ; -case S3C2410_DMASRC_MEM : +case DMA_TO_DEVICE :/* source is memory */ pr_debug ("%s: mem source, devaddr=%08lx, hwcfg=%d\n" , __func__, devaddr, hwcfg);
arch/arm/plat-samsung/include/plat/dma-s3c24xx.h +1 -1
@@ -47,7 +47,7 @@ struct s3c24xx_dma_selection {void (*direction)(struct s3c2410_dma_chan *chan,struct s3c24xx_dma_map *map, -enum s3c2410_dmasrc dir); +enum dma_data_direction dir); };extern int s3c24xx_dma_init_map (struct s3c24xx_dma_selection *sel);
arch/arm/plat-samsung/include/plat/dma.h +3 -6
@@ -10,17 +10,14 @@* published by the Free Software Foundation. */ +#include <linux/dma-mapping.h> +enum s3c2410_dma_buffresult {S3C2410_RES_OK ,S3C2410_RES_ERR ,S3C2410_RES_ABORT }; -enum s3c2410_dmasrc { -S3C2410_DMASRC_HW ,/* source is memory */ -S3C2410_DMASRC_MEM /* source is hardware */ -}; -/* enum s3c2410_chan_op * * operation codes passed to the DMA code by the user, and also used
@@ -111,7 +108,7 @@ extern int s3c2410_dma_config(unsigned int channel, int xferunit);*/ extern int s3c2410_dma_devconfig (unsigned int channel, -enum s3c2410_dmasrc source,unsigned long devaddr); +enum dma_data_direction source,unsigned long devaddr);/* s3c2410_dma_getposition *
arch/arm/plat-samsung/s3c-dma-ops.c +1 -4
@@ -48,10 +48,7 @@ static unsigned s3c_dma_request(enum dma_ch dma_ch, data->ch = dma_ch;list_add_tail (&data->node, &dma_list); -if (info->direction ==DMA_FROM_DEVICE ) -s3c2410_dma_devconfig (dma_ch,S3C2410_DMASRC_HW , info->fifo); -else -s3c2410_dma_devconfig (dma_ch,S3C2410_DMASRC_MEM , info->fifo); +s3c2410_dma_devconfig (dma_ch, info->direction, info->fifo);if (info->cap ==DMA_CYCLIC )s3c2410_dma_setflags (dma_ch,S3C2410_DMAF_CIRCULAR );
drivers/mmc/host/s3cmci.c +3 -3
@@ -913,9 +913,9 @@ request_done: }static void s3cmci_dma_setup (struct s3cmci_host *host, -enum s3c2410_dmasrc source) +enum dma_data_direction source) { -static enum s3c2410_dmasrc last_source =-1 ; +static enum dma_data_direction last_source =-1 ;static int setup_ok;if (last_source == source)
@@ -1087,7 +1087,7 @@ static int s3cmci_prepare_dma(struct s3cmci_host *host, struct mmc_data *data)BUG_ON ((data->flags &BOTH_DIR ) ==BOTH_DIR ); -s3cmci_dma_setup (host, rw ?S3C2410_DMASRC_MEM :S3C2410_DMASRC_HW ); +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,
Signature · 1 line
1.7.1
PATCH v4 14/14 ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
Quoted 5 lines · Boojin Kim
This patch removes the samsung specific enum type '
s3c2410_dmasrc' and uses 'dma_data_direction' instead.Signed-off-by Boojin Kim <[email protected]>Signed-off-by Kukjin Kim <[email protected]>
If this patch was first in the patchset, probably it could have been already merged.
PATCH v4 14/14 ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
Quoted 11 lines · Jassi Brar
Quoted 5 lines · Boojin Kim
This patch removes the samsung specific enum type '
s3c2410_dmasrc' and uses 'dma_data_direction' instead.Signed-off-by Boojin Kim <[email protected]>Signed-off-by Kukjin Kim <[email protected]>Acked-by Jassi Brar <[email protected]>If this patch was first in the patchset, probably it could have been already merged.
Indeed. If you move this to the front when you post the next version then it can be merged right away.
PATCH v4 14/14 ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
Grant Likely Wrote:
Quoted 17 lines
Likely
Sent: Tuesday, July 26, 2011 6:16 AM
To: Jassi Brar
Cc: Boojin Kim; linux-arm-kernel at lists.infradead.org; linux-samsung- soc at vger.kernel.org; Vinod Koul; Dan Williams; Kukjin Kim; Mark Brown
Subject: Re: [PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma directionQuoted 1 line · Jassi Brar
On Mon, Jul 25, 2011 at 6:58 AM, Boojin Kim <[email protected]>
Quoted 6 lines · wrote:
Quoted 5 lines
This patch removes the samsung specific enum type '
s3c2410_dmasrc' and uses 'dma_data_direction' instead.Signed-off-by Boojin Kim <[email protected]>Signed-off-by Kukjin Kim <[email protected]>
Quoted 7 lines
Quoted 4 lines
Acked-by Jassi Brar <[email protected]>If this patch was first in the patchset, probably it could have been already merged.
Indeed. If you move this to the front when you post the next version then it can be merged right away.
I tried to move it ahead. But It made some conflicts. So, I pushed as it is on V5 release.
Sorry.. I would have noticed it before I release V5.
Quoted 2 lines
Acked-by Grant Likely <[email protected]>
v4 cover To use DMA generic APIs for Samsung DMA
In reply to Boojin KimQuoted 13 lines · Boojin Kim
This patchset adds support DMA generic APIs for Samsung DMA and is re-sent by the request of DMA maintainer, Vinod Koul.
V4 has the changes about 3 patches from V3.
Changes from V3:
- Divided '[03/13 patch] DMA: PL330: Add DMA capabilites' on V3 patchset into two patches.
- One is '03/14 patch' for supportingDMA_SLAVE_CONFIGcommand.
- Another is '04/14 patch' for supportingDMA_CYCLICcapability.
- Code clean-up
- Remove unnecessary vairable referance on '01/14 patch'.
- Remove redunancy code on '06/14 patch'
Quoted 15 lines
[PATCH V4 01/14] DMA: PL330: Add support runtime PM for PL330 DMAC [PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver
[PATCH V4 03/14] DMA: PL330: SupportDMA_SLAVE_CONFIGcommand
[PATCH V4 04/14] DMA: PL330: AddDMA_CYCLICcapability
[PATCH V4 05/14] ARM: SAMSUNG: Update to use PL330-DMA driver
[PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
[PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330 driver
[PATCH V4 08/14] ARM: S5PV210: Use generic DMA PL330 driver
[PATCH V4 09/14] ARM: S5PC100: Use generic DMA PL330 driver
[PATCH V4 10/14] ARM: S5P64X0: Use generic DMA PL330 driver
[PATCH V4 11/14] ARM: SAMSUNG: Remove S3C-PL330-DMA driver
[PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
[PATCH V4 13/14] ASoC: Samsung: Update DMA interface
[PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
Thanks for resending I will review them now, You should use git --cover-letter to generate this
Signature · 2 lines
~Vinod Koul Intel Corp.
v4 cover To use DMA generic APIs for Samsung DMA
Quoted 29 lines · Vinod Koul
Quoted 13 lines · Boojin Kim
This patchset adds support DMA generic APIs for Samsung DMA and is re-sent by the request of DMA maintainer, Vinod Koul.
V4 has the changes about 3 patches from V3.
Changes from V3:
- Divided '[03/13 patch] DMA: PL330: Add DMA capabilites' on V3 patchset into two patches.
- One is '03/14 patch' for supportingDMA_SLAVE_CONFIGcommand.
- Another is '04/14 patch' for supportingDMA_CYCLICcapability.
- Code clean-up
- Remove unnecessary vairable referance on '01/14 patch'.
- Remove redunancy code on '06/14 patch'Quoted 15 lines
[PATCH V4 01/14] DMA: PL330: Add support runtime PM for PL330 DMAC [PATCH V4 02/14] DMA: PL330: Update PL330 DMA API driver
[PATCH V4 03/14] DMA: PL330: SupportDMA_SLAVE_CONFIGcommand
[PATCH V4 04/14] DMA: PL330: AddDMA_CYCLICcapability
[PATCH V4 05/14] ARM: SAMSUNG: Update to use PL330-DMA driver
[PATCH V4 06/14] ARM: SAMSUNG: Add common DMA operations
[PATCH V4 07/14] ARM: EXYNOS4: Use generic DMA PL330 driver
[PATCH V4 08/14] ARM: S5PV210: Use generic DMA PL330 driver
[PATCH V4 09/14] ARM: S5PC100: Use generic DMA PL330 driver
[PATCH V4 10/14] ARM: S5P64X0: Use generic DMA PL330 driver
[PATCH V4 11/14] ARM: SAMSUNG: Remove S3C-PL330-DMA driver
[PATCH V4 12/14] spi/s3c64xx: Add support DMA engine API
[PATCH V4 13/14] ASoC: Samsung: Update DMA interface
[PATCH V4 14/14] ARM: SAMSUNG: Remove Samsung specific enum type for dma direction
Quoted 3 lines
Thanks for resending I will review them now, You should use git --cover-letter to generate this
Also I noticed the whole patch set doesn't have any acks from previous posting. If a patch has got ack from someone and it is not changed at all in next posting then you can carry that ack.
Makes things easier for me to track while applying
Signature · 2 lines
~Vinod Koul Intel Corp.