aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>2013-01-16 08:48:50 -0500
committerVinod Koul <vinod.koul@intel.com>2013-01-20 23:49:21 -0500
commitf8122a82d2eae8ef42de48829deed0ca9d9e1f17 (patch)
treeade059660ab99a330c93dffa90e7e4f4972270af /drivers/dma
parent855372c013bbad8369223f7c75242bd3c94f9345 (diff)
dw_dmac: allocate dma descriptors from DMA_COHERENT memory
Currently descriptors are allocated from normal cacheable memory and that slows down filling the descriptors, as we need to call cache_coherency routines afterwards. It would be better to allocate memory for these descriptors from DMA_COHERENT memory. This would make code much cleaner too. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com> Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/dw_dmac.c81
-rw-r--r--drivers/dma/dw_dmac_regs.h1
2 files changed, 18 insertions, 64 deletions
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
index 28d5f01c350c..76301c4ba1ad 100644
--- a/drivers/dma/dw_dmac.c
+++ b/drivers/dma/dw_dmac.c
@@ -14,6 +14,7 @@
14#include <linux/delay.h> 14#include <linux/delay.h>
15#include <linux/dmaengine.h> 15#include <linux/dmaengine.h>
16#include <linux/dma-mapping.h> 16#include <linux/dma-mapping.h>
17#include <linux/dmapool.h>
17#include <linux/init.h> 18#include <linux/init.h>
18#include <linux/interrupt.h> 19#include <linux/interrupt.h>
19#include <linux/io.h> 20#include <linux/io.h>
@@ -91,14 +92,6 @@ static inline unsigned int dwc_get_data_width(struct dma_chan *chan, int master)
91 92
92/*----------------------------------------------------------------------*/ 93/*----------------------------------------------------------------------*/
93 94
94/*
95 * Because we're not relying on writeback from the controller (it may not
96 * even be configured into the core!) we don't need to use dma_pool. These
97 * descriptors -- and associated data -- are cacheable. We do need to make
98 * sure their dcache entries are written back before handing them off to
99 * the controller, though.
100 */
101
102static struct device *chan2dev(struct dma_chan *chan) 95static struct device *chan2dev(struct dma_chan *chan)
103{ 96{
104 return &chan->dev->device; 97 return &chan->dev->device;
@@ -137,19 +130,6 @@ static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc)
137 return ret; 130 return ret;
138} 131}
139 132
140static void dwc_sync_desc_for_cpu(struct dw_dma_chan *dwc, struct dw_desc *desc)
141{
142 struct dw_desc *child;
143
144 list_for_each_entry(child, &desc->tx_list, desc_node)
145 dma_sync_single_for_cpu(chan2parent(&dwc->chan),
146 child->txd.phys, sizeof(child->lli),
147 DMA_TO_DEVICE);
148 dma_sync_single_for_cpu(chan2parent(&dwc->chan),
149 desc->txd.phys, sizeof(desc->lli),
150 DMA_TO_DEVICE);
151}
152
153/* 133/*
154 * Move a descriptor, including any children, to the free list. 134 * Move a descriptor, including any children, to the free list.
155 * `desc' must not be on any lists. 135 * `desc' must not be on any lists.
@@ -161,8 +141,6 @@ static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc)
161 if (desc) { 141 if (desc) {
162 struct dw_desc *child; 142 struct dw_desc *child;
163 143
164 dwc_sync_desc_for_cpu(dwc, desc);
165
166 spin_lock_irqsave(&dwc->lock, flags); 144 spin_lock_irqsave(&dwc->lock, flags);
167 list_for_each_entry(child, &desc->tx_list, desc_node) 145 list_for_each_entry(child, &desc->tx_list, desc_node)
168 dev_vdbg(chan2dev(&dwc->chan), 146 dev_vdbg(chan2dev(&dwc->chan),
@@ -335,8 +313,6 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc,
335 param = txd->callback_param; 313 param = txd->callback_param;
336 } 314 }
337 315
338 dwc_sync_desc_for_cpu(dwc, desc);
339
340 /* async_tx_ack */ 316 /* async_tx_ack */
341 list_for_each_entry(child, &desc->tx_list, desc_node) 317 list_for_each_entry(child, &desc->tx_list, desc_node)
342 async_tx_ack(&child->txd); 318 async_tx_ack(&child->txd);
@@ -770,25 +746,17 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
770 first = desc; 746 first = desc;
771 } else { 747 } else {
772 prev->lli.llp = desc->txd.phys; 748 prev->lli.llp = desc->txd.phys;
773 dma_sync_single_for_device(chan2parent(chan),
774 prev->txd.phys, sizeof(prev->lli),
775 DMA_TO_DEVICE);
776 list_add_tail(&desc->desc_node, 749 list_add_tail(&desc->desc_node,
777 &first->tx_list); 750 &first->tx_list);
778 } 751 }
779 prev = desc; 752 prev = desc;
780 } 753 }
781 754
782
783 if (flags & DMA_PREP_INTERRUPT) 755 if (flags & DMA_PREP_INTERRUPT)
784 /* Trigger interrupt after last block */ 756 /* Trigger interrupt after last block */
785 prev->lli.ctllo |= DWC_CTLL_INT_EN; 757 prev->lli.ctllo |= DWC_CTLL_INT_EN;
786 758
787 prev->lli.llp = 0; 759 prev->lli.llp = 0;
788 dma_sync_single_for_device(chan2parent(chan),
789 prev->txd.phys, sizeof(prev->lli),
790 DMA_TO_DEVICE);
791
792 first->txd.flags = flags; 760 first->txd.flags = flags;
793 first->len = len; 761 first->len = len;
794 762
@@ -876,10 +844,6 @@ slave_sg_todev_fill_desc:
876 first = desc; 844 first = desc;
877 } else { 845 } else {
878 prev->lli.llp = desc->txd.phys; 846 prev->lli.llp = desc->txd.phys;
879 dma_sync_single_for_device(chan2parent(chan),
880 prev->txd.phys,
881 sizeof(prev->lli),
882 DMA_TO_DEVICE);
883 list_add_tail(&desc->desc_node, 847 list_add_tail(&desc->desc_node,
884 &first->tx_list); 848 &first->tx_list);
885 } 849 }
@@ -938,10 +902,6 @@ slave_sg_fromdev_fill_desc:
938 first = desc; 902 first = desc;
939 } else { 903 } else {
940 prev->lli.llp = desc->txd.phys; 904 prev->lli.llp = desc->txd.phys;
941 dma_sync_single_for_device(chan2parent(chan),
942 prev->txd.phys,
943 sizeof(prev->lli),
944 DMA_TO_DEVICE);
945 list_add_tail(&desc->desc_node, 905 list_add_tail(&desc->desc_node,
946 &first->tx_list); 906 &first->tx_list);
947 } 907 }
@@ -961,10 +921,6 @@ slave_sg_fromdev_fill_desc:
961 prev->lli.ctllo |= DWC_CTLL_INT_EN; 921 prev->lli.ctllo |= DWC_CTLL_INT_EN;
962 922
963 prev->lli.llp = 0; 923 prev->lli.llp = 0;
964 dma_sync_single_for_device(chan2parent(chan),
965 prev->txd.phys, sizeof(prev->lli),
966 DMA_TO_DEVICE);
967
968 first->len = total_len; 924 first->len = total_len;
969 925
970 return &first->txd; 926 return &first->txd;
@@ -1118,7 +1074,6 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
1118 struct dw_desc *desc; 1074 struct dw_desc *desc;
1119 int i; 1075 int i;
1120 unsigned long flags; 1076 unsigned long flags;
1121 int ret;
1122 1077
1123 dev_vdbg(chan2dev(chan), "%s\n", __func__); 1078 dev_vdbg(chan2dev(chan), "%s\n", __func__);
1124 1079
@@ -1139,21 +1094,21 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
1139 spin_lock_irqsave(&dwc->lock, flags); 1094 spin_lock_irqsave(&dwc->lock, flags);
1140 i = dwc->descs_allocated; 1095 i = dwc->descs_allocated;
1141 while (dwc->descs_allocated < NR_DESCS_PER_CHANNEL) { 1096 while (dwc->descs_allocated < NR_DESCS_PER_CHANNEL) {
1097 dma_addr_t phys;
1098
1142 spin_unlock_irqrestore(&dwc->lock, flags); 1099 spin_unlock_irqrestore(&dwc->lock, flags);
1143 1100
1144 desc = kzalloc(sizeof(struct dw_desc), GFP_KERNEL); 1101 desc = dma_pool_alloc(dw->desc_pool, GFP_ATOMIC, &phys);
1145 if (!desc) 1102 if (!desc)
1146 goto err_desc_alloc; 1103 goto err_desc_alloc;
1147 1104
1105 memset(desc, 0, sizeof(struct dw_desc));
1106
1148 INIT_LIST_HEAD(&desc->tx_list); 1107 INIT_LIST_HEAD(&desc->tx_list);
1149 dma_async_tx_descriptor_init(&desc->txd, chan); 1108 dma_async_tx_descriptor_init(&desc->txd, chan);
1150 desc->txd.tx_submit = dwc_tx_submit; 1109 desc->txd.tx_submit = dwc_tx_submit;
1151 desc->txd.flags = DMA_CTRL_ACK; 1110 desc->txd.flags = DMA_CTRL_ACK;
1152 desc->txd.phys = dma_map_single(chan2parent(chan), &desc->lli, 1111 desc->txd.phys = phys;
1153 sizeof(desc->lli), DMA_TO_DEVICE);
1154 ret = dma_mapping_error(chan2parent(chan), desc->txd.phys);
1155 if (ret)
1156 goto err_desc_alloc;
1157 1112
1158 dwc_desc_put(dwc, desc); 1113 dwc_desc_put(dwc, desc);
1159 1114
@@ -1168,8 +1123,6 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
1168 return i; 1123 return i;
1169 1124
1170err_desc_alloc: 1125err_desc_alloc:
1171 kfree(desc);
1172
1173 dev_info(chan2dev(chan), "only allocated %d descriptors\n", i); 1126 dev_info(chan2dev(chan), "only allocated %d descriptors\n", i);
1174 1127
1175 return i; 1128 return i;
@@ -1204,9 +1157,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
1204 1157
1205 list_for_each_entry_safe(desc, _desc, &list, desc_node) { 1158 list_for_each_entry_safe(desc, _desc, &list, desc_node) {
1206 dev_vdbg(chan2dev(chan), " freeing descriptor %p\n", desc); 1159 dev_vdbg(chan2dev(chan), " freeing descriptor %p\n", desc);
1207 dma_unmap_single(chan2parent(chan), desc->txd.phys, 1160 dma_pool_free(dw->desc_pool, desc, desc->txd.phys);
1208 sizeof(desc->lli), DMA_TO_DEVICE);
1209 kfree(desc);
1210 } 1161 }
1211 1162
1212 dev_vdbg(chan2dev(chan), "%s: done\n", __func__); 1163 dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
@@ -1451,20 +1402,14 @@ struct dw_cyclic_desc *dw_dma_cyclic_prep(struct dma_chan *chan,
1451 desc->lli.ctlhi = (period_len >> reg_width); 1402 desc->lli.ctlhi = (period_len >> reg_width);
1452 cdesc->desc[i] = desc; 1403 cdesc->desc[i] = desc;
1453 1404
1454 if (last) { 1405 if (last)
1455 last->lli.llp = desc->txd.phys; 1406 last->lli.llp = desc->txd.phys;
1456 dma_sync_single_for_device(chan2parent(chan),
1457 last->txd.phys, sizeof(last->lli),
1458 DMA_TO_DEVICE);
1459 }
1460 1407
1461 last = desc; 1408 last = desc;
1462 } 1409 }
1463 1410
1464 /* lets make a cyclic list */ 1411 /* lets make a cyclic list */
1465 last->lli.llp = cdesc->desc[0]->txd.phys; 1412 last->lli.llp = cdesc->desc[0]->txd.phys;
1466 dma_sync_single_for_device(chan2parent(chan), last->txd.phys,
1467 sizeof(last->lli), DMA_TO_DEVICE);
1468 1413
1469 dev_dbg(chan2dev(&dwc->chan), "cyclic prepared buf 0x%llx len %zu " 1414 dev_dbg(chan2dev(&dwc->chan), "cyclic prepared buf 0x%llx len %zu "
1470 "period %zu periods %d\n", (unsigned long long)buf_addr, 1415 "period %zu periods %d\n", (unsigned long long)buf_addr,
@@ -1722,6 +1667,14 @@ static int dw_probe(struct platform_device *pdev)
1722 1667
1723 platform_set_drvdata(pdev, dw); 1668 platform_set_drvdata(pdev, dw);
1724 1669
1670 /* create a pool of consistent memory blocks for hardware descriptors */
1671 dw->desc_pool = dmam_pool_create("dw_dmac_desc_pool", &pdev->dev,
1672 sizeof(struct dw_desc), 4, 0);
1673 if (!dw->desc_pool) {
1674 dev_err(&pdev->dev, "No memory for descriptors dma pool\n");
1675 return -ENOMEM;
1676 }
1677
1725 tasklet_init(&dw->tasklet, dw_dma_tasklet, (unsigned long)dw); 1678 tasklet_init(&dw->tasklet, dw_dma_tasklet, (unsigned long)dw);
1726 1679
1727 INIT_LIST_HEAD(&dw->dma.channels); 1680 INIT_LIST_HEAD(&dw->dma.channels);
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
index 577f2dd35882..fef296de4af1 100644
--- a/drivers/dma/dw_dmac_regs.h
+++ b/drivers/dma/dw_dmac_regs.h
@@ -235,6 +235,7 @@ static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan)
235struct dw_dma { 235struct dw_dma {
236 struct dma_device dma; 236 struct dma_device dma;
237 void __iomem *regs; 237 void __iomem *regs;
238 struct dma_pool *desc_pool;
238 struct tasklet_struct tasklet; 239 struct tasklet_struct tasklet;
239 struct clk *clk; 240 struct clk *clk;
240 241