Merge branch 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/async_tx
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 18 Dec 2008 20:05:53 +0000 (12:05 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 18 Dec 2008 20:05:53 +0000 (12:05 -0800)
* 'fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/djbw/async_tx:
  async_xor: dma_map destination DMA_BIDIRECTIONAL
  dmaengine: protect 'id' from concurrent registrations
  ioat: wait for self-test completion

crypto/async_tx/async_xor.c
drivers/dma/dmaengine.c
drivers/dma/ioat_dma.c
drivers/dma/iop-adma.c
drivers/dma/mv_xor.c

index c029d3eb9ef0a76ed248deb4a40e47511ba12afe..595b78672b36ad90e27cf50ed28126bb43970fb5 100644 (file)
@@ -53,10 +53,17 @@ do_async_xor(struct dma_chan *chan, struct page *dest, struct page **src_list,
        int xor_src_cnt;
        dma_addr_t dma_dest;
 
-       dma_dest = dma_map_page(dma->dev, dest, offset, len, DMA_FROM_DEVICE);
-       for (i = 0; i < src_cnt; i++)
+       /* map the dest bidrectional in case it is re-used as a source */
+       dma_dest = dma_map_page(dma->dev, dest, offset, len, DMA_BIDIRECTIONAL);
+       for (i = 0; i < src_cnt; i++) {
+               /* only map the dest once */
+               if (unlikely(src_list[i] == dest)) {
+                       dma_src[i] = dma_dest;
+                       continue;
+               }
                dma_src[i] = dma_map_page(dma->dev, src_list[i], offset,
                                          len, DMA_TO_DEVICE);
+       }
 
        while (src_cnt) {
                async_flags = flags;
index 5317e08221ecb2a34e699c77bac4f72a505f59e6..657996517374f30f51f10257dd0ef0ee40ae66b9 100644 (file)
@@ -388,7 +388,10 @@ int dma_async_device_register(struct dma_device *device)
 
        init_completion(&device->done);
        kref_init(&device->refcount);
+
+       mutex_lock(&dma_list_mutex);
        device->dev_id = id++;
+       mutex_unlock(&dma_list_mutex);
 
        /* represent channels in sysfs. Probably want devs too */
        list_for_each_entry(chan, &device->channels, device_node) {
index ecd743f7cc617b9921b7d08e553da0264d8c401c..6607fdd00b1cd3a31655cc6b53fca580919f3354 100644 (file)
@@ -1341,10 +1341,12 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan)
  */
 #define IOAT_TEST_SIZE 2000
 
+DECLARE_COMPLETION(test_completion);
 static void ioat_dma_test_callback(void *dma_async_param)
 {
        printk(KERN_ERR "ioatdma: ioat_dma_test_callback(%p)\n",
                dma_async_param);
+       complete(&test_completion);
 }
 
 /**
@@ -1410,7 +1412,8 @@ static int ioat_dma_self_test(struct ioatdma_device *device)
                goto free_resources;
        }
        device->common.device_issue_pending(dma_chan);
-       msleep(1);
+
+       wait_for_completion_timeout(&test_completion, msecs_to_jiffies(3000));
 
        if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL)
                                        != DMA_SUCCESS) {
index c7a9306d951d2c61f622c601ef2d49af422b679e..6be3172622009ff67ec502b049f167d6ccebe1cd 100644 (file)
@@ -85,18 +85,28 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc,
                        enum dma_ctrl_flags flags = desc->async_tx.flags;
                        u32 src_cnt;
                        dma_addr_t addr;
+                       dma_addr_t dest;
 
+                       src_cnt = unmap->unmap_src_cnt;
+                       dest = iop_desc_get_dest_addr(unmap, iop_chan);
                        if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
-                               addr = iop_desc_get_dest_addr(unmap, iop_chan);
-                               dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
+                               enum dma_data_direction dir;
+
+                               if (src_cnt > 1) /* is xor? */
+                                       dir = DMA_BIDIRECTIONAL;
+                               else
+                                       dir = DMA_FROM_DEVICE;
+
+                               dma_unmap_page(dev, dest, len, dir);
                        }
 
                        if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
-                               src_cnt = unmap->unmap_src_cnt;
                                while (src_cnt--) {
                                        addr = iop_desc_get_src_addr(unmap,
                                                                     iop_chan,
                                                                     src_cnt);
+                                       if (addr == dest)
+                                               continue;
                                        dma_unmap_page(dev, addr, len,
                                                       DMA_TO_DEVICE);
                                }
index 0328da020a1084e6c7f0fcfd0e729a00e079702d..bcda17426411ea6f4c311aa5b077a1e91e906b63 100644 (file)
@@ -311,17 +311,26 @@ mv_xor_run_tx_complete_actions(struct mv_xor_desc_slot *desc,
                        enum dma_ctrl_flags flags = desc->async_tx.flags;
                        u32 src_cnt;
                        dma_addr_t addr;
+                       dma_addr_t dest;
 
+                       src_cnt = unmap->unmap_src_cnt;
+                       dest = mv_desc_get_dest_addr(unmap);
                        if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
-                               addr = mv_desc_get_dest_addr(unmap);
-                               dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE);
+                               enum dma_data_direction dir;
+
+                               if (src_cnt > 1) /* is xor ? */
+                                       dir = DMA_BIDIRECTIONAL;
+                               else
+                                       dir = DMA_FROM_DEVICE;
+                               dma_unmap_page(dev, dest, len, dir);
                        }
 
                        if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
-                               src_cnt = unmap->unmap_src_cnt;
                                while (src_cnt--) {
                                        addr = mv_desc_get_src_addr(unmap,
                                                                    src_cnt);
+                                       if (addr == dest)
+                                               continue;
                                        dma_unmap_page(dev, addr, len,
                                                       DMA_TO_DEVICE);
                                }