ia64/xen-unstable

changeset 13419:ed73ff8440d8

linux: Reduce restrictions on address width for DMA operations

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@novell.com>
author kfraser@localhost.localdomain
date Fri Jan 12 15:34:30 2007 +0000 (2007-01-12)
parents 38fcc7646959
children c149ffa2fd1a
files linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c	Fri Jan 12 15:27:09 2007 +0000
     1.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/pci-dma-xen.c	Fri Jan 12 15:34:30 2007 +0000
     1.3 @@ -161,6 +161,8 @@ void *dma_alloc_coherent(struct device *
     1.4  	struct dma_coherent_mem *mem = dev ? dev->dma_mem : NULL;
     1.5  	unsigned int order = get_order(size);
     1.6  	unsigned long vstart;
     1.7 +	u64 mask;
     1.8 +
     1.9  	/* ignore region specifiers */
    1.10  	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
    1.11  
    1.12 @@ -183,9 +185,14 @@ void *dma_alloc_coherent(struct device *
    1.13  	vstart = __get_free_pages(gfp, order);
    1.14  	ret = (void *)vstart;
    1.15  
    1.16 +	if (dev != NULL && dev->coherent_dma_mask)
    1.17 +		mask = dev->coherent_dma_mask;
    1.18 +	else
    1.19 +		mask = 0xffffffff;
    1.20 +
    1.21  	if (ret != NULL) {
    1.22  		if (xen_create_contiguous_region(vstart, order,
    1.23 -						 dma_bits) != 0) {
    1.24 +						 fls64(mask)) != 0) {
    1.25  			free_pages(vstart, order);
    1.26  			return NULL;
    1.27  		}
     2.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c	Fri Jan 12 15:27:09 2007 +0000
     2.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c	Fri Jan 12 15:34:30 2007 +0000
     2.3 @@ -47,9 +47,6 @@ EXPORT_SYMBOL(swiotlb);
     2.4   */
     2.5  #define IO_TLB_SHIFT 11
     2.6  
     2.7 -/* Width of DMA addresses. 30 bits is a b44 limitation. */
     2.8 -#define DEFAULT_DMA_BITS 30
     2.9 -
    2.10  static int swiotlb_force;
    2.11  static char *iotlb_virt_start;
    2.12  static unsigned long iotlb_nslabs;
    2.13 @@ -98,11 +95,12 @@ static struct phys_addr {
    2.14   */
    2.15  static DEFINE_SPINLOCK(io_tlb_lock);
    2.16  
    2.17 -unsigned int dma_bits = DEFAULT_DMA_BITS;
    2.18 +static unsigned int dma_bits;
    2.19 +static unsigned int __initdata max_dma_bits = 32;
    2.20  static int __init
    2.21  setup_dma_bits(char *str)
    2.22  {
    2.23 -	dma_bits = simple_strtoul(str, NULL, 0);
    2.24 +	max_dma_bits = simple_strtoul(str, NULL, 0);
    2.25  	return 0;
    2.26  }
    2.27  __setup("dma_bits=", setup_dma_bits);
    2.28 @@ -143,6 +141,7 @@ void
    2.29  swiotlb_init_with_default_size (size_t default_size)
    2.30  {
    2.31  	unsigned long i, bytes;
    2.32 +	int rc;
    2.33  
    2.34  	if (!iotlb_nslabs) {
    2.35  		iotlb_nslabs = (default_size >> IO_TLB_SHIFT);
    2.36 @@ -159,16 +158,33 @@ swiotlb_init_with_default_size (size_t d
    2.37  	 */
    2.38  	iotlb_virt_start = alloc_bootmem_low_pages(bytes);
    2.39  	if (!iotlb_virt_start)
    2.40 -		panic("Cannot allocate SWIOTLB buffer!\n"
    2.41 -		      "Use dom0_mem Xen boot parameter to reserve\n"
    2.42 -		      "some DMA memory (e.g., dom0_mem=-128M).\n");
    2.43 +		panic("Cannot allocate SWIOTLB buffer!\n");
    2.44  
    2.45 +	dma_bits = get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT) + PAGE_SHIFT;
    2.46  	for (i = 0; i < iotlb_nslabs; i += IO_TLB_SEGSIZE) {
    2.47 -		int rc = xen_create_contiguous_region(
    2.48 -			(unsigned long)iotlb_virt_start + (i << IO_TLB_SHIFT),
    2.49 -			get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT),
    2.50 -			dma_bits);
    2.51 -		BUG_ON(rc);
    2.52 +		do {
    2.53 +			rc = xen_create_contiguous_region(
    2.54 +				(unsigned long)iotlb_virt_start + (i << IO_TLB_SHIFT),
    2.55 +				get_order(IO_TLB_SEGSIZE << IO_TLB_SHIFT),
    2.56 +				dma_bits);
    2.57 +		} while (rc && dma_bits++ < max_dma_bits);
    2.58 +		if (rc) {
    2.59 +			if (i == 0)
    2.60 +				panic("No suitable physical memory available for SWIOTLB buffer!\n"
    2.61 +				      "Use dom0_mem Xen boot parameter to reserve\n"
    2.62 +				      "some DMA memory (e.g., dom0_mem=-128M).\n");
    2.63 +			iotlb_nslabs = i;
    2.64 +			i <<= IO_TLB_SHIFT;
    2.65 +			free_bootmem(__pa(iotlb_virt_start + i), bytes - i);
    2.66 +			bytes = i;
    2.67 +			for (dma_bits = 0; i > 0; i -= IO_TLB_SEGSIZE << IO_TLB_SHIFT) {
    2.68 +				unsigned int bits = fls64(virt_to_bus(iotlb_virt_start + i - 1));
    2.69 +
    2.70 +				if (bits > dma_bits)
    2.71 +					dma_bits = bits;
    2.72 +			}
    2.73 +			break;
    2.74 +		}
    2.75  	}
    2.76  
    2.77  	/*
    2.78 @@ -186,17 +202,27 @@ swiotlb_init_with_default_size (size_t d
    2.79  	 * Get the overflow emergency buffer
    2.80  	 */
    2.81  	io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow);
    2.82 +	if (!io_tlb_overflow_buffer)
    2.83 +		panic("Cannot allocate SWIOTLB overflow buffer!\n");
    2.84 +
    2.85 +	do {
    2.86 +		rc = xen_create_contiguous_region(
    2.87 +			(unsigned long)io_tlb_overflow_buffer,
    2.88 +			get_order(io_tlb_overflow),
    2.89 +			dma_bits);
    2.90 +	} while (rc && dma_bits++ < max_dma_bits);
    2.91 +	if (rc)
    2.92 +		panic("No suitable physical memory available for SWIOTLB overflow buffer!\n");
    2.93  
    2.94  	iotlb_pfn_start = __pa(iotlb_virt_start) >> PAGE_SHIFT;
    2.95  	iotlb_pfn_end   = iotlb_pfn_start + (bytes >> PAGE_SHIFT);
    2.96  
    2.97  	printk(KERN_INFO "Software IO TLB enabled: \n"
    2.98  	       " Aperture:     %lu megabytes\n"
    2.99 -	       " Kernel range: 0x%016lx - 0x%016lx\n"
   2.100 +	       " Kernel range: %p - %p\n"
   2.101  	       " Address size: %u bits\n",
   2.102  	       bytes >> 20,
   2.103 -	       (unsigned long)iotlb_virt_start,
   2.104 -	       (unsigned long)iotlb_virt_start + bytes,
   2.105 +	       iotlb_virt_start, iotlb_virt_start + bytes,
   2.106  	       dma_bits);
   2.107  }
   2.108  
     3.1 --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h	Fri Jan 12 15:27:09 2007 +0000
     3.2 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/swiotlb.h	Fri Jan 12 15:34:30 2007 +0000
     3.3 @@ -34,8 +34,6 @@ extern void swiotlb_unmap_page(struct de
     3.4  extern int swiotlb_dma_supported(struct device *hwdev, u64 mask);
     3.5  extern void swiotlb_init(void);
     3.6  
     3.7 -extern unsigned int dma_bits;
     3.8 -
     3.9  #ifdef CONFIG_SWIOTLB
    3.10  extern int swiotlb;
    3.11  #else