* [11/46] dmaengine: tegra20-apb-dma: use helper dmaenginem_async_device_register
From: Huang Shijie @ 2018-08-03 7:19 UTC (permalink / raw)
To: vkoul
Cc: dmaengine, linux-kernel, dave.jiang, radhey.shyam.pandey,
appana.durga.rao, jmkrzyszt, gomonovych, peter.ujfalusi, keescook,
horms+renesas, geert+renesas, shawnguo, baoyou.xie, michal.simek,
baohua, ludovic.desroches, linus.walleij, david.brown,
Huang Shijie
Use dmaenginem_async_device_register to simplify the code:
remove dma_async_device_unregister
remove the label err_unregister_dma_dev
Signed-off-by: Huang Shijie <sjhuang@iluvatar.ai>
---
drivers/dma/tegra20-apb-dma.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
index 9a558e30c461..9f6f51abbeef 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -1444,7 +1444,7 @@ static int tegra_dma_probe(struct platform_device *pdev)
tdma->dma_dev.device_tx_status = tegra_dma_tx_status;
tdma->dma_dev.device_issue_pending = tegra_dma_issue_pending;
- ret = dma_async_device_register(&tdma->dma_dev);
+ ret = dmaenginem_async_device_register(&tdma->dma_dev);
if (ret < 0) {
dev_err(&pdev->dev,
"Tegra20 APB DMA driver registration failed %d\n", ret);
@@ -1456,15 +1456,13 @@ static int tegra_dma_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(&pdev->dev,
"Tegra20 APB DMA OF registration failed %d\n", ret);
- goto err_unregister_dma_dev;
+ goto err_irq;
}
dev_info(&pdev->dev, "Tegra20 APB DMA driver register %d channels\n",
cdata->nr_channels);
return 0;
-err_unregister_dma_dev:
- dma_async_device_unregister(&tdma->dma_dev);
err_irq:
while (--i >= 0) {
struct tegra_dma_channel *tdc = &tdma->channels[i];
@@ -1485,8 +1483,6 @@ static int tegra_dma_remove(struct platform_device *pdev)
int i;
struct tegra_dma_channel *tdc;
- dma_async_device_unregister(&tdma->dma_dev);
-
for (i = 0; i < tdma->chip_data->nr_channels; ++i) {
tdc = &tdma->channels[i];
free_irq(tdc->irq, tdc);
^ permalink raw reply related
* [10/46] dmaengine: tegra210-adma: use helper dmaenginem_async_device_register
From: Huang Shijie @ 2018-08-03 7:19 UTC (permalink / raw)
To: vkoul
Cc: dmaengine, linux-kernel, dave.jiang, radhey.shyam.pandey,
appana.durga.rao, jmkrzyszt, gomonovych, peter.ujfalusi, keescook,
horms+renesas, geert+renesas, shawnguo, baoyou.xie, michal.simek,
baohua, ludovic.desroches, linus.walleij, david.brown,
Huang Shijie
Use dmaenginem_async_device_register to simplify the code:
remove dma_async_device_unregister
remove the label dma_remove
Signed-off-by: Huang Shijie <sjhuang@iluvatar.ai>
---
drivers/dma/tegra210-adma.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c
index b26256f23d67..bd99f12a00e3 100644
--- a/drivers/dma/tegra210-adma.c
+++ b/drivers/dma/tegra210-adma.c
@@ -746,7 +746,7 @@ static int tegra_adma_probe(struct platform_device *pdev)
tdma->dma_dev.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
tdma->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
- ret = dma_async_device_register(&tdma->dma_dev);
+ ret = dmaenginem_async_device_register(&tdma->dma_dev);
if (ret < 0) {
dev_err(&pdev->dev, "ADMA registration failed: %d\n", ret);
goto irq_dispose;
@@ -756,7 +756,7 @@ static int tegra_adma_probe(struct platform_device *pdev)
tegra_dma_of_xlate, tdma);
if (ret < 0) {
dev_err(&pdev->dev, "ADMA OF registration failed %d\n", ret);
- goto dma_remove;
+ goto irq_dispose;
}
pm_runtime_put(&pdev->dev);
@@ -766,8 +766,6 @@ static int tegra_adma_probe(struct platform_device *pdev)
return 0;
-dma_remove:
- dma_async_device_unregister(&tdma->dma_dev);
irq_dispose:
while (--i >= 0)
irq_dispose_mapping(tdma->channels[i].irq);
@@ -786,8 +784,6 @@ static int tegra_adma_remove(struct platform_device *pdev)
struct tegra_adma *tdma = platform_get_drvdata(pdev);
int i;
- dma_async_device_unregister(&tdma->dma_dev);
-
for (i = 0; i < tdma->nr_channels; ++i)
irq_dispose_mapping(tdma->channels[i].irq);
^ permalink raw reply related
* [09/46] dmaengine: cppi41: use dmaenginem_async_device_register to simplify the code
From: Huang Shijie @ 2018-08-03 7:19 UTC (permalink / raw)
To: vkoul
Cc: dmaengine, linux-kernel, dave.jiang, radhey.shyam.pandey,
appana.durga.rao, jmkrzyszt, gomonovych, peter.ujfalusi, keescook,
horms+renesas, geert+renesas, shawnguo, baoyou.xie, michal.simek,
baohua, ludovic.desroches, linus.walleij, david.brown,
Huang Shijie
Use dmaenginem_async_device_register to simplify the code:
remove dma_async_device_unregister
Signed-off-by: Huang Shijie <sjhuang@iluvatar.ai>
---
drivers/dma/ti/cppi41.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/dma/ti/cppi41.c b/drivers/dma/ti/cppi41.c
index 1497da367710..d2998a19ed2e 100644
--- a/drivers/dma/ti/cppi41.c
+++ b/drivers/dma/ti/cppi41.c
@@ -1096,21 +1096,19 @@ static int cppi41_dma_probe(struct platform_device *pdev)
goto err_chans;
cdd->irq = irq;
- ret = dma_async_device_register(&cdd->ddev);
+ ret = dmaenginem_async_device_register(&cdd->ddev);
if (ret)
goto err_chans;
ret = of_dma_controller_register(dev->of_node,
cppi41_dma_xlate, &cpp41_dma_info);
if (ret)
- goto err_of;
+ goto err_chans;
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return 0;
-err_of:
- dma_async_device_unregister(&cdd->ddev);
err_chans:
deinit_cppi41(dev, cdd);
err_init_cppi:
@@ -1132,7 +1130,6 @@ static int cppi41_dma_remove(struct platform_device *pdev)
dev_err(&pdev->dev, "%s could not pm_runtime_get: %i\n",
__func__, error);
of_dma_controller_free(pdev->dev.of_node);
- dma_async_device_unregister(&cdd->ddev);
devm_free_irq(&pdev->dev, cdd->irq, cdd);
deinit_cppi41(&pdev->dev, cdd);
^ permalink raw reply related
* [08/46] dmaengine: edma: use dmaenginem_async_device_register to simplify the code
From: Huang Shijie @ 2018-08-03 7:19 UTC (permalink / raw)
To: vkoul
Cc: dmaengine, linux-kernel, dave.jiang, radhey.shyam.pandey,
appana.durga.rao, jmkrzyszt, gomonovych, peter.ujfalusi, keescook,
horms+renesas, geert+renesas, shawnguo, baoyou.xie, michal.simek,
baohua, ludovic.desroches, linus.walleij, david.brown,
Huang Shijie
Use dmaenginem_async_device_register to simplify the code:
remove dma_async_device_unregister
Signed-off-by: Huang Shijie <sjhuang@iluvatar.ai>
---
drivers/dma/ti/edma.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/drivers/dma/ti/edma.c b/drivers/dma/ti/edma.c
index ceabdea40ae0..28ba1e722c47 100644
--- a/drivers/dma/ti/edma.c
+++ b/drivers/dma/ti/edma.c
@@ -2388,18 +2388,17 @@ static int edma_probe(struct platform_device *pdev)
ecc->dma_slave.filter.mapcnt = info->slavecnt;
ecc->dma_slave.filter.fn = edma_filter_fn;
- ret = dma_async_device_register(&ecc->dma_slave);
+ ret = dmaenginem_async_device_register(&ecc->dma_slave);
if (ret) {
dev_err(dev, "slave ddev registration failed (%d)\n", ret);
goto err_reg1;
}
if (ecc->dma_memcpy) {
- ret = dma_async_device_register(ecc->dma_memcpy);
+ ret = dmaenginem_async_device_register(ecc->dma_memcpy);
if (ret) {
dev_err(dev, "memcpy ddev registration failed (%d)\n",
ret);
- dma_async_device_unregister(&ecc->dma_slave);
goto err_reg1;
}
}
@@ -2439,9 +2438,6 @@ static int edma_remove(struct platform_device *pdev)
if (dev->of_node)
of_dma_controller_free(dev->of_node);
- dma_async_device_unregister(&ecc->dma_slave);
- if (ecc->dma_memcpy)
- dma_async_device_unregister(ecc->dma_memcpy);
edma_free_slot(ecc, ecc->dummy_slot);
return 0;
^ permalink raw reply related
* [07/46] dmaengine: omap-dma: use dmaenginem_async_device_register to simplify the code
From: Huang Shijie @ 2018-08-03 7:19 UTC (permalink / raw)
To: vkoul
Cc: dmaengine, linux-kernel, dave.jiang, radhey.shyam.pandey,
appana.durga.rao, jmkrzyszt, gomonovych, peter.ujfalusi, keescook,
horms+renesas, geert+renesas, shawnguo, baoyou.xie, michal.simek,
baohua, ludovic.desroches, linus.walleij, david.brown,
Huang Shijie
Use dmaenginem_async_device_register to simplify the code:
remove dma_async_device_unregister
Signed-off-by: Huang Shijie <sjhuang@iluvatar.ai>
---
drivers/dma/ti/omap-dma.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/dma/ti/omap-dma.c b/drivers/dma/ti/omap-dma.c
index a4a931ddf6f6..085748c6eb67 100644
--- a/drivers/dma/ti/omap-dma.c
+++ b/drivers/dma/ti/omap-dma.c
@@ -1566,7 +1566,7 @@ static int omap_dma_probe(struct platform_device *pdev)
}
}
- rc = dma_async_device_register(&od->ddev);
+ rc = dmaenginem_async_device_register(&od->ddev);
if (rc) {
pr_warn("OMAP-DMA: failed to register slave DMA engine device: %d\n",
rc);
@@ -1584,7 +1584,6 @@ static int omap_dma_probe(struct platform_device *pdev)
of_dma_simple_xlate, &omap_dma_info);
if (rc) {
pr_warn("OMAP-DMA: failed to register DMA controller\n");
- dma_async_device_unregister(&od->ddev);
omap_dma_free(od);
}
}
@@ -1606,8 +1605,6 @@ static int omap_dma_remove(struct platform_device *pdev)
irq = platform_get_irq(pdev, 1);
devm_free_irq(&pdev->dev, irq, od);
- dma_async_device_unregister(&od->ddev);
-
if (!od->legacy) {
/* Disable all interrupts */
omap_dma_glbl_write(od, IRQENABLE_L0, 0);
^ permalink raw reply related
* [06/46] dmaengine: timb_dma: use dmaenginem_async_device_register to simplify the code
From: Huang Shijie @ 2018-08-03 7:19 UTC (permalink / raw)
To: vkoul
Cc: dmaengine, linux-kernel, dave.jiang, radhey.shyam.pandey,
appana.durga.rao, jmkrzyszt, gomonovych, peter.ujfalusi, keescook,
horms+renesas, geert+renesas, shawnguo, baoyou.xie, michal.simek,
baohua, ludovic.desroches, linus.walleij, david.brown,
Huang Shijie
Use dmaenginem_async_device_register to simplify the code:
remove dma_async_device_unregister
Signed-off-by: Huang Shijie <sjhuang@iluvatar.ai>
---
drivers/dma/timb_dma.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c
index 395c698edb4d..39e1ba2347db 100644
--- a/drivers/dma/timb_dma.c
+++ b/drivers/dma/timb_dma.c
@@ -723,7 +723,7 @@ static int td_probe(struct platform_device *pdev)
list_add_tail(&td_chan->chan.device_node, &td->dma.channels);
}
- err = dma_async_device_register(&td->dma);
+ err = dmaenginem_async_device_register(&td->dma);
if (err) {
dev_err(&pdev->dev, "Failed to register async device\n");
goto err_free_irq;
@@ -754,7 +754,6 @@ static int td_remove(struct platform_device *pdev)
struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
int irq = platform_get_irq(pdev, 0);
- dma_async_device_unregister(&td->dma);
free_irq(irq, td);
tasklet_kill(&td->tasklet);
iounmap(td->membase);
^ permalink raw reply related
* [05/46] dmaengine: txx9dmac: use dmaenginem_async_device_register to simplify the code
From: Huang Shijie @ 2018-08-03 7:19 UTC (permalink / raw)
To: vkoul
Cc: dmaengine, linux-kernel, dave.jiang, radhey.shyam.pandey,
appana.durga.rao, jmkrzyszt, gomonovych, peter.ujfalusi, keescook,
horms+renesas, geert+renesas, shawnguo, baoyou.xie, michal.simek,
baohua, ludovic.desroches, linus.walleij, david.brown,
Huang Shijie
Use dmaenginem_async_device_register to simplify the code:
remove dma_async_device_unregister
Signed-off-by: Huang Shijie <sjhuang@iluvatar.ai>
---
drivers/dma/txx9dmac.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c
index eb45af71d3a3..1e97bee485d7 100644
--- a/drivers/dma/txx9dmac.c
+++ b/drivers/dma/txx9dmac.c
@@ -1147,7 +1147,7 @@ static int __init txx9dmac_chan_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dc);
- err = dma_async_device_register(&dc->dma);
+ err = dmaenginem_async_device_register(&dc->dma);
if (err)
return err;
dev_dbg(&pdev->dev, "TXx9 DMA Channel (dma%d%s%s)\n",
@@ -1162,8 +1162,6 @@ static int txx9dmac_chan_remove(struct platform_device *pdev)
{
struct txx9dmac_chan *dc = platform_get_drvdata(pdev);
-
- dma_async_device_unregister(&dc->dma);
if (dc->irq >= 0) {
devm_free_irq(&pdev->dev, dc->irq, dc);
tasklet_kill(&dc->tasklet);
^ permalink raw reply related
* [04/46] dmaengine: xgene-dma: use dmaenginem_async_device_register to simplify the code
From: Huang Shijie @ 2018-08-03 7:19 UTC (permalink / raw)
To: vkoul
Cc: dmaengine, linux-kernel, dave.jiang, radhey.shyam.pandey,
appana.durga.rao, jmkrzyszt, gomonovych, peter.ujfalusi, keescook,
horms+renesas, geert+renesas, shawnguo, baoyou.xie, michal.simek,
baohua, ludovic.desroches, linus.walleij, david.brown,
Huang Shijie
Use dmaenginem_async_device_register to simplify the code:
remove xgene_dma_async_register
remove dma_async_device_unregister
Signed-off-by: Huang Shijie <sjhuang@iluvatar.ai>
---
drivers/dma/xgene-dma.c | 16 ++--------------
1 file changed, 2 insertions(+), 14 deletions(-)
diff --git a/drivers/dma/xgene-dma.c b/drivers/dma/xgene-dma.c
index 1d5988849aa6..192322bbdc29 100644
--- a/drivers/dma/xgene-dma.c
+++ b/drivers/dma/xgene-dma.c
@@ -1564,7 +1564,7 @@ static int xgene_dma_async_register(struct xgene_dma *pdma, int id)
list_add_tail(&chan->dma_chan.device_node, &dma_dev->channels);
/* Register with Linux async DMA framework*/
- ret = dma_async_device_register(dma_dev);
+ ret = dmaenginem_async_device_register(dma_dev);
if (ret) {
chan_err(chan, "Failed to register async device %d", ret);
tasklet_kill(&chan->tasklet);
@@ -1588,10 +1588,8 @@ static int xgene_dma_init_async(struct xgene_dma *pdma)
for (i = 0; i < XGENE_DMA_MAX_CHANNEL ; i++) {
ret = xgene_dma_async_register(pdma, i);
if (ret) {
- for (j = 0; j < i; j++) {
- dma_async_device_unregister(&pdma->dma_dev[j]);
+ for (j = 0; j < i; j++)
tasklet_kill(&pdma->chan[j].tasklet);
- }
return ret;
}
@@ -1600,14 +1598,6 @@ static int xgene_dma_init_async(struct xgene_dma *pdma)
return ret;
}
-static void xgene_dma_async_unregister(struct xgene_dma *pdma)
-{
- int i;
-
- for (i = 0; i < XGENE_DMA_MAX_CHANNEL; i++)
- dma_async_device_unregister(&pdma->dma_dev[i]);
-}
-
static void xgene_dma_init_channels(struct xgene_dma *pdma)
{
struct xgene_dma_chan *chan;
@@ -1796,8 +1786,6 @@ static int xgene_dma_remove(struct platform_device *pdev)
struct xgene_dma_chan *chan;
int i;
- xgene_dma_async_unregister(pdma);
-
/* Mask interrupts and disable DMA engine */
xgene_dma_mask_interrupts(pdma);
xgene_dma_disable(pdma);
^ permalink raw reply related
* [03/46] dmaengine: xilinx_dma: use dmaenginem_async_device_register to simplify the code
From: Huang Shijie @ 2018-08-03 7:19 UTC (permalink / raw)
To: vkoul
Cc: dmaengine, linux-kernel, dave.jiang, radhey.shyam.pandey,
appana.durga.rao, jmkrzyszt, gomonovych, peter.ujfalusi, keescook,
horms+renesas, geert+renesas, shawnguo, baoyou.xie, michal.simek,
baohua, ludovic.desroches, linus.walleij, david.brown,
Huang Shijie
Use dmaenginem_async_device_register to simplify the code,
remove dma_async_device_unregister.
Signed-off-by: Huang Shijie <sjhuang@iluvatar.ai>
---
drivers/dma/xilinx/xilinx_dma.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index c12442312595..97ffeb5e59bb 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -2705,13 +2705,12 @@ static int xilinx_dma_probe(struct platform_device *pdev)
}
/* Register the DMA engine with the core */
- dma_async_device_register(&xdev->common);
+ dmaenginem_async_device_register(&xdev->common);
err = of_dma_controller_register(node, of_dma_xilinx_xlate,
xdev);
if (err < 0) {
dev_err(&pdev->dev, "Unable to register DMA to DT\n");
- dma_async_device_unregister(&xdev->common);
goto error;
}
@@ -2747,8 +2746,6 @@ static int xilinx_dma_remove(struct platform_device *pdev)
of_dma_controller_free(pdev->dev.of_node);
- dma_async_device_unregister(&xdev->common);
-
for (i = 0; i < xdev->nr_channels; i++)
if (xdev->chan[i])
xilinx_dma_chan_remove(xdev->chan[i]);
^ permalink raw reply related
* [02/46] dmaengine: zynqmp_dma: use dmaenginem_async_device_register to simplify the code
From: Huang Shijie @ 2018-08-03 7:19 UTC (permalink / raw)
To: vkoul
Cc: dmaengine, linux-kernel, dave.jiang, radhey.shyam.pandey,
appana.durga.rao, jmkrzyszt, gomonovych, peter.ujfalusi, keescook,
horms+renesas, geert+renesas, shawnguo, baoyou.xie, michal.simek,
baohua, ludovic.desroches, linus.walleij, david.brown,
Huang Shijie
Use dmaenginem_async_device_register to simplify the code,
remove dma_async_device_unregister.
Signed-off-by: Huang Shijie <sjhuang@iluvatar.ai>
---
drivers/dma/xilinx/zynqmp_dma.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c
index c74a88b65039..acfc74b68717 100644
--- a/drivers/dma/xilinx/zynqmp_dma.c
+++ b/drivers/dma/xilinx/zynqmp_dma.c
@@ -1085,13 +1085,12 @@ static int zynqmp_dma_probe(struct platform_device *pdev)
p->dst_addr_widths = BIT(zdev->chan->bus_width / 8);
p->src_addr_widths = BIT(zdev->chan->bus_width / 8);
- dma_async_device_register(&zdev->common);
+ dmaenginem_async_device_register(&zdev->common);
ret = of_dma_controller_register(pdev->dev.of_node,
of_zynqmp_dma_xlate, zdev);
if (ret) {
dev_err(&pdev->dev, "Unable to register DMA to DT\n");
- dma_async_device_unregister(&zdev->common);
goto free_chan_resources;
}
@@ -1122,7 +1121,6 @@ static int zynqmp_dma_remove(struct platform_device *pdev)
struct zynqmp_dma_device *zdev = platform_get_drvdata(pdev);
of_dma_controller_free(pdev->dev.of_node);
- dma_async_device_unregister(&zdev->common);
zynqmp_dma_chan_remove(zdev->chan);
pm_runtime_disable(zdev->dev);
^ permalink raw reply related
* [01/46] dmaengine: zx_dma: use dmaenginem_async_device_register to simplify the code
From: Huang Shijie @ 2018-08-03 7:19 UTC (permalink / raw)
To: vkoul
Cc: dmaengine, linux-kernel, dave.jiang, radhey.shyam.pandey,
appana.durga.rao, jmkrzyszt, gomonovych, peter.ujfalusi, keescook,
horms+renesas, geert+renesas, shawnguo, baoyou.xie, michal.simek,
baohua, ludovic.desroches, linus.walleij, david.brown,
Huang Shijie
Use dmaenginem_async_device_register() to simplify the code.
Remove the code calling dma_async_device_unregister().
Signed-off-by: Huang Shijie <sjhuang@iluvatar.ai>
---
drivers/dma/zx_dma.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/dma/zx_dma.c b/drivers/dma/zx_dma.c
index 2571bc7693df..7febd20113ef 100644
--- a/drivers/dma/zx_dma.c
+++ b/drivers/dma/zx_dma.c
@@ -861,20 +861,18 @@ static int zx_dma_probe(struct platform_device *op)
INIT_LIST_HEAD(&d->chan_pending);
platform_set_drvdata(op, d);
- ret = dma_async_device_register(&d->slave);
+ ret = dmaenginem_async_device_register(&d->slave);
if (ret)
goto clk_dis;
ret = of_dma_controller_register((&op->dev)->of_node,
zx_of_dma_simple_xlate, d);
if (ret)
- goto of_dma_register_fail;
+ goto clk_dis;
dev_info(&op->dev, "initialized\n");
return 0;
-of_dma_register_fail:
- dma_async_device_unregister(&d->slave);
clk_dis:
clk_disable_unprepare(d->clk);
zx_dma_out:
@@ -889,7 +887,6 @@ static int zx_dma_remove(struct platform_device *op)
/* explictly free the irq */
devm_free_irq(&op->dev, d->irq, d);
- dma_async_device_unregister(&d->slave);
of_dma_controller_free((&op->dev)->of_node);
list_for_each_entry_safe(c, cn, &d->slave.channels,
^ permalink raw reply related
* [v4,7/7] dmaengine: xilinx_dma: Drop SG support for VDMA IP
From: Andrea Merello @ 2018-08-02 14:10 UTC (permalink / raw)
To: vkoul, dan.j.williams, michal.simek, appana.durga.rao, dmaengine
Cc: v4-000linux-arm-kernel, linux-kernel, robh+dt, mark.rutland,
devicetree, radhey.shyam.pandey, Andrea Merello
xilinx_vdma_start_transfer() is used only for VDMA IP, still it contains
conditional code on has_sg variable. has_sg is set only whenever the HW
does support SG mode, that is never true for VDMA IP.
This patch drops the never-taken branches.
Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
---
Changes in V4: introduced this patch in series
---
drivers/dma/xilinx/xilinx_dma.c | 84 +++++++++++++--------------------
1 file changed, 32 insertions(+), 52 deletions(-)
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index 78d0f2f8225e..07ceadef0a00 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -1093,6 +1093,8 @@ static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan)
struct xilinx_dma_tx_descriptor *desc, *tail_desc;
u32 reg, j;
struct xilinx_vdma_tx_segment *tail_segment;
+ struct xilinx_vdma_tx_segment *segment, *last = NULL;
+ int i = 0;
/* This function was invoked with lock held */
if (chan->err)
@@ -1112,14 +1114,6 @@ static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan)
tail_segment = list_last_entry(&tail_desc->segments,
struct xilinx_vdma_tx_segment, node);
- /*
- * If hardware is idle, then all descriptors on the running lists are
- * done, start new transfers
- */
- if (chan->has_sg)
- dma_ctrl_write(chan, XILINX_DMA_REG_CURDESC,
- desc->async_tx.phys);
-
/* Configure the hardware using info in the config structure */
reg = dma_ctrl_read(chan, XILINX_DMA_REG_DMACR);
@@ -1128,15 +1122,11 @@ static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan)
else
reg &= ~XILINX_DMA_DMACR_FRAMECNT_EN;
- /*
- * With SG, start with circular mode, so that BDs can be fetched.
- * In direct register mode, if not parking, enable circular mode
- */
- if (chan->has_sg || !config->park)
- reg |= XILINX_DMA_DMACR_CIRC_EN;
-
+ /* If not parking, enable circular mode */
if (config->park)
reg &= ~XILINX_DMA_DMACR_CIRC_EN;
+ else
+ reg |= XILINX_DMA_DMACR_CIRC_EN;
dma_ctrl_write(chan, XILINX_DMA_REG_DMACR, reg);
@@ -1158,48 +1148,38 @@ static void xilinx_vdma_start_transfer(struct xilinx_dma_chan *chan)
return;
/* Start the transfer */
- if (chan->has_sg) {
- dma_ctrl_write(chan, XILINX_DMA_REG_TAILDESC,
- tail_segment->phys);
- list_splice_tail_init(&chan->pending_list, &chan->active_list);
- chan->desc_pendingcount = 0;
- } else {
- struct xilinx_vdma_tx_segment *segment, *last = NULL;
- int i = 0;
-
- if (chan->desc_submitcount < chan->num_frms)
- i = chan->desc_submitcount;
-
- list_for_each_entry(segment, &desc->segments, node) {
- if (chan->ext_addr)
- vdma_desc_write_64(chan,
- XILINX_VDMA_REG_START_ADDRESS_64(i++),
- segment->hw.buf_addr,
- segment->hw.buf_addr_msb);
- else
- vdma_desc_write(chan,
+ if (chan->desc_submitcount < chan->num_frms)
+ i = chan->desc_submitcount;
+
+ list_for_each_entry(segment, &desc->segments, node) {
+ if (chan->ext_addr)
+ vdma_desc_write_64(chan,
+ XILINX_VDMA_REG_START_ADDRESS_64(i++),
+ segment->hw.buf_addr,
+ segment->hw.buf_addr_msb);
+ else
+ vdma_desc_write(chan,
XILINX_VDMA_REG_START_ADDRESS(i++),
segment->hw.buf_addr);
- last = segment;
- }
-
- if (!last)
- return;
+ last = segment;
+ }
- /* HW expects these parameters to be same for one transaction */
- vdma_desc_write(chan, XILINX_DMA_REG_HSIZE, last->hw.hsize);
- vdma_desc_write(chan, XILINX_DMA_REG_FRMDLY_STRIDE,
- last->hw.stride);
- vdma_desc_write(chan, XILINX_DMA_REG_VSIZE, last->hw.vsize);
+ if (!last)
+ return;
- chan->desc_submitcount++;
- chan->desc_pendingcount--;
- list_del(&desc->node);
- list_add_tail(&desc->node, &chan->active_list);
- if (chan->desc_submitcount == chan->num_frms)
- chan->desc_submitcount = 0;
- }
+ /* HW expects these parameters to be same for one transaction */
+ vdma_desc_write(chan, XILINX_DMA_REG_HSIZE, last->hw.hsize);
+ vdma_desc_write(chan, XILINX_DMA_REG_FRMDLY_STRIDE,
+ last->hw.stride);
+ vdma_desc_write(chan, XILINX_DMA_REG_VSIZE, last->hw.vsize);
+
+ chan->desc_submitcount++;
+ chan->desc_pendingcount--;
+ list_del(&desc->node);
+ list_add_tail(&desc->node, &chan->active_list);
+ if (chan->desc_submitcount == chan->num_frms)
+ chan->desc_submitcount = 0;
chan->idle = false;
}
^ permalink raw reply related
* [v4,6/7] dt-bindings: dmaengine: xilinx_dma: drop has-sg property
From: Andrea Merello @ 2018-08-02 14:10 UTC (permalink / raw)
To: vkoul, dan.j.williams, michal.simek, appana.durga.rao, dmaengine
Cc: v4-000linux-arm-kernel, linux-kernel, robh+dt, mark.rutland,
devicetree, radhey.shyam.pandey, Andrea Merello
This property is not needed anymore, because the driver now autodetects it.
Delete references in documentation.
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: devicetree@vger.kernel.org
Cc: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
Reviewed-by: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
Reviewed-by: Rob Herring <robh@kernel.org>
---
Changes in v2:
- cc DT maintainer
Changes in v3:
- cc DT maintainerS/ML
Changes in v4:
None
---
Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt | 3 ---
1 file changed, 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
index aec4a41a03ae..3051bc3713c6 100644
--- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
+++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
@@ -37,9 +37,6 @@ Required properties:
Required properties for VDMA:
- xlnx,num-fstores: Should be the number of framebuffers as configured in h/w.
-Optional properties:
-- xlnx,include-sg: Tells configured for Scatter-mode in
- the hardware.
Optional properties for AXI DMA:
- xlnx,sg-length-width: Should be set to the width in bits of the length
register as configured in h/w. Takes values {8...26}. If the property
^ permalink raw reply related
* [v4,5/7] dmaengine: xilinx_dma: autodetect whether the HW supports scatter-gather
From: Andrea Merello @ 2018-08-02 14:10 UTC (permalink / raw)
To: vkoul, dan.j.williams, michal.simek, appana.durga.rao, dmaengine
Cc: v4-000linux-arm-kernel, linux-kernel, robh+dt, mark.rutland,
devicetree, radhey.shyam.pandey, Andrea Merello
The AXIDMA and CDMA HW can be either direct-access or scatter-gather
version. These are SW incompatible.
The driver can handle both versions: a DT property was used to
tell the driver whether to assume the HW is in scatter-gather mode.
This patch makes the driver to autodetect this information. The DT
property is not required anymore.
No changes for VDMA.
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: devicetree@vger.kernel.org
Cc: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
Reviewed-by: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
---
Changes in v2:
- autodetect only in !VDMA case
Changes in v3:
- cc DT maintainers/ML
Changes in v4:
- fix typos in commit message
---
drivers/dma/xilinx/xilinx_dma.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index b17f24e4ec35..78d0f2f8225e 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -86,6 +86,7 @@
#define XILINX_DMA_DMASR_DMA_DEC_ERR BIT(6)
#define XILINX_DMA_DMASR_DMA_SLAVE_ERR BIT(5)
#define XILINX_DMA_DMASR_DMA_INT_ERR BIT(4)
+#define XILINX_DMA_DMASR_SG_MASK BIT(3)
#define XILINX_DMA_DMASR_IDLE BIT(1)
#define XILINX_DMA_DMASR_HALTED BIT(0)
#define XILINX_DMA_DMASR_DELAY_MASK GENMASK(31, 24)
@@ -407,7 +408,6 @@ struct xilinx_dma_config {
* @dev: Device Structure
* @common: DMA device structure
* @chan: Driver specific DMA channel
- * @has_sg: Specifies whether Scatter-Gather is present or not
* @mcdma: Specifies whether Multi-Channel is present or not
* @flush_on_fsync: Flush on frame sync
* @ext_addr: Indicates 64 bit addressing is supported by dma device
@@ -427,7 +427,6 @@ struct xilinx_dma_device {
struct device *dev;
struct dma_device common;
struct xilinx_dma_chan *chan[XILINX_DMA_MAX_CHANS_PER_DEVICE];
- bool has_sg;
bool mcdma;
u32 flush_on_fsync;
bool ext_addr;
@@ -2400,7 +2399,6 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
chan->dev = xdev->dev;
chan->xdev = xdev;
- chan->has_sg = xdev->has_sg;
chan->desc_pendingcount = 0x0;
chan->ext_addr = xdev->ext_addr;
/* This variable ensures that descriptors are not
@@ -2493,6 +2491,15 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
chan->stop_transfer = xilinx_dma_stop_transfer;
}
+ /* check if SG is enabled (only for AXIDMA and CDMA) */
+ if (xdev->dma_config->dmatype != XDMA_TYPE_VDMA) {
+ if (dma_ctrl_read(chan, XILINX_DMA_REG_DMASR) &
+ XILINX_DMA_DMASR_SG_MASK)
+ chan->has_sg = true;
+ dev_dbg(chan->dev, "ch %d: SG %s\n", chan->id,
+ chan->has_sg ? "enabled" : "disabled");
+ }
+
/* Initialize the tasklet */
tasklet_init(&chan->tasklet, xilinx_dma_do_tasklet,
(unsigned long)chan);
@@ -2631,7 +2638,6 @@ static int xilinx_dma_probe(struct platform_device *pdev)
return PTR_ERR(xdev->regs);
/* Retrieve the DMA engine properties from the device tree */
- xdev->has_sg = of_property_read_bool(node, "xlnx,include-sg");
xdev->max_buffer_len = GENMASK(XILINX_DMA_MAX_TRANS_LEN_MAX - 1, 0);
if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
^ permalink raw reply related
* [v4,4/7] dmaengine: xilinx_dma: program hardware supported buffer length
From: Andrea Merello @ 2018-08-02 14:10 UTC (permalink / raw)
To: vkoul, dan.j.williams, michal.simek, appana.durga.rao, dmaengine
Cc: v4-000linux-arm-kernel, linux-kernel, robh+dt, mark.rutland,
devicetree, radhey.shyam.pandey, Andrea Merello
From: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
AXI-DMA IP supports configurable (c_sg_length_width) buffer length
register width, hence read buffer length (xlnx,sg-length-width) DT
property and ensure that driver doesn't program buffer length
exceeding the supported limit. For VDMA and CDMA there is no change.
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: devicetree@vger.kernel.org
Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Signed-off-by: Andrea Merello <andrea.merello@gmail.com> [rebase, reword]
---
Changes in v2:
- drop original patch and replace with the one in Xilinx tree
Changes in v3:
- cc DT maintainers/ML
Changes in v4:
- upper bound for the property should be 26, not 23
- add warn for width > 23 as per xilinx original patch
- rework due to changes introduced in 1/6
---
drivers/dma/xilinx/xilinx_dma.c | 36 +++++++++++++++++++++++++--------
1 file changed, 28 insertions(+), 8 deletions(-)
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index aaa6de8a70e4..b17f24e4ec35 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -158,7 +158,9 @@
#define XILINX_DMA_REG_BTT 0x28
/* AXI DMA Specific Masks/Bit fields */
-#define XILINX_DMA_MAX_TRANS_LEN GENMASK(22, 0)
+#define XILINX_DMA_MAX_TRANS_LEN_MIN 8
+#define XILINX_DMA_MAX_TRANS_LEN_MAX 23
+#define XILINX_DMA_V2_MAX_TRANS_LEN_MAX 26
#define XILINX_DMA_CR_COALESCE_MAX GENMASK(23, 16)
#define XILINX_DMA_CR_CYCLIC_BD_EN_MASK BIT(4)
#define XILINX_DMA_CR_COALESCE_SHIFT 16
@@ -418,6 +420,7 @@ struct xilinx_dma_config {
* @rxs_clk: DMA s2mm stream clock
* @nr_channels: Number of channels DMA device supports
* @chan_id: DMA channel identifier
+ * @max_buffer_len: Max buffer length
*/
struct xilinx_dma_device {
void __iomem *regs;
@@ -437,6 +440,7 @@ struct xilinx_dma_device {
struct clk *rxs_clk;
u32 nr_channels;
u32 chan_id;
+ u32 max_buffer_len;
};
/* Macros */
@@ -964,7 +968,7 @@ static int xilinx_dma_calc_copysize(struct xilinx_dma_chan *chan,
int size, int done)
{
size_t copy = min_t(size_t, size - done,
- XILINX_DMA_MAX_TRANS_LEN);
+ chan->xdev->max_buffer_len);
if ((copy + done < size) &&
chan->xdev->common.copy_align) {
@@ -1011,7 +1015,7 @@ static enum dma_status xilinx_dma_tx_status(struct dma_chan *dchan,
list_for_each_entry(segment, &desc->segments, node) {
hw = &segment->hw;
residue += (hw->control - hw->status) &
- XILINX_DMA_MAX_TRANS_LEN;
+ chan->xdev->max_buffer_len;
}
}
spin_unlock_irqrestore(&chan->lock, flags);
@@ -1263,7 +1267,7 @@ static void xilinx_cdma_start_transfer(struct xilinx_dma_chan *chan)
/* Start the transfer */
dma_ctrl_write(chan, XILINX_DMA_REG_BTT,
- hw->control & XILINX_DMA_MAX_TRANS_LEN);
+ hw->control & chan->xdev->max_buffer_len);
}
list_splice_tail_init(&chan->pending_list, &chan->active_list);
@@ -1366,7 +1370,7 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)
/* Start the transfer */
dma_ctrl_write(chan, XILINX_DMA_REG_BTT,
- hw->control & XILINX_DMA_MAX_TRANS_LEN);
+ hw->control & chan->xdev->max_buffer_len);
}
list_splice_tail_init(&chan->pending_list, &chan->active_list);
@@ -1727,7 +1731,7 @@ xilinx_cdma_prep_memcpy(struct dma_chan *dchan, dma_addr_t dma_dst,
struct xilinx_cdma_tx_segment *segment;
struct xilinx_cdma_desc_hw *hw;
- if (!len || len > XILINX_DMA_MAX_TRANS_LEN)
+ if (!len || len > chan->xdev->max_buffer_len)
return NULL;
desc = xilinx_dma_alloc_tx_descriptor(chan);
@@ -2596,7 +2600,7 @@ static int xilinx_dma_probe(struct platform_device *pdev)
struct xilinx_dma_device *xdev;
struct device_node *child, *np = pdev->dev.of_node;
struct resource *io;
- u32 num_frames, addr_width;
+ u32 num_frames, addr_width, len_width;
int i, err;
/* Allocate and initialize the DMA engine structure */
@@ -2628,8 +2632,24 @@ static int xilinx_dma_probe(struct platform_device *pdev)
/* Retrieve the DMA engine properties from the device tree */
xdev->has_sg = of_property_read_bool(node, "xlnx,include-sg");
- if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
+ xdev->max_buffer_len = GENMASK(XILINX_DMA_MAX_TRANS_LEN_MAX - 1, 0);
+
+ if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
xdev->mcdma = of_property_read_bool(node, "xlnx,mcdma");
+ if (!of_property_read_u32(node, "xlnx,sg-length-width",
+ &len_width)) {
+ if (len_width < XILINX_DMA_MAX_TRANS_LEN_MIN ||
+ len_width > XILINX_DMA_V2_MAX_TRANS_LEN_MAX) {
+ dev_warn(xdev->dev,
+ "invalid xlnx,sg-length-width property value. Using default width\n");
+ } else {
+ if (len_width > XILINX_DMA_MAX_TRANS_LEN_MAX)
+ dev_warn(xdev->dev, "Please ensure that IP supports buffer length > 23 bits\n");
+ xdev->max_buffer_len =
+ GENMASK(len_width - 1, 0);
+ }
+ }
+ }
if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
err = of_property_read_u32(node, "xlnx,num-fstores",
^ permalink raw reply related
* [v4,3/7] dt-bindings: dmaengine: xilinx_dma: add optional xlnx,sg-length-width property
From: Andrea Merello @ 2018-08-02 14:10 UTC (permalink / raw)
To: vkoul, dan.j.williams, michal.simek, appana.durga.rao, dmaengine
Cc: v4-000linux-arm-kernel, linux-kernel, robh+dt, mark.rutland,
devicetree, radhey.shyam.pandey, Andrea Merello
The width of the "length register" cannot be autodetected, and it is now
specified with a DT property. Add DOC for it.
Cc: Rob Herring <robh+dt@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: devicetree@vger.kernel.org
Cc: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
Reviewed-by: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
---
Changes in v2:
- change property name
- property is now optional
- cc DT maintainer
Changes in v3:
- reword
- cc DT maintainerS and ML
Changes in v4:
- specify the unit, the valid range and the default value
---
Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
index a2b8bfaec43c..aec4a41a03ae 100644
--- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
+++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
@@ -41,6 +41,10 @@ Optional properties:
- xlnx,include-sg: Tells configured for Scatter-mode in
the hardware.
Optional properties for AXI DMA:
+- xlnx,sg-length-width: Should be set to the width in bits of the length
+ register as configured in h/w. Takes values {8...26}. If the property
+ is missing or invalid then the default value 23 is used. This is the
+ maximum value that is supported by all IP versions.
- xlnx,mcdma: Tells whether configured for multi-channel mode in the hardware.
Optional properties for VDMA:
- xlnx,flush-fsync: Tells which channel to Flush on Frame sync.
^ permalink raw reply related
* [v4,2/7] dmaengine: xilinx_dma: in axidma slave_sg and dma_cylic mode align split descriptors
From: Andrea Merello @ 2018-08-02 14:10 UTC (permalink / raw)
To: vkoul, dan.j.williams, michal.simek, appana.durga.rao, dmaengine
Cc: v4-000linux-arm-kernel, linux-kernel, robh+dt, mark.rutland,
devicetree, radhey.shyam.pandey, Andrea Merello
Whenever a single or cyclic transaction is prepared, the driver
could eventually split it over several SG descriptors in order
to deal with the HW maximum transfer length.
This could end up in DMA operations starting from a misaligned
address. This seems fatal for the HW if DRE is not enabled.
This patch eventually adjusts the transfer size in order to make sure
all operations start from an aligned address.
Cc: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
Reviewed-by: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
---
Changes in v2:
- don't introduce copy_mask field, rather rely on already-esistent
copy_align field. Suggested by Radhey Shyam Pandey
- reword title
Changes in v3:
- fix bug introduced in v2: wrong copy size when DRE is enabled
- use implementation suggested by Radhey Shyam Pandey
Changes in v4:
- rework on the top of 1/6
---
drivers/dma/xilinx/xilinx_dma.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index a3aaa0e34cc7..aaa6de8a70e4 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -954,15 +954,28 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
/**
* xilinx_dma_calc_copysize - Calculate the amount of data to copy
+ * @chan: Driver specific DMA channel
* @size: Total data that needs to be copied
* @done: Amount of data that has been already copied
*
* Return: Amount of data that has to be copied
*/
-static int xilinx_dma_calc_copysize(int size, int done)
+static int xilinx_dma_calc_copysize(struct xilinx_dma_chan *chan,
+ int size, int done)
{
- return min_t(size_t, size - done,
+ size_t copy = min_t(size_t, size - done,
XILINX_DMA_MAX_TRANS_LEN);
+
+ if ((copy + done < size) &&
+ chan->xdev->common.copy_align) {
+ /*
+ * If this is not the last descriptor, make sure
+ * the next one will be properly aligned
+ */
+ copy = rounddown(copy,
+ (1 << chan->xdev->common.copy_align));
+ }
+ return copy;
}
/**
@@ -1804,7 +1817,7 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg(
* Calculate the maximum number of bytes to transfer,
* making sure it is less than the hw limit
*/
- copy = xilinx_dma_calc_copysize(sg_dma_len(sg),
+ copy = xilinx_dma_calc_copysize(chan, sg_dma_len(sg),
sg_used);
hw = &segment->hw;
@@ -1909,7 +1922,8 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_dma_cyclic(
* Calculate the maximum number of bytes to transfer,
* making sure it is less than the hw limit
*/
- copy = xilinx_dma_calc_copysize(period_len, sg_used);
+ copy = xilinx_dma_calc_copysize(chan,
+ period_len, sg_used);
hw = &segment->hw;
xilinx_axidma_buf(chan, hw, buf_addr, sg_used,
period_len * i);
^ permalink raw reply related
* [v4,1/7] dmaengine: xilinx_dma: commonize DMA copy size calculation
From: Andrea Merello @ 2018-08-02 14:10 UTC (permalink / raw)
To: vkoul, dan.j.williams, michal.simek, appana.durga.rao, dmaengine
Cc: v4-000linux-arm-kernel, linux-kernel, robh+dt, mark.rutland,
devicetree, radhey.shyam.pandey, Andrea Merello
This patch removes a bit of duplicated code by introducing a new
function that implements calculations for DMA copy size.
Suggested-by: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Andrea Merello <andrea.merello@gmail.com>
---
Changes in v4:
- introduce this patch in the patch series
---
drivers/dma/xilinx/xilinx_dma.c | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index 27b523530c4a..a3aaa0e34cc7 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -952,6 +952,19 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
return 0;
}
+/**
+ * xilinx_dma_calc_copysize - Calculate the amount of data to copy
+ * @size: Total data that needs to be copied
+ * @done: Amount of data that has been already copied
+ *
+ * Return: Amount of data that has to be copied
+ */
+static int xilinx_dma_calc_copysize(int size, int done)
+{
+ return min_t(size_t, size - done,
+ XILINX_DMA_MAX_TRANS_LEN);
+}
+
/**
* xilinx_dma_tx_status - Get DMA transaction status
* @dchan: DMA channel
@@ -1791,8 +1804,8 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg(
* Calculate the maximum number of bytes to transfer,
* making sure it is less than the hw limit
*/
- copy = min_t(size_t, sg_dma_len(sg) - sg_used,
- XILINX_DMA_MAX_TRANS_LEN);
+ copy = xilinx_dma_calc_copysize(sg_dma_len(sg),
+ sg_used);
hw = &segment->hw;
/* Fill in the descriptor */
@@ -1896,8 +1909,7 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_dma_cyclic(
* Calculate the maximum number of bytes to transfer,
* making sure it is less than the hw limit
*/
- copy = min_t(size_t, period_len - sg_used,
- XILINX_DMA_MAX_TRANS_LEN);
+ copy = xilinx_dma_calc_copysize(period_len, sg_used);
hw = &segment->hw;
xilinx_axidma_buf(chan, hw, buf_addr, sg_used,
period_len * i);
^ permalink raw reply related
* [RFC,2/2] dmaengine: xilinx_dma: Add Xilinx AXI MCDMA Engine driver support
From: Radhey Shyam Pandey @ 2018-07-31 17:46 UTC (permalink / raw)
To: vkoul, robh+dt, mark.rutland, michal.simek, dan.j.williams,
radhey.shyam.pandey, appanad, lars
Cc: dmaengine, devicetree, linux-arm-kernel, linux-kernel
Add support for AXI Multichannel Direct Memory Access (AXI MCDMA)
core, which is a soft Xilinx IP core that provides high-bandwidth
direct memory access between memory and AXI4-Stream target peripherals.
The AXI MCDMA core provides scatter-gather interface with multiple
independent transmit and receive channels.
Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
---
drivers/dma/xilinx/xilinx_dma.c | 449 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 440 insertions(+), 9 deletions(-)
diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index c124423..f136e5a 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -25,6 +25,11 @@
* Access (DMA) between a memory-mapped source address and a memory-mapped
* destination address.
*
+ * The AXI Multichannel Direct Memory Access (AXI MCDMA) core is a soft
+ * Xilinx IP that provides high-bandwidth direct memory access between
+ * memory and AXI4-Stream target peripherals. It supports scatter-gather
+ * interface with multiple independent transmit and receive channels.
+ *
* 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
@@ -190,6 +195,30 @@
/* AXI CDMA Specific Masks */
#define XILINX_CDMA_CR_SGMODE BIT(3)
+/* AXI MCDMA Specific Registers/Offsets */
+#define XILINX_MCDMA_MM2S_CTRL_OFFSET 0x0000
+#define XILINX_MCDMA_S2MM_CTRL_OFFSET 0x0500
+#define XILINX_MCDMA_CHEN_OFFSET 0x0008
+#define XILINX_MCDMA_CH_ERR_OFFSET 0x0010
+#define XILINX_MCDMA_RXINT_SER_OFFSET 0x0020
+#define XILINX_MCDMA_TXINT_SER_OFFSET 0x0028
+#define XILINX_MCDMA_CHAN_CR_OFFSET(x) (0x40 + (x) * 0x40)
+#define XILINX_MCDMA_CHAN_SR_OFFSET(x) (0x44 + (x) * 0x40)
+#define XILINX_MCDMA_CHAN_CDESC_OFFSET(x) (0x48 + (x) * 0x40)
+#define XILINX_MCDMA_CHAN_TDESC_OFFSET(x) (0x50 + (x) * 0x40)
+
+/* AXI MCDMA Specific Masks/Shifts */
+#define XILINX_MCDMA_COALESCE_SHIFT 16
+#define XILINX_MCDMA_COALESCE_MAX 24
+#define XILINX_MCDMA_IRQ_ALL_MASK GENMASK(7, 5)
+#define XILINX_MCDMA_COALESCE_MASK GENMASK(23, 16)
+#define XILINX_MCDMA_CR_RUNSTOP_MASK BIT(0)
+#define XILINX_MCDMA_IRQ_IOC_MASK BIT(5)
+#define XILINX_MCDMA_IRQ_DELAY_MASK BIT(6)
+#define XILINX_MCDMA_IRQ_ERR_MASK BIT(7)
+#define XILINX_MCDMA_BD_EOP BIT(30)
+#define XILINX_MCDMA_BD_SOP BIT(31)
+
/**
* struct xilinx_vdma_desc_hw - Hardware Descriptor
* @next_desc: Next Descriptor Pointer @0x00
@@ -236,6 +265,30 @@ struct xilinx_axidma_desc_hw {
} __aligned(64);
/**
+ * struct xilinx_aximcdma_desc_hw - Hardware Descriptor for AXI MCDMA
+ * @next_desc: Next Descriptor Pointer @0x00
+ * @next_desc_msb: MSB of Next Descriptor Pointer @0x04
+ * @buf_addr: Buffer address @0x08
+ * @buf_addr_msb: MSB of Buffer address @0x0C
+ * @rsvd: Reserved field @0x10
+ * @control: Control Information field @0x14
+ * @status: Status field @0x18
+ * @sideband_status: Status of sideband signals @0x1C
+ * @app: APP Fields @0x20 - 0x30
+ */
+struct xilinx_aximcdma_desc_hw {
+ u32 next_desc;
+ u32 next_desc_msb;
+ u32 buf_addr;
+ u32 buf_addr_msb;
+ u32 rsvd;
+ u32 control;
+ u32 status;
+ u32 sideband_status;
+ u32 app[XILINX_DMA_NUM_APP_WORDS];
+} __aligned(64);
+
+/**
* struct xilinx_cdma_desc_hw - Hardware Descriptor
* @next_desc: Next Descriptor Pointer @0x00
* @next_desc_msb: Next Descriptor Pointer MSB @0x04
@@ -282,6 +335,18 @@ struct xilinx_axidma_tx_segment {
} __aligned(64);
/**
+ * struct xilinx_aximcdma_tx_segment - Descriptor segment
+ * @hw: Hardware descriptor
+ * @node: Node in the descriptor segments list
+ * @phys: Physical address of segment
+ */
+struct xilinx_aximcdma_tx_segment {
+ struct xilinx_aximcdma_desc_hw hw;
+ struct list_head node;
+ dma_addr_t phys;
+} __aligned(64);
+
+/**
* struct xilinx_cdma_tx_segment - Descriptor segment
* @hw: Hardware descriptor
* @node: Node in the descriptor segments list
@@ -336,7 +401,8 @@ struct xilinx_dma_tx_descriptor {
* @ext_addr: Indicates 64 bit addressing is supported by dma channel
* @desc_submitcount: Descriptor h/w submitted count
* @residue: Residue for AXI DMA
- * @seg_v: Statically allocated segments base
+ * @seg_v: Statically allocated segments base for AXI DMA
+ * @seg_mv: Statically allocated segments base for AXI MCDMA
* @seg_p: Physical allocated segments base
* @cyclic_seg_v: Statically allocated segment base for cyclic transfers
* @cyclic_seg_p: Physical allocated segments base for cyclic dma
@@ -374,6 +440,7 @@ struct xilinx_dma_chan {
u32 desc_submitcount;
u32 residue;
struct xilinx_axidma_tx_segment *seg_v;
+ struct xilinx_aximcdma_tx_segment *seg_mv;
dma_addr_t seg_p;
struct xilinx_axidma_tx_segment *cyclic_seg_v;
dma_addr_t cyclic_seg_p;
@@ -395,6 +462,7 @@ enum xdma_ip_type {
XDMA_TYPE_AXIDMA = 0,
XDMA_TYPE_CDMA,
XDMA_TYPE_VDMA,
+ XDMA_TYPE_AXIMCDMA
};
struct xilinx_dma_config {
@@ -402,6 +470,7 @@ struct xilinx_dma_config {
int (*clk_init)(struct platform_device *pdev, struct clk **axi_clk,
struct clk **tx_clk, struct clk **txs_clk,
struct clk **rx_clk, struct clk **rxs_clk);
+ irqreturn_t (*irq_handler)(int irq, void *data);
};
/**
@@ -542,6 +611,18 @@ static inline void xilinx_axidma_buf(struct xilinx_dma_chan *chan,
}
}
+static inline void xilinx_aximcdma_buf(struct xilinx_dma_chan *chan,
+ struct xilinx_aximcdma_desc_hw *hw,
+ dma_addr_t buf_addr, size_t sg_used)
+{
+ if (chan->ext_addr) {
+ hw->buf_addr = lower_32_bits(buf_addr + sg_used);
+ hw->buf_addr_msb = upper_32_bits(buf_addr + sg_used);
+ } else {
+ hw->buf_addr = buf_addr + sg_used;
+ }
+}
+
/* -----------------------------------------------------------------------------
* Descriptors and segments alloc and free
*/
@@ -612,6 +693,31 @@ xilinx_axidma_alloc_tx_segment(struct xilinx_dma_chan *chan)
return segment;
}
+/**
+ * xilinx_aximcdma_alloc_tx_segment - Allocate transaction segment
+ * @chan: Driver specific DMA channel
+ *
+ * Return: The allocated segment on success and NULL on failure.
+ */
+static struct xilinx_aximcdma_tx_segment *
+xilinx_aximcdma_alloc_tx_segment(struct xilinx_dma_chan *chan)
+{
+ struct xilinx_aximcdma_tx_segment *segment = NULL;
+ unsigned long flags;
+
+ spin_lock_irqsave(&chan->lock, flags);
+ if (!list_empty(&chan->free_seg_list)) {
+ segment = list_first_entry(&chan->free_seg_list,
+ struct xilinx_aximcdma_tx_segment,
+ node);
+ list_del(&segment->node);
+ }
+ spin_unlock_irqrestore(&chan->lock, flags);
+
+ return segment;
+}
+
+
static void xilinx_dma_clean_hw_desc(struct xilinx_axidma_desc_hw *hw)
{
u32 next_desc = hw->next_desc;
@@ -623,6 +729,17 @@ static void xilinx_dma_clean_hw_desc(struct xilinx_axidma_desc_hw *hw)
hw->next_desc_msb = next_desc_msb;
}
+static void xilinx_mcdma_clean_hw_desc(struct xilinx_aximcdma_desc_hw *hw)
+{
+ u32 next_desc = hw->next_desc;
+ u32 next_desc_msb = hw->next_desc_msb;
+
+ memset(hw, 0, sizeof(struct xilinx_aximcdma_desc_hw));
+
+ hw->next_desc = next_desc;
+ hw->next_desc_msb = next_desc_msb;
+}
+
/**
* xilinx_dma_free_tx_segment - Free transaction segment
* @chan: Driver specific DMA channel
@@ -637,6 +754,19 @@ static void xilinx_dma_free_tx_segment(struct xilinx_dma_chan *chan,
}
/**
+ * xilinx_mcdma_free_tx_segment - Free transaction segment
+ * @chan: Driver specific DMA channel
+ * @segment: DMA transaction segment
+ */
+static void xilinx_mcdma_free_tx_segment(struct xilinx_dma_chan *chan,
+ struct xilinx_aximcdma_tx_segment *segment)
+{
+ xilinx_mcdma_clean_hw_desc(&segment->hw);
+
+ list_add_tail(&segment->node, &chan->free_seg_list);
+}
+
+/**
* xilinx_cdma_free_tx_segment - Free transaction segment
* @chan: Driver specific DMA channel
* @segment: DMA transaction segment
@@ -690,6 +820,7 @@ xilinx_dma_free_tx_descriptor(struct xilinx_dma_chan *chan,
struct xilinx_vdma_tx_segment *segment, *next;
struct xilinx_cdma_tx_segment *cdma_segment, *cdma_next;
struct xilinx_axidma_tx_segment *axidma_segment, *axidma_next;
+ struct xilinx_aximcdma_tx_segment *aximcdma_segment, *aximcdma_next;
if (!desc)
return;
@@ -705,12 +836,18 @@ xilinx_dma_free_tx_descriptor(struct xilinx_dma_chan *chan,
list_del(&cdma_segment->node);
xilinx_cdma_free_tx_segment(chan, cdma_segment);
}
- } else {
+ } else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
list_for_each_entry_safe(axidma_segment, axidma_next,
&desc->segments, node) {
list_del(&axidma_segment->node);
xilinx_dma_free_tx_segment(chan, axidma_segment);
}
+ } else {
+ list_for_each_entry_safe(aximcdma_segment, aximcdma_next,
+ &desc->segments, node) {
+ list_del(&aximcdma_segment->node);
+ xilinx_mcdma_free_tx_segment(chan, aximcdma_segment);
+ }
}
kfree(desc);
@@ -779,7 +916,19 @@ static void xilinx_dma_free_chan_resources(struct dma_chan *dchan)
chan->cyclic_seg_v, chan->cyclic_seg_p);
}
- if (chan->xdev->dma_config->dmatype != XDMA_TYPE_AXIDMA) {
+ if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA) {
+ spin_lock_irqsave(&chan->lock, flags);
+ INIT_LIST_HEAD(&chan->free_seg_list);
+ spin_unlock_irqrestore(&chan->lock, flags);
+
+ /* Free memory that is allocated for BD */
+ dma_free_coherent(chan->dev, sizeof(*chan->seg_mv) *
+ XILINX_DMA_NUM_DESCS, chan->seg_mv,
+ chan->seg_p);
+ }
+
+ if (chan->xdev->dma_config->dmatype != XDMA_TYPE_AXIDMA &&
+ chan->xdev->dma_config->dmatype != XDMA_TYPE_AXIMCDMA) {
dma_pool_destroy(chan->desc_pool);
chan->desc_pool = NULL;
}
@@ -900,6 +1049,30 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
list_add_tail(&chan->seg_v[i].node,
&chan->free_seg_list);
}
+ } else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA) {
+ /* Allocate the buffer descriptors. */
+ chan->seg_mv = dma_zalloc_coherent(chan->dev,
+ sizeof(*chan->seg_mv) *
+ XILINX_DMA_NUM_DESCS,
+ &chan->seg_p, GFP_KERNEL);
+ if (!chan->seg_mv) {
+ dev_err(chan->dev,
+ "unable to allocate channel %d descriptors\n",
+ chan->id);
+ return -ENOMEM;
+ }
+ for (i = 0; i < XILINX_DMA_NUM_DESCS; i++) {
+ chan->seg_mv[i].hw.next_desc =
+ lower_32_bits(chan->seg_p + sizeof(*chan->seg_mv) *
+ ((i + 1) % XILINX_DMA_NUM_DESCS));
+ chan->seg_mv[i].hw.next_desc_msb =
+ upper_32_bits(chan->seg_p + sizeof(*chan->seg_mv) *
+ ((i + 1) % XILINX_DMA_NUM_DESCS));
+ chan->seg_mv[i].phys = chan->seg_p +
+ sizeof(*chan->seg_v) * i;
+ list_add_tail(&chan->seg_mv[i].node,
+ &chan->free_seg_list);
+ }
} else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
chan->desc_pool = dma_pool_create("xilinx_cdma_desc_pool",
chan->dev,
@@ -915,7 +1088,8 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
}
if (!chan->desc_pool &&
- (chan->xdev->dma_config->dmatype != XDMA_TYPE_AXIDMA)) {
+ ((chan->xdev->dma_config->dmatype != XDMA_TYPE_AXIDMA) &&
+ chan->xdev->dma_config->dmatype != XDMA_TYPE_AXIMCDMA)) {
dev_err(chan->dev,
"unable to allocate channel %d descriptor pool\n",
chan->id);
@@ -1362,6 +1536,71 @@ static void xilinx_dma_start_transfer(struct xilinx_dma_chan *chan)
}
/**
+ * xilinx_mcdma_start_transfer - Starts MCDMA transfer
+ * @chan: Driver specific channel struct pointer
+ */
+static void xilinx_mcdma_start_transfer(struct xilinx_dma_chan *chan)
+{
+ struct xilinx_dma_tx_descriptor *head_desc, *tail_desc;
+ struct xilinx_axidma_tx_segment *tail_segment;
+ u32 reg;
+
+ if (chan->err)
+ return;
+
+ if (!chan->idle)
+ return;
+
+ if (list_empty(&chan->pending_list))
+ return;
+
+ head_desc = list_first_entry(&chan->pending_list,
+ struct xilinx_dma_tx_descriptor, node);
+ tail_desc = list_last_entry(&chan->pending_list,
+ struct xilinx_dma_tx_descriptor, node);
+ tail_segment = list_last_entry(&tail_desc->segments,
+ struct xilinx_axidma_tx_segment, node);
+
+ reg = dma_ctrl_read(chan, XILINX_MCDMA_CHAN_CR_OFFSET(chan->tdest));
+
+ if (chan->desc_pendingcount <= XILINX_MCDMA_COALESCE_MAX) {
+ reg &= ~XILINX_MCDMA_COALESCE_MASK;
+ reg |= chan->desc_pendingcount <<
+ XILINX_MCDMA_COALESCE_SHIFT;
+ }
+
+ reg |= XILINX_MCDMA_IRQ_ALL_MASK;
+ dma_ctrl_write(chan, XILINX_MCDMA_CHAN_CR_OFFSET(chan->tdest), reg);
+
+ /* Program current descriptor */
+ xilinx_write(chan, XILINX_MCDMA_CHAN_CDESC_OFFSET(chan->tdest),
+ head_desc->async_tx.phys);
+
+ /* Program channel enable register */
+ reg = dma_ctrl_read(chan, XILINX_MCDMA_CHEN_OFFSET);
+ reg |= BIT(chan->tdest);
+ dma_ctrl_write(chan, XILINX_MCDMA_CHEN_OFFSET, reg);
+
+ /* Start the fetch of BDs for the channel */
+ reg = dma_ctrl_read(chan, XILINX_MCDMA_CHAN_CR_OFFSET(chan->tdest));
+ reg |= XILINX_MCDMA_CR_RUNSTOP_MASK;
+ dma_ctrl_write(chan, XILINX_MCDMA_CHAN_CR_OFFSET(chan->tdest), reg);
+
+ xilinx_dma_start(chan);
+
+ if (chan->err)
+ return;
+
+ /* Start the transfer */
+ xilinx_write(chan, XILINX_MCDMA_CHAN_TDESC_OFFSET(chan->tdest),
+ tail_segment->phys);
+
+ list_splice_tail_init(&chan->pending_list, &chan->active_list);
+ chan->desc_pendingcount = 0;
+ chan->idle = false;
+}
+
+/**
* xilinx_dma_issue_pending - Issue pending transactions
* @dchan: DMA channel
*/
@@ -1452,6 +1691,75 @@ static int xilinx_dma_chan_reset(struct xilinx_dma_chan *chan)
}
/**
+ * xilinx_mcdma_irq_handler - MCDMA Interrupt handler
+ * @irq: IRQ number
+ * @data: Pointer to the Xilinx MCDMA channel structure
+ *
+ * Return: IRQ_HANDLED/IRQ_NONE
+ */
+static irqreturn_t xilinx_mcdma_irq_handler(int irq, void *data)
+{
+ struct xilinx_dma_chan *chan = data;
+ u32 status, ser_offset, chan_sermask, chan_offset = 0, chan_id;
+
+ if (chan->direction == DMA_DEV_TO_MEM)
+ ser_offset = XILINX_MCDMA_RXINT_SER_OFFSET;
+ else
+ ser_offset = XILINX_MCDMA_TXINT_SER_OFFSET;
+
+ /* Read the channel id raising the interrupt*/
+ chan_sermask = dma_ctrl_read(chan, ser_offset);
+ chan_id = ffs(chan_sermask);
+
+ if (!chan_id)
+ return IRQ_NONE;
+
+ if (chan->direction == DMA_DEV_TO_MEM)
+ chan_offset = XILINX_DMA_MAX_CHANS_PER_DEVICE / 2;
+
+ chan_offset = chan_offset + (chan_id - 1);
+ chan = chan->xdev->chan[chan_offset];
+ /* Read the status and ack the interrupts. */
+ status = dma_ctrl_read(chan, XILINX_MCDMA_CHAN_SR_OFFSET(chan->tdest));
+ if (!(status & XILINX_MCDMA_IRQ_ALL_MASK))
+ return IRQ_NONE;
+
+ dma_ctrl_write(chan, XILINX_MCDMA_CHAN_SR_OFFSET(chan->tdest),
+ status & XILINX_MCDMA_IRQ_ALL_MASK);
+
+ if (status & XILINX_MCDMA_IRQ_ERR_MASK) {
+ dev_err(chan->dev, "Channel %p has errors %x cdr %x tdr %x\n",
+ chan, dma_ctrl_read(chan,
+ XILINX_MCDMA_CH_ERR_OFFSET), dma_ctrl_read(chan,
+ XILINX_MCDMA_CHAN_CDESC_OFFSET(chan->tdest)),
+ dma_ctrl_read(chan,
+ XILINX_MCDMA_CHAN_TDESC_OFFSET
+ (chan->tdest)));
+ chan->err = true;
+ }
+
+ if (status & XILINX_MCDMA_IRQ_DELAY_MASK) {
+ /*
+ * Device takes too long to do the transfer when user requires
+ * responsiveness.
+ */
+ dev_dbg(chan->dev, "Inter-packet latency too long\n");
+ }
+
+ if (status & XILINX_MCDMA_IRQ_IOC_MASK) {
+ spin_lock(&chan->lock);
+ xilinx_dma_complete_descriptor(chan);
+ chan->idle = true;
+ chan->start_transfer(chan);
+ spin_unlock(&chan->lock);
+ }
+
+ tasklet_schedule(&chan->tasklet);
+ return IRQ_HANDLED;
+
+}
+
+/**
* xilinx_dma_irq_handler - DMA Interrupt handler
* @irq: IRQ number
* @data: Pointer to the Xilinx DMA channel structure
@@ -1750,6 +2058,103 @@ xilinx_cdma_prep_memcpy(struct dma_chan *dchan, dma_addr_t dma_dst,
xilinx_dma_free_tx_descriptor(chan, desc);
return NULL;
}
+/**
+ * xilinx_mcdma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction
+ * @dchan: DMA channel
+ * @sgl: scatterlist to transfer to/from
+ * @sg_len: number of entries in @scatterlist
+ * @direction: DMA direction
+ * @flags: transfer ack flags
+ * @context: APP words of the descriptor
+ *
+ * Return: Async transaction descriptor on success and NULL on failure
+ */
+static struct dma_async_tx_descriptor *xilinx_mcdma_prep_slave_sg(
+ struct dma_chan *dchan, struct scatterlist *sgl, unsigned int sg_len,
+ enum dma_transfer_direction direction, unsigned long flags,
+ void *context)
+{
+ struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
+ struct xilinx_dma_tx_descriptor *desc;
+ struct xilinx_aximcdma_tx_segment *segment = NULL;
+ u32 *app_w = (u32 *)context;
+ struct scatterlist *sg;
+ size_t copy;
+ size_t sg_used;
+ unsigned int i;
+
+ if (!is_slave_direction(direction))
+ return NULL;
+
+ /* Allocate a transaction descriptor. */
+ desc = xilinx_dma_alloc_tx_descriptor(chan);
+ if (!desc)
+ return NULL;
+
+ dma_async_tx_descriptor_init(&desc->async_tx, &chan->common);
+ desc->async_tx.tx_submit = xilinx_dma_tx_submit;
+
+ /* Build transactions using information in the scatter gather list */
+ for_each_sg(sgl, sg, sg_len, i) {
+ sg_used = 0;
+
+ /* Loop until the entire scatterlist entry is used */
+ while (sg_used < sg_dma_len(sg)) {
+ struct xilinx_aximcdma_desc_hw *hw;
+
+ /* Get a free segment */
+ segment = xilinx_aximcdma_alloc_tx_segment(chan);
+ if (!segment)
+ goto error;
+
+ /*
+ * Calculate the maximum number of bytes to transfer,
+ * making sure it is less than the hw limit
+ */
+ copy = min_t(size_t, sg_dma_len(sg) - sg_used,
+ XILINX_DMA_MAX_TRANS_LEN);
+ hw = &segment->hw;
+
+ /* Fill in the descriptor */
+ xilinx_aximcdma_buf(chan, hw, sg_dma_address(sg),
+ sg_used);
+ hw->control = copy;
+
+ if (chan->direction == DMA_MEM_TO_DEV) {
+ if (app_w)
+ memcpy(hw->app, app_w, sizeof(u32) *
+ XILINX_DMA_NUM_APP_WORDS);
+ }
+
+ sg_used += copy;
+ /*
+ * Insert the segment into the descriptor segments
+ * list.
+ */
+ list_add_tail(&segment->node, &desc->segments);
+ }
+ }
+
+ segment = list_first_entry(&desc->segments,
+ struct xilinx_aximcdma_tx_segment, node);
+ desc->async_tx.phys = segment->phys;
+
+ /* For the last DMA_MEM_TO_DEV transfer, set EOP */
+ if (chan->direction == DMA_MEM_TO_DEV) {
+ segment->hw.control |= XILINX_MCDMA_BD_SOP;
+ segment = list_last_entry(&desc->segments,
+ struct xilinx_aximcdma_tx_segment,
+ node);
+ segment->hw.control |= XILINX_MCDMA_BD_EOP;
+ }
+
+ return &desc->async_tx;
+
+error:
+ xilinx_dma_free_tx_descriptor(chan, desc);
+
+ return NULL;
+}
/**
* xilinx_dma_prep_slave_sg - prepare descriptors for a DMA_SLAVE transaction
@@ -2422,12 +2827,16 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
if (of_device_is_compatible(node, "xlnx,axi-vdma-mm2s-channel") ||
of_device_is_compatible(node, "xlnx,axi-dma-mm2s-channel") ||
- of_device_is_compatible(node, "xlnx,axi-cdma-channel")) {
+ of_device_is_compatible(node, "xlnx,axi-cdma-channel") ||
+ of_device_is_compatible(node, "xlnx,axi-mcdma-mm2s-channel")) {
chan->direction = DMA_MEM_TO_DEV;
chan->id = chan_id;
chan->tdest = chan_id;
- chan->ctrl_offset = XILINX_DMA_MM2S_CTRL_OFFSET;
+ if (xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA)
+ chan->ctrl_offset = XILINX_MCDMA_MM2S_CTRL_OFFSET;
+ else
+ chan->ctrl_offset = XILINX_DMA_MM2S_CTRL_OFFSET;
if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
chan->desc_offset = XILINX_VDMA_MM2S_DESC_OFFSET;
chan->config.park = 1;
@@ -2439,7 +2848,9 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
} else if (of_device_is_compatible(node,
"xlnx,axi-vdma-s2mm-channel") ||
of_device_is_compatible(node,
- "xlnx,axi-dma-s2mm-channel")) {
+ "xlnx,axi-dma-s2mm-channel") ||
+ of_device_is_compatible(node,
+ "xlnx,axi-mcdma-s2mm-channel")) {
chan->direction = DMA_DEV_TO_MEM;
chan->id = chan_id;
chan->tdest = chan_id - xdev->nr_channels;
@@ -2451,7 +2862,11 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
XILINX_VDMA_ENABLE_VERTICAL_FLIP;
}
- chan->ctrl_offset = XILINX_DMA_S2MM_CTRL_OFFSET;
+ if (xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA)
+ chan->ctrl_offset = XILINX_MCDMA_S2MM_CTRL_OFFSET;
+ else
+ chan->ctrl_offset = XILINX_DMA_S2MM_CTRL_OFFSET;
+
if (xdev->dma_config->dmatype == XDMA_TYPE_VDMA) {
chan->desc_offset = XILINX_VDMA_S2MM_DESC_OFFSET;
chan->config.park = 1;
@@ -2467,7 +2882,7 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
/* Request the interrupt */
chan->irq = irq_of_parse_and_map(node, 0);
- err = request_irq(chan->irq, xilinx_dma_irq_handler, IRQF_SHARED,
+ err = request_irq(chan->irq, xdev->dma_config->irq_handler, IRQF_SHARED,
"xilinx-dma-controller", chan);
if (err) {
dev_err(xdev->dev, "unable to request IRQ %d\n", chan->irq);
@@ -2477,6 +2892,9 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
chan->start_transfer = xilinx_dma_start_transfer;
chan->stop_transfer = xilinx_dma_stop_transfer;
+ } else if (xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA) {
+ chan->start_transfer = xilinx_mcdma_start_transfer;
+ chan->stop_transfer = xilinx_dma_stop_transfer;
} else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
chan->start_transfer = xilinx_cdma_start_transfer;
chan->stop_transfer = xilinx_cdma_stop_transfer;
@@ -2557,22 +2975,31 @@ static struct dma_chan *of_dma_xilinx_xlate(struct of_phandle_args *dma_spec,
static const struct xilinx_dma_config axidma_config = {
.dmatype = XDMA_TYPE_AXIDMA,
.clk_init = axidma_clk_init,
+ .irq_handler = xilinx_dma_irq_handler,
};
+static const struct xilinx_dma_config aximcdma_config = {
+ .dmatype = XDMA_TYPE_AXIMCDMA,
+ .clk_init = axidma_clk_init,
+ .irq_handler = xilinx_mcdma_irq_handler,
+};
static const struct xilinx_dma_config axicdma_config = {
.dmatype = XDMA_TYPE_CDMA,
.clk_init = axicdma_clk_init,
+ .irq_handler = xilinx_dma_irq_handler,
};
static const struct xilinx_dma_config axivdma_config = {
.dmatype = XDMA_TYPE_VDMA,
.clk_init = axivdma_clk_init,
+ .irq_handler = xilinx_dma_irq_handler,
};
static const struct of_device_id xilinx_dma_of_ids[] = {
{ .compatible = "xlnx,axi-dma-1.00.a", .data = &axidma_config },
{ .compatible = "xlnx,axi-cdma-1.00.a", .data = &axicdma_config },
{ .compatible = "xlnx,axi-vdma-1.00.a", .data = &axivdma_config },
+ { .compatible = "xlnx,axi-mcdma-1.00.a", .data = &aximcdma_config },
{}
};
MODULE_DEVICE_TABLE(of, xilinx_dma_of_ids);
@@ -2684,6 +3111,8 @@ static int xilinx_dma_probe(struct platform_device *pdev)
} else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
dma_cap_set(DMA_MEMCPY, xdev->common.cap_mask);
xdev->common.device_prep_dma_memcpy = xilinx_cdma_prep_memcpy;
+ } else if (xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA) {
+ xdev->common.device_prep_slave_sg = xilinx_mcdma_prep_slave_sg;
} else {
xdev->common.device_prep_interleaved_dma =
xilinx_vdma_dma_prep_interleaved;
@@ -2719,6 +3148,8 @@ static int xilinx_dma_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "Xilinx AXI DMA Engine Driver Probed!!\n");
else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA)
dev_info(&pdev->dev, "Xilinx AXI CDMA Engine Driver Probed!!\n");
+ else if (xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA)
+ dev_info(&pdev->dev, "Xilinx AXI MCDMA Engine Driver Probed!!\n");
else
dev_info(&pdev->dev, "Xilinx AXI VDMA Engine Driver Probed!!\n");
^ permalink raw reply related
* [RFC,1/2] dt-bindings: dmaengine: xilinx_dma: Add binding for Xilinx MCDMA IP
From: Radhey Shyam Pandey @ 2018-07-31 17:46 UTC (permalink / raw)
To: vkoul, robh+dt, mark.rutland, michal.simek, dan.j.williams,
radhey.shyam.pandey, appanad, lars
Cc: dmaengine, devicetree, linux-arm-kernel, linux-kernel
Add devicetree binding for Xilinx AXI Multichannel Direct Memory Access
(AXI MCDMA) IP. The AXI MCDMA provides high-bandwidth direct memory
access between memory and AXI4-Stream target peripherals. The AXI MCDMA
core provides scatter-gather interface with multiple channel support.
Signed-off-by: Radhey Shyam Pandey <radhey.shyam.pandey@xilinx.com>
---
Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
index 174af2c..57bb02e 100644
--- a/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
+++ b/Documentation/devicetree/bindings/dma/xilinx/xilinx_dma.txt
@@ -11,9 +11,13 @@ is to receive from the device.
Xilinx AXI CDMA engine, it does transfers between memory-mapped source
address and a memory-mapped destination address.
+Xilinx AXI MCDMA engine, it does transfer between memory and AXI4 stream
+target devices. It can be configured to have up to 16 independent transmit
+and receive channels.
+
Required properties:
- compatible: Should be "xlnx,axi-vdma-1.00.a" or "xlnx,axi-dma-1.00.a" or
- "xlnx,axi-cdma-1.00.a""
+ "xlnx,axi-cdma-1.00.a" or "xlnx,axi-mcdma-1.00.a".
- #dma-cells: Should be <1>, see "dmas" property below
- reg: Should contain VDMA registers location and length.
- xlnx,addrwidth: Should be the vdma addressing size in bits(ex: 32 bits).
@@ -56,6 +60,8 @@ Required child node properties:
For CDMA: It should be "xlnx,axi-cdma-channel".
For AXIDMA: It should be either "xlnx,axi-dma-mm2s-channel" or
"xlnx,axi-dma-s2mm-channel".
+ For MCDMA: It should be either "xlnx,axi-mcdma-mm2s-channel" or
+ "xlnx,axi-mcdma-s2mm-channel".
- interrupts: Should contain per channel VDMA interrupts.
- xlnx,datawidth: Should contain the stream data width, take values
{32,64...1024}.
@@ -68,7 +74,7 @@ Optional child node properties for VDMA:
enabled/disabled in hardware.
- xlnx,enable-vert-flip: Tells vertical flip is
enabled/disabled in hardware(S2MM path).
-Optional child node properties for AXI DMA:
+Optional child node properties for AXI DMA and MCDMA:
-dma-channels: Number of dma channels in child node.
Example:
^ permalink raw reply related
* [RFC] dmaengine: Add metadat_ops for dma_async_tx_descriptor
From: Vinod Koul @ 2018-07-31 4:29 UTC (permalink / raw)
To: Peter Ujfalusi
Cc: radheys, vinod.koul, lars, michal.simek, linux-kernel, dmaengine,
dan.j.williams, appanad, linux-arm-kernel
On 30-07-18, 12:46, Peter Ujfalusi wrote:
> Vinod,
>
> On 2018-07-24 14:14, Vinod wrote:
> >>>> Clients must not mix the two way of handling the metadata.
> >>>> The set_len() is intended to tell the DMA driver the client provided
> >>>> metadata size (in MEM_TO_DEV case mostly).
> >>>>
> >>>> MEM_TO_DEV flow on client side:
> >>>> get_ptr()
> >>>> fill in the metadata to the pointer (not exceeding max_len)
> >>>> set_len() to tell the DMA driver the amount of valid bytes written
> >>>>
> >>>> DEV_TO_MEM flow on client side:
> >>>> In the completion callback, get_ptr()
> >>>> the metadata is payload_len bytes and can be accessed in the return pointer.
> >>>
> >>> I would think to unify this..
> >>
> >> I have tried it, but the attach mode and the pointer mode is hard to
> >> handle with a generic API.
> >> I will try to find a way to unify things in a sane way.
> >
> > Hmmm, looking from the description they will be for different methods,
> > so lets make them orthogonal and not allow driver to register both.
>
> I would allow DMA drivers to register both, but somehow enforce that
> clients are not mixing the two distinct way of dealing with the metadata.
>
> The reason for that is for example the attach mode is the simplest (I
> implemented it first and I have a client using it), but if the pointer
> mode is found to be more efficient and feasible for the DMA then the DMA
> driver can implement that mode and the client can move as well w/o
> breaking anything.
Sounds reasonable...
^ permalink raw reply
* dmaengine: sh: rcar-dmac: Should not stop the DMAC by rcar_dmac_sync_tcr()
From: Vinod Koul @ 2018-07-31 4:28 UTC (permalink / raw)
To: Yoshihiro Shimoda; +Cc: vinod.koul, dmaengine, linux-renesas-soc
On 25-07-18, 17:27, Yoshihiro Shimoda wrote:
> rcar_dmac_chan_get_residue() should not stop the DMAC, because
> the commit 538603c6026c ("dmaengine: sh: rcar-dmac: avoid to write
> CHCR.TE to 1 if TCR is set to 0") had fixed unexpected re-transferring
> issue. But it had caused the next issue which might stop the cyclic
> mode transferring. Thus, for example R-Car sound might be stopped
> suddenly.
>
> According to the commit 73a47bd0da66 ("dmaengine: rcar-dmac: use TCRB
> instead of TCR for residue"), the purpose of clearing CHCR.DE bit is
> flushing buffered data to calculate the exact residue.
>
> Such the "exact" residue had been required by sh-sci driver. sh-sci
> driver is calling dmaengine_pause() to stop transferring, and get
> "exact" residue. Otherwise, it might receive extra data during
> getting residue without pausing.
>
> In rx_timer_fn() of sh-sci driver:
> dmaengine_tx_status(); /* For checking roughly */
> dmaengine_pause();
> dmaengine_tx_status(); /* For getting residue */
> dmaengine_terminate_all();
>
> But, unfortunately the rcar-dmac driver didn't support dmaengine_pause()
> at that time. So, the sh-sci driver cannot get the "exact" residue
> without stopping the transferring, because rcar-dmac is buffering data
> inside.
>
> Because of these backgrounds, rcar-dmac had been cleared/set CHCR.DE
> bit in rcar_dmac_chan_get_residue() to synchronizing data and getting
> "exact" residue.
>
> However, rcar-dmac driver has rcar_dmac_chan_pause() now, and clearing
> CHCR.DE bit in rcar_dmac_chan_get_residue() doesn't need anymore.
> So, this patch removes the rcar_dmac_sync_tcr().
Applied, thanks
^ permalink raw reply
* [v3,1/4] dt-bindings: dmaengine: Add binding for Actions Semi Owl SoCs
From: Rob Herring @ 2018-07-30 23:10 UTC (permalink / raw)
To: Manivannan Sadhasivam
Cc: vkoul, dan.j.williams, afaerber, dmaengine, liuwei, 96boards,
devicetree, daniel.thompson, amit.kucheria, linux-arm-kernel,
linux-kernel, hzhang, bdong, manivannanece23, thomas.liau,
jeff.chen, pn, edgar.righi
On Thu, Jul 26, 2018 at 10:36:55AM +0530, Manivannan Sadhasivam wrote:
> Add devicetree binding for Actions Semi Owl SoCs DMA controller.
>
> Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
> ---
> .../devicetree/bindings/dma/owl-dma.txt | 47 +++++++++++++++++++
> 1 file changed, 47 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/dma/owl-dma.txt
Reviewed-by: Rob Herring <robh@kernel.org>
---
To unsubscribe from this list: send the line "unsubscribe dmaengine" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [v3,01/18] doc: dt-bindings: jz4780-dma: Update bindings to reflect driver changes
From: Paul Cercueil @ 2018-07-30 21:13 UTC (permalink / raw)
To: Rob Herring
Cc: Vinod Koul, Mark Rutland, Ralf Baechle, Paul Burton, James Hogan,
Zubair Lutfullah Kakakhel, Mathieu Malaterre, Daniel Silsby,
dmaengine, devicetree, linux-kernel, linux-mips
Hi,
Le mer. 25 juil. 2018 à 1:35, Rob Herring <robh@kernel.org> a écrit :
> On Sat, Jul 21, 2018 at 01:06:26PM +0200, Paul Cercueil wrote:
>> The driver is now compatible with four SoCs: JZ4780, JZ4770,
>> JZ4725B and
>> JZ4740.
>
> What the driver supports is irrelevant to the binding.
That's just informative. But I can remove it, no problem.
>>
>> Besides, it now expects the devicetree to supply a second memory
>> resource. This resource is mandatory on the newly supported SoCs.
>> For the JZ4780, new devicetree code must also provide it, although
>> the
>> driver is still compatible with older devicetree binaries.
>>
>> Signed-off-by: Paul Cercueil <paul@crapouillou.net>
>> Tested-by: Mathieu Malaterre <malat@debian.org>
>> ---
>> Documentation/devicetree/bindings/dma/jz4780-dma.txt | 14
>> ++++++++++----
>> 1 file changed, 10 insertions(+), 4 deletions(-)
>>
>> v2: New patch in this series; regroups the changes made to the
>> jz4780-dma.txt doc file in the previous version of the patchset.
>>
>> v3: Updated example to comply with devicetree specification
>>
>> diff --git a/Documentation/devicetree/bindings/dma/jz4780-dma.txt
>> b/Documentation/devicetree/bindings/dma/jz4780-dma.txt
>> index f25feee62b15..14f33305e194 100644
>> --- a/Documentation/devicetree/bindings/dma/jz4780-dma.txt
>> +++ b/Documentation/devicetree/bindings/dma/jz4780-dma.txt
>> @@ -2,8 +2,13 @@
>>
>> Required properties:
>>
>> -- compatible: Should be "ingenic,jz4780-dma"
>> -- reg: Should contain the DMA controller registers location and
>> length.
>> +- compatible: Should be one of:
>> + * ingenic,jz4740-dma
>> + * ingenic,jz4725b-dma
>> + * ingenic,jz4770-dma
>> + * ingenic,jz4780-dma
>
> So none of these are compatible with each other? It should be one
> valid
> combination per line.
That's correct - they are all slightly different.
>> +- reg: Should contain the DMA channel registers location and
>> length, followed
>> + by the DMA controller registers location and length.
>> - interrupts: Should contain the interrupt specifier of the DMA
>> controller.
>> - interrupt-parent: Should be the phandle of the interrupt
>> controller that
>> - clocks: Should contain a clock specifier for the JZ4780 PDMA
>> clock.
>> @@ -20,9 +25,10 @@ Optional properties:
>>
>> Example:
>>
>> -dma: dma@13420000 {
>> +dma: dma-controller@13420000 {
>> compatible = "ingenic,jz4780-dma";
>> - reg = <0x13420000 0x10000>;
>> + reg = <0x13420000 0x400
>> + 0x13421000 0x40>;
>>
>> interrupt-parent = <&intc>;
>> interrupts = <10>;
>> --
>> 2.11.0
>>
---
To unsubscribe from this list: send the line "unsubscribe dmaengine" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [RFC] dmaengine: Add metadat_ops for dma_async_tx_descriptor
From: Peter Ujfalusi @ 2018-07-30 9:46 UTC (permalink / raw)
To: Vinod
Cc: radheys, vinod.koul, lars, michal.simek, linux-kernel, dmaengine,
dan.j.williams, appanad, linux-arm-kernel
Vinod,
On 2018-07-24 14:14, Vinod wrote:
>>>> Clients must not mix the two way of handling the metadata.
>>>> The set_len() is intended to tell the DMA driver the client provided
>>>> metadata size (in MEM_TO_DEV case mostly).
>>>>
>>>> MEM_TO_DEV flow on client side:
>>>> get_ptr()
>>>> fill in the metadata to the pointer (not exceeding max_len)
>>>> set_len() to tell the DMA driver the amount of valid bytes written
>>>>
>>>> DEV_TO_MEM flow on client side:
>>>> In the completion callback, get_ptr()
>>>> the metadata is payload_len bytes and can be accessed in the return pointer.
>>>
>>> I would think to unify this..
>>
>> I have tried it, but the attach mode and the pointer mode is hard to
>> handle with a generic API.
>> I will try to find a way to unify things in a sane way.
>
> Hmmm, looking from the description they will be for different methods,
> so lets make them orthogonal and not allow driver to register both.
I would allow DMA drivers to register both, but somehow enforce that
clients are not mixing the two distinct way of dealing with the metadata.
The reason for that is for example the attach mode is the simplest (I
implemented it first and I have a client using it), but if the pointer
mode is found to be more efficient and feasible for the DMA then the DMA
driver can implement that mode and the client can move as well w/o
breaking anything.
>
>>
>> I have moved the metadata_ops to dma_async_tx_descriptor to emphasize
>> that it is per descriptor setting:
>> https://github.com/omap-audio/linux-audio/commit/02e095d1320a4bb3ae281ddb208ce82ead746f00#diff-92c0a79f414dc3be9dfc67a969c0dd71
>>
>>
>>>> BTW: The driver which is going to need this is now accessible in public:
>>>> https://git.ti.com/ti-linux-kernel/ti-linux-kernel/trees/ti-linux-4.14.y/drivers/dma/ti
>>>>
>>>> or in my wip tree:
>>>> https://github.com/omap-audio/linux-audio/tree/peter/ti-linux-4.14.y/wip/drivers/dma/ti
>>>>
>>>> prefixed with k3-*
>>>>
>>
>> - Péter
>>
>> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
>> Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
>
- Péter
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
---
To unsubscribe from this list: send the line "unsubscribe dmaengine" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox