diff options
author | NeilBrown <neilb@suse.de> | 2009-09-23 04:31:11 -0400 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2009-09-23 04:31:11 -0400 |
commit | 4b3df5668c8ebaebd8d66a5a94374be3e3b2ef0c (patch) | |
tree | 51a231742e211143f5845edf4b09d1712dcd2771 /drivers/dma/dw_dmac.c | |
parent | 1ef04fefe2241087d9db7e9615c3f11b516e36cf (diff) | |
parent | 1f6672d44c1ae7408b43c06170ec34eb0a0e9b9f (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/async_tx into for-linus
Diffstat (limited to 'drivers/dma/dw_dmac.c')
-rw-r--r-- | drivers/dma/dw_dmac.c | 50 |
1 files changed, 29 insertions, 21 deletions
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index 933c143b6a7..2eea823516a 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c | |||
@@ -116,7 +116,7 @@ static void dwc_sync_desc_for_cpu(struct dw_dma_chan *dwc, struct dw_desc *desc) | |||
116 | { | 116 | { |
117 | struct dw_desc *child; | 117 | struct dw_desc *child; |
118 | 118 | ||
119 | list_for_each_entry(child, &desc->txd.tx_list, desc_node) | 119 | list_for_each_entry(child, &desc->tx_list, desc_node) |
120 | dma_sync_single_for_cpu(chan2parent(&dwc->chan), | 120 | dma_sync_single_for_cpu(chan2parent(&dwc->chan), |
121 | child->txd.phys, sizeof(child->lli), | 121 | child->txd.phys, sizeof(child->lli), |
122 | DMA_TO_DEVICE); | 122 | DMA_TO_DEVICE); |
@@ -137,11 +137,11 @@ static void dwc_desc_put(struct dw_dma_chan *dwc, struct dw_desc *desc) | |||
137 | dwc_sync_desc_for_cpu(dwc, desc); | 137 | dwc_sync_desc_for_cpu(dwc, desc); |
138 | 138 | ||
139 | spin_lock_bh(&dwc->lock); | 139 | spin_lock_bh(&dwc->lock); |
140 | list_for_each_entry(child, &desc->txd.tx_list, desc_node) | 140 | list_for_each_entry(child, &desc->tx_list, desc_node) |
141 | dev_vdbg(chan2dev(&dwc->chan), | 141 | dev_vdbg(chan2dev(&dwc->chan), |
142 | "moving child desc %p to freelist\n", | 142 | "moving child desc %p to freelist\n", |
143 | child); | 143 | child); |
144 | list_splice_init(&desc->txd.tx_list, &dwc->free_list); | 144 | list_splice_init(&desc->tx_list, &dwc->free_list); |
145 | dev_vdbg(chan2dev(&dwc->chan), "moving desc %p to freelist\n", desc); | 145 | dev_vdbg(chan2dev(&dwc->chan), "moving desc %p to freelist\n", desc); |
146 | list_add(&desc->desc_node, &dwc->free_list); | 146 | list_add(&desc->desc_node, &dwc->free_list); |
147 | spin_unlock_bh(&dwc->lock); | 147 | spin_unlock_bh(&dwc->lock); |
@@ -209,19 +209,28 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc) | |||
209 | param = txd->callback_param; | 209 | param = txd->callback_param; |
210 | 210 | ||
211 | dwc_sync_desc_for_cpu(dwc, desc); | 211 | dwc_sync_desc_for_cpu(dwc, desc); |
212 | list_splice_init(&txd->tx_list, &dwc->free_list); | 212 | list_splice_init(&desc->tx_list, &dwc->free_list); |
213 | list_move(&desc->desc_node, &dwc->free_list); | 213 | list_move(&desc->desc_node, &dwc->free_list); |
214 | 214 | ||
215 | /* | 215 | if (!dwc->chan.private) { |
216 | * We use dma_unmap_page() regardless of how the buffers were | 216 | struct device *parent = chan2parent(&dwc->chan); |
217 | * mapped before they were submitted... | 217 | if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) { |
218 | */ | 218 | if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE) |
219 | if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) | 219 | dma_unmap_single(parent, desc->lli.dar, |
220 | dma_unmap_page(chan2parent(&dwc->chan), desc->lli.dar, | 220 | desc->len, DMA_FROM_DEVICE); |
221 | desc->len, DMA_FROM_DEVICE); | 221 | else |
222 | if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) | 222 | dma_unmap_page(parent, desc->lli.dar, |
223 | dma_unmap_page(chan2parent(&dwc->chan), desc->lli.sar, | 223 | desc->len, DMA_FROM_DEVICE); |
224 | desc->len, DMA_TO_DEVICE); | 224 | } |
225 | if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) { | ||
226 | if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE) | ||
227 | dma_unmap_single(parent, desc->lli.sar, | ||
228 | desc->len, DMA_TO_DEVICE); | ||
229 | else | ||
230 | dma_unmap_page(parent, desc->lli.sar, | ||
231 | desc->len, DMA_TO_DEVICE); | ||
232 | } | ||
233 | } | ||
225 | 234 | ||
226 | /* | 235 | /* |
227 | * The API requires that no submissions are done from a | 236 | * The API requires that no submissions are done from a |
@@ -289,7 +298,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) | |||
289 | /* This one is currently in progress */ | 298 | /* This one is currently in progress */ |
290 | return; | 299 | return; |
291 | 300 | ||
292 | list_for_each_entry(child, &desc->txd.tx_list, desc_node) | 301 | list_for_each_entry(child, &desc->tx_list, desc_node) |
293 | if (child->lli.llp == llp) | 302 | if (child->lli.llp == llp) |
294 | /* Currently in progress */ | 303 | /* Currently in progress */ |
295 | return; | 304 | return; |
@@ -356,7 +365,7 @@ static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc) | |||
356 | dev_printk(KERN_CRIT, chan2dev(&dwc->chan), | 365 | dev_printk(KERN_CRIT, chan2dev(&dwc->chan), |
357 | " cookie: %d\n", bad_desc->txd.cookie); | 366 | " cookie: %d\n", bad_desc->txd.cookie); |
358 | dwc_dump_lli(dwc, &bad_desc->lli); | 367 | dwc_dump_lli(dwc, &bad_desc->lli); |
359 | list_for_each_entry(child, &bad_desc->txd.tx_list, desc_node) | 368 | list_for_each_entry(child, &bad_desc->tx_list, desc_node) |
360 | dwc_dump_lli(dwc, &child->lli); | 369 | dwc_dump_lli(dwc, &child->lli); |
361 | 370 | ||
362 | /* Pretend the descriptor completed successfully */ | 371 | /* Pretend the descriptor completed successfully */ |
@@ -608,7 +617,7 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, | |||
608 | prev->txd.phys, sizeof(prev->lli), | 617 | prev->txd.phys, sizeof(prev->lli), |
609 | DMA_TO_DEVICE); | 618 | DMA_TO_DEVICE); |
610 | list_add_tail(&desc->desc_node, | 619 | list_add_tail(&desc->desc_node, |
611 | &first->txd.tx_list); | 620 | &first->tx_list); |
612 | } | 621 | } |
613 | prev = desc; | 622 | prev = desc; |
614 | } | 623 | } |
@@ -658,8 +667,6 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
658 | reg_width = dws->reg_width; | 667 | reg_width = dws->reg_width; |
659 | prev = first = NULL; | 668 | prev = first = NULL; |
660 | 669 | ||
661 | sg_len = dma_map_sg(chan2parent(chan), sgl, sg_len, direction); | ||
662 | |||
663 | switch (direction) { | 670 | switch (direction) { |
664 | case DMA_TO_DEVICE: | 671 | case DMA_TO_DEVICE: |
665 | ctllo = (DWC_DEFAULT_CTLLO | 672 | ctllo = (DWC_DEFAULT_CTLLO |
@@ -700,7 +707,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
700 | sizeof(prev->lli), | 707 | sizeof(prev->lli), |
701 | DMA_TO_DEVICE); | 708 | DMA_TO_DEVICE); |
702 | list_add_tail(&desc->desc_node, | 709 | list_add_tail(&desc->desc_node, |
703 | &first->txd.tx_list); | 710 | &first->tx_list); |
704 | } | 711 | } |
705 | prev = desc; | 712 | prev = desc; |
706 | total_len += len; | 713 | total_len += len; |
@@ -746,7 +753,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | |||
746 | sizeof(prev->lli), | 753 | sizeof(prev->lli), |
747 | DMA_TO_DEVICE); | 754 | DMA_TO_DEVICE); |
748 | list_add_tail(&desc->desc_node, | 755 | list_add_tail(&desc->desc_node, |
749 | &first->txd.tx_list); | 756 | &first->tx_list); |
750 | } | 757 | } |
751 | prev = desc; | 758 | prev = desc; |
752 | total_len += len; | 759 | total_len += len; |
@@ -902,6 +909,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) | |||
902 | break; | 909 | break; |
903 | } | 910 | } |
904 | 911 | ||
912 | INIT_LIST_HEAD(&desc->tx_list); | ||
905 | dma_async_tx_descriptor_init(&desc->txd, chan); | 913 | dma_async_tx_descriptor_init(&desc->txd, chan); |
906 | desc->txd.tx_submit = dwc_tx_submit; | 914 | desc->txd.tx_submit = dwc_tx_submit; |
907 | desc->txd.flags = DMA_CTRL_ACK; | 915 | desc->txd.flags = DMA_CTRL_ACK; |