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] linux: Reduce restrictions on address width for DMA

To: <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH] linux: Reduce restrictions on address width for DMA operations
From: "Jan Beulich" <jbeulich@xxxxxxxxxx>
Date: Tue, 02 Jan 2007 14:28:46 +0000
Delivery-date: Tue, 02 Jan 2007 06:27:08 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
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/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Use address width needed by device rather than dma_bits in dma_alloc_coherent().
Probe supported address width in swiotlb initialization.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>

Index: sle10-sp1-2006-12-21/arch/i386/kernel/pci-dma-xen.c
===================================================================
--- sle10-sp1-2006-12-21.orig/arch/i386/kernel/pci-dma-xen.c    2007-01-02 
12:36:26.000000000 +0100
+++ sle10-sp1-2006-12-21/arch/i386/kernel/pci-dma-xen.c 2007-01-02 
10:32:16.000000000 +0100
@@ -161,6 +161,8 @@ void *dma_alloc_coherent(struct device *
        struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
        unsigned int order = get_order(size);
        unsigned long vstart;
+       u64 mask;
+
        /* ignore region specifiers */
        gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
 
@@ -183,9 +185,14 @@ void *dma_alloc_coherent(struct device *
        vstart = __get_free_pages(gfp, order);
        ret = (void *)vstart;
 
+       if (dev != NULL && dev->coherent_dma_mask)
+               mask = dev->coherent_dma_mask;
+       else
+               mask = 0xffffffff;
+
        if (ret != NULL) {
                if (xen_create_contiguous_region(vstart, order,
-                                                dma_bits) != 0) {
+                                                fls64(mask)) != 0) {
                        free_pages(vstart, order);
                        return NULL;
                }
Index: sle10-sp1-2006-12-21/arch/i386/kernel/swiotlb.c
===================================================================
--- sle10-sp1-2006-12-21.orig/arch/i386/kernel/swiotlb.c        2007-01-02 
12:36:26.000000000 +0100
+++ sle10-sp1-2006-12-21/arch/i386/kernel/swiotlb.c     2007-01-02 
12:48:40.000000000 +0100
@@ -47,9 +47,6 @@ EXPORT_SYMBOL(swiotlb);
  */
 #define IO_TLB_SHIFT 11
 
-/* Width of DMA addresses. 30 bits is a b44 limitation. */
-#define DEFAULT_DMA_BITS 30
-
 static int swiotlb_force;
 static char *iotlb_virt_start;
 static unsigned long iotlb_nslabs;
@@ -98,11 +95,12 @@ static struct phys_addr {
  */
 static DEFINE_SPINLOCK(io_tlb_lock);
 
-unsigned int dma_bits = DEFAULT_DMA_BITS;
+static unsigned int dma_bits;
+static unsigned int __initdata max_dma_bits = 32;
 static int __init
 setup_dma_bits(char *str)
 {
-       dma_bits = simple_strtoul(str, NULL, 0);
+       max_dma_bits = simple_strtoul(str, NULL, 0);
        return 0;
 }
 __setup("dma_bits=", setup_dma_bits);
@@ -143,6 +141,7 @@ void
 swiotlb_init_with_default_size (size_t default_size)
 {
        unsigned long i, bytes;
+       int rc;
 
        if (!iotlb_nslabs) {
                iotlb_nslabs = (default_size >> IO_TLB_SHIFT);
@@ -159,16 +158,33 @@ swiotlb_init_with_default_size (size_t d
         */
        iotlb_virt_start = alloc_bootmem_low_pages(bytes);
        if (!iotlb_virt_start)
-               panic("Cannot allocate SWIOTLB buffer!\n"
-                     "Use dom0_mem Xen boot parameter to reserve\n"
-                     "some DMA memory (e.g., dom0_mem=-128M).\n");
+               panic("Cannot allocate SWIOTLB buffer!\n");
 
+       dma_bits = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT) + PAGE_SHIFT;
        for (i = 0; i < iotlb_nslabs; i += IO_TLB_SEGSIZE) {
-               int rc = xen_create_contiguous_region(
-                       (unsigned long)iotlb_virt_start + (i << IO_TLB_SHIFT),
-                       get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT),
-                       dma_bits);
-               BUG_ON(rc);
+               do {
+                       rc = xen_create_contiguous_region(
+                               (unsigned long)iotlb_virt_start + (i << 
IO_TLB_SHIFT),
+                               get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT),
+                               dma_bits);
+               } while (rc && dma_bits++ < max_dma_bits);
+               if (rc) {
+                       if (i == 0)
+                               panic("No suitable physical memory available 
for SWIOTLB buffer!\n"
+                                     "Use dom0_mem Xen boot parameter to 
reserve\n"
+                                     "some DMA memory (e.g., 
dom0_mem=-128M).\n");
+                       iotlb_nslabs = i;
+                       i <<= IO_TLB_SHIFT;
+                       free_bootmem(__pa(iotlb_virt_start + i), bytes - i);
+                       bytes = i;
+                       for (dma_bits = 0; i > 0; i -= IO_TLB_SEGSIZE << 
IO_TLB_SHIFT) {
+                               unsigned int bits = 
fls64(virt_to_bus(iotlb_virt_start + i - 1));
+
+                               if (bits > dma_bits)
+                                       dma_bits = bits;
+                       }
+                       break;
+               }
        }
 
        /*
@@ -186,17 +202,27 @@ swiotlb_init_with_default_size (size_t d
         * Get the overflow emergency buffer
         */
        io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow);
+       if (!io_tlb_overflow_buffer)
+               panic("Cannot allocate SWIOTLB overflow buffer!\n");
+
+       do {
+               rc = xen_create_contiguous_region(
+                       (unsigned long)io_tlb_overflow_buffer,
+                       get_order(io_tlb_overflow),
+                       dma_bits);
+       } while (rc && dma_bits++ < max_dma_bits);
+       if (rc)
+               panic("No suitable physical memory available for SWIOTLB 
overflow buffer!\n");
 
        iotlb_pfn_start = __pa(iotlb_virt_start) >> PAGE_SHIFT;
        iotlb_pfn_end   = iotlb_pfn_start + (bytes >> PAGE_SHIFT);
 
        printk(KERN_INFO "Software IO TLB enabled: \n"
               " Aperture:     %lu megabytes\n"
-              " Kernel range: 0x%016lx - 0x%016lx\n"
+              " Kernel range: %p - %p\n"
               " Address size: %u bits\n",
               bytes >> 20,
-              (unsigned long)iotlb_virt_start,
-              (unsigned long)iotlb_virt_start + bytes,
+              iotlb_virt_start, iotlb_virt_start + bytes,
               dma_bits);
 }
 
Index: sle10-sp1-2006-12-21/include/asm-i386/mach-xen/asm/swiotlb.h
===================================================================
--- sle10-sp1-2006-12-21.orig/include/asm-i386/mach-xen/asm/swiotlb.h   
2007-01-02 12:36:26.000000000 +0100
+++ sle10-sp1-2006-12-21/include/asm-i386/mach-xen/asm/swiotlb.h        
2007-01-02 10:28:31.000000000 +0100
@@ -34,8 +34,6 @@ extern void swiotlb_unmap_page(struct de
 extern int swiotlb_dma_supported(struct device *hwdev, u64 mask);
 extern void swiotlb_init(void);
 
-extern unsigned int dma_bits;
-
 #ifdef CONFIG_SWIOTLB
 extern int swiotlb;
 #else


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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-devel] [PATCH] linux: Reduce restrictions on address width for DMA operations, Jan Beulich <=