diff options
Diffstat (limited to 'drivers/dma/iop-adma.c')
-rw-r--r-- | drivers/dma/iop-adma.c | 53 |
1 files changed, 36 insertions, 17 deletions
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index 0ec0f431e6a1..85bfeba4d85e 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c | |||
@@ -82,17 +82,24 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc, | |||
82 | struct device *dev = | 82 | struct device *dev = |
83 | &iop_chan->device->pdev->dev; | 83 | &iop_chan->device->pdev->dev; |
84 | u32 len = unmap->unmap_len; | 84 | u32 len = unmap->unmap_len; |
85 | u32 src_cnt = unmap->unmap_src_cnt; | 85 | enum dma_ctrl_flags flags = desc->async_tx.flags; |
86 | dma_addr_t addr = iop_desc_get_dest_addr(unmap, | 86 | u32 src_cnt; |
87 | iop_chan); | 87 | dma_addr_t addr; |
88 | 88 | ||
89 | dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE); | 89 | if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) { |
90 | while (src_cnt--) { | 90 | addr = iop_desc_get_dest_addr(unmap, iop_chan); |
91 | addr = iop_desc_get_src_addr(unmap, | 91 | dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE); |
92 | iop_chan, | 92 | } |
93 | src_cnt); | 93 | |
94 | dma_unmap_page(dev, addr, len, | 94 | if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) { |
95 | DMA_TO_DEVICE); | 95 | src_cnt = unmap->unmap_src_cnt; |
96 | while (src_cnt--) { | ||
97 | addr = iop_desc_get_src_addr(unmap, | ||
98 | iop_chan, | ||
99 | src_cnt); | ||
100 | dma_unmap_page(dev, addr, len, | ||
101 | DMA_TO_DEVICE); | ||
102 | } | ||
96 | } | 103 | } |
97 | desc->group_head = NULL; | 104 | desc->group_head = NULL; |
98 | } | 105 | } |
@@ -366,8 +373,8 @@ retry: | |||
366 | if (!retry++) | 373 | if (!retry++) |
367 | goto retry; | 374 | goto retry; |
368 | 375 | ||
369 | /* try to free some slots if the allocation fails */ | 376 | /* perform direct reclaim if the allocation fails */ |
370 | tasklet_schedule(&iop_chan->irq_tasklet); | 377 | __iop_adma_slot_cleanup(iop_chan); |
371 | 378 | ||
372 | return NULL; | 379 | return NULL; |
373 | } | 380 | } |
@@ -443,8 +450,18 @@ iop_adma_tx_submit(struct dma_async_tx_descriptor *tx) | |||
443 | static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan); | 450 | static void iop_chan_start_null_memcpy(struct iop_adma_chan *iop_chan); |
444 | static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan); | 451 | static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan); |
445 | 452 | ||
446 | /* returns the number of allocated descriptors */ | 453 | /** |
447 | static int iop_adma_alloc_chan_resources(struct dma_chan *chan) | 454 | * iop_adma_alloc_chan_resources - returns the number of allocated descriptors |
455 | * @chan - allocate descriptor resources for this channel | ||
456 | * @client - current client requesting the channel be ready for requests | ||
457 | * | ||
458 | * Note: We keep the slots for 1 operation on iop_chan->chain at all times. To | ||
459 | * avoid deadlock, via async_xor, num_descs_in_pool must at a minimum be | ||
460 | * greater than 2x the number slots needed to satisfy a device->max_xor | ||
461 | * request. | ||
462 | * */ | ||
463 | static int iop_adma_alloc_chan_resources(struct dma_chan *chan, | ||
464 | struct dma_client *client) | ||
448 | { | 465 | { |
449 | char *hw_desc; | 466 | char *hw_desc; |
450 | int idx; | 467 | int idx; |
@@ -838,7 +855,7 @@ static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device) | |||
838 | dma_chan = container_of(device->common.channels.next, | 855 | dma_chan = container_of(device->common.channels.next, |
839 | struct dma_chan, | 856 | struct dma_chan, |
840 | device_node); | 857 | device_node); |
841 | if (iop_adma_alloc_chan_resources(dma_chan) < 1) { | 858 | if (iop_adma_alloc_chan_resources(dma_chan, NULL) < 1) { |
842 | err = -ENODEV; | 859 | err = -ENODEV; |
843 | goto out; | 860 | goto out; |
844 | } | 861 | } |
@@ -936,7 +953,7 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device) | |||
936 | dma_chan = container_of(device->common.channels.next, | 953 | dma_chan = container_of(device->common.channels.next, |
937 | struct dma_chan, | 954 | struct dma_chan, |
938 | device_node); | 955 | device_node); |
939 | if (iop_adma_alloc_chan_resources(dma_chan) < 1) { | 956 | if (iop_adma_alloc_chan_resources(dma_chan, NULL) < 1) { |
940 | err = -ENODEV; | 957 | err = -ENODEV; |
941 | goto out; | 958 | goto out; |
942 | } | 959 | } |
@@ -1387,6 +1404,8 @@ static void iop_chan_start_null_xor(struct iop_adma_chan *iop_chan) | |||
1387 | spin_unlock_bh(&iop_chan->lock); | 1404 | spin_unlock_bh(&iop_chan->lock); |
1388 | } | 1405 | } |
1389 | 1406 | ||
1407 | MODULE_ALIAS("platform:iop-adma"); | ||
1408 | |||
1390 | static struct platform_driver iop_adma_driver = { | 1409 | static struct platform_driver iop_adma_driver = { |
1391 | .probe = iop_adma_probe, | 1410 | .probe = iop_adma_probe, |
1392 | .remove = iop_adma_remove, | 1411 | .remove = iop_adma_remove, |