WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 7 of 9] swiotlb: Add support for systems with highmem

To: Ingo Molnar <mingo@xxxxxxx>
Subject: [Xen-devel] [PATCH 7 of 9] swiotlb: Add support for systems with highmem
From: Jeremy Fitzhardinge <jeremy@xxxxxxxx>
Date: Mon, 22 Dec 2008 10:26:09 -0800
Cc: Xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxx>, Ian Campbell <ian.campbell@xxxxxxxxxx>, Becky Bruce <beckyb@xxxxxxxxxxxxxxxxxxx>, the arch/x86 maintainers <x86@xxxxxxxxxx>, linux-kernel@xxxxxxxxxxxxxxx, FUJITA Tomonori <fujita.tomonori@xxxxxxxxxxxxx>
Delivery-date: Mon, 22 Dec 2008 10:30:05 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <patchbomb.1229970362@xxxxxxxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
From: Becky Bruce <beckyb@xxxxxxxxxxxxxxxxxxx>

On highmem systems, the original dma buffer might not
have a virtual mapping - we need to kmap it in to perform
the bounce.  Extract the code that does the actual
copy into a function that does the kmap if highmem
is enabled, and defaults to the normal swiotlb memcpy
if not.

Signed-off-by: Becky Bruce <beckyb@xxxxxxxxxxxxxxxxxxx>
---
 lib/swiotlb.c |   53 +++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 45 insertions(+), 8 deletions(-)

diff --git a/lib/swiotlb.c b/lib/swiotlb.c
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -14,6 +14,7 @@
  * 04/07/.. ak         Better overflow handling. Assorted fixes.
  * 05/09/10 linville   Add support for syncing ranges, support syncing for
  *                     DMA_BIDIRECTIONAL mappings, miscellaneous cleanup.
+ * 08/12/11 beckyb     Add highmem support
  */
 
 #include <linux/cache.h>
@@ -26,6 +27,7 @@
 #include <linux/swiotlb.h>
 #include <linux/types.h>
 #include <linux/ctype.h>
+#include <linux/highmem.h>
 
 #include <asm/io.h>
 #include <asm/dma.h>
@@ -326,6 +328,45 @@
 }
 
 /*
+ * Bounce: copy the swiotlb buffer back to the original dma location
+ */
+void swiotlb_bounce(phys_addr_t phys, char *dma_addr, size_t size,
+                 enum dma_data_direction dir)
+{
+#ifdef CONFIG_HIGHMEM
+       /* The buffer may not have a mapping.  Map it in and copy */
+       unsigned int offset = ((unsigned long)phys &
+                              ((1 << PAGE_SHIFT) - 1));
+       char *buffer;
+       unsigned int sz = 0;
+       unsigned long flags;
+
+       while (size) {
+               sz = ((PAGE_SIZE - offset) > size) ? size :
+                       PAGE_SIZE - offset;
+               local_irq_save(flags);
+               buffer = kmap_atomic(pfn_to_page(phys >> PAGE_SHIFT),
+                                    KM_BOUNCE_READ);
+               if (dir == DMA_TO_DEVICE)
+                       memcpy(dma_addr, buffer + offset, sz);
+               else
+                       memcpy(buffer + offset, dma_addr, sz);
+               kunmap_atomic(buffer, KM_BOUNCE_READ);
+               local_irq_restore(flags);
+               size -= sz;
+               phys += sz;
+               dma_addr += sz;
+               offset = 0;
+       }
+#else
+       if (dir == DMA_TO_DEVICE)
+               memcpy(dma_addr, phys_to_virt(phys), size);
+       else
+               memcpy(phys_to_virt(phys), dma_addr, size);
+#endif
+}
+
+/*
  * Allocates bounce buffer and returns its kernel virtual address.
  */
 static void *
@@ -426,7 +467,7 @@
        for (i = 0; i < nslots; i++)
                io_tlb_orig_addr[index+i] = phys + (i << IO_TLB_SHIFT);
        if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
-               memcpy(dma_addr, phys_to_virt(phys), size);
+               swiotlb_bounce(phys, dma_addr, size, DMA_TO_DEVICE);
 
        return dma_addr;
 }
@@ -446,11 +487,7 @@
         * First, sync the memory before unmapping the entry
         */
        if (phys && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)))
-               /*
-                * bounce... copy the data back into the original buffer * and
-                * delete the bounce buffer.
-                */
-               memcpy(phys_to_virt(phys), dma_addr, size);
+               swiotlb_bounce(phys, dma_addr, size, DMA_FROM_DEVICE);
 
        /*
         * Return the buffer to the free list by setting the corresponding
@@ -490,13 +527,13 @@
        switch (target) {
        case SYNC_FOR_CPU:
                if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL))
-                       memcpy(phys_to_virt(phys), dma_addr, size);
+                       swiotlb_bounce(phys, 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))
-                       memcpy(dma_addr, phys_to_virt(phys), size);
+                       swiotlb_bounce(phys, dma_addr, size, DMA_TO_DEVICE);
                else
                        BUG_ON(dir != DMA_FROM_DEVICE);
                break;



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