[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [linux-2.6.18-xen] linux: fix swiotlb sync functions to properly deal with DMA_BIDIRECTIONAL



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1284396082 -3600
# Node ID 04cd43bee272b8493b809c52cae5cc2577019002
# Parent  669c133aef5317183c013c368f36e4c77fb60231
linux: fix swiotlb sync functions to properly deal with DMA_BIDIRECTIONAL

This change was left out from a merge somewhere between 2.6.12 and
2.6.16.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
Cc: Dominic Curran <dominic.curran@xxxxxxxxxx>
---
 lib/swiotlb-xen.c |   80 +++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 53 insertions(+), 27 deletions(-)

diff -r 669c133aef53 -r 04cd43bee272 lib/swiotlb-xen.c
--- a/lib/swiotlb-xen.c Mon Sep 13 17:40:48 2010 +0100
+++ b/lib/swiotlb-xen.c Mon Sep 13 17:41:22 2010 +0100
@@ -46,6 +46,14 @@ EXPORT_SYMBOL(swiotlb);
  * controllable.
  */
 #define IO_TLB_SHIFT 11
+
+/*
+ * Enumeration for sync targets
+ */
+enum dma_sync_target {
+       SYNC_FOR_CPU = 0,
+       SYNC_FOR_DEVICE = 1,
+};
 
 int swiotlb_force;
 
@@ -440,11 +448,26 @@ unmap_single(struct device *hwdev, char 
 }
 
 static void
-sync_single(struct device *hwdev, char *dma_addr, size_t size, int dir)
+sync_single(struct device *hwdev, char *dma_addr, size_t size,
+           int dir, int target)
 {
        struct phys_addr buffer = dma_addr_to_phys_addr(dma_addr);
-       BUG_ON((dir != DMA_FROM_DEVICE) && (dir != DMA_TO_DEVICE));
-       __sync_single(buffer, dma_addr, size, dir);
+       switch (target) {
+       case SYNC_FOR_CPU:
+               if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL))
+                       __sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE);
+               else
+                       BUG_ON(dir != DMA_TO_DEVICE);
+               break;
+       case SYNC_FOR_DEVICE:
+               if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL))
+                       __sync_single(buffer, dma_addr, size, DMA_TO_DEVICE);
+               else
+                       BUG_ON(dir != DMA_FROM_DEVICE);
+               break;
+       default:
+               BUG();
+       }
 }
 
 static void
@@ -539,22 +562,27 @@ swiotlb_unmap_single(struct device *hwde
  * address back to the card, you must first perform a
  * swiotlb_dma_sync_for_device, and then the device again owns the buffer
  */
+static inline void
+swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
+                   size_t size, int dir, int target)
+{
+       BUG_ON(dir == DMA_NONE);
+       if (in_swiotlb_aperture(dev_addr))
+               sync_single(hwdev, bus_to_virt(dev_addr), size, dir, target);
+}
+
 void
 swiotlb_sync_single_for_cpu(struct device *hwdev, dma_addr_t dev_addr,
                            size_t size, int dir)
 {
-       BUG_ON(dir == DMA_NONE);
-       if (in_swiotlb_aperture(dev_addr))
-               sync_single(hwdev, bus_to_virt(dev_addr), size, dir);
+       swiotlb_sync_single(hwdev, dev_addr, size, dir, SYNC_FOR_CPU);
 }
 
 void
 swiotlb_sync_single_for_device(struct device *hwdev, dma_addr_t dev_addr,
                               size_t size, int dir)
 {
-       BUG_ON(dir == DMA_NONE);
-       if (in_swiotlb_aperture(dev_addr))
-               sync_single(hwdev, bus_to_virt(dev_addr), size, dir);
+       swiotlb_sync_single(hwdev, dev_addr, size, dir, SYNC_FOR_DEVICE);
 }
 
 /*
@@ -638,34 +666,32 @@ swiotlb_unmap_sg(struct device *hwdev, s
  * The same as swiotlb_sync_single_* but for a scatter-gather list, same rules
  * and usage.
  */
+static inline void
+swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sg,
+               int nelems, int dir, int target)
+{
+       int i;
+
+       BUG_ON(dir == DMA_NONE);
+
+       for (i = 0; i < nelems; i++, sg++)
+               if (in_swiotlb_aperture(sg->dma_address))
+                       sync_single(hwdev, bus_to_virt(sg->dma_address),
+                                   sg->dma_length, dir, target);
+}
+
 void
 swiotlb_sync_sg_for_cpu(struct device *hwdev, struct scatterlist *sg,
                        int nelems, int dir)
 {
-       int i;
-
-       BUG_ON(dir == DMA_NONE);
-
-       for (i = 0; i < nelems; i++, sg++)
-               if (in_swiotlb_aperture(sg->dma_address))
-                       sync_single(hwdev,
-                                   (void *)bus_to_virt(sg->dma_address),
-                                   sg->dma_length, dir);
+       swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_CPU);
 }
 
 void
 swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
                           int nelems, int dir)
 {
-       int i;
-
-       BUG_ON(dir == DMA_NONE);
-
-       for (i = 0; i < nelems; i++, sg++)
-               if (in_swiotlb_aperture(sg->dma_address))
-                       sync_single(hwdev,
-                                   (void *)bus_to_virt(sg->dma_address),
-                                   sg->dma_length, dir);
+       swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_DEVICE);
 }
 
 #ifdef CONFIG_HIGHMEM

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.