ia64/xen-unstable

changeset 6661:d647c3d381d2

The attached patch fixes two problems I ran into with the swiotlb code
in unstable (changeset aeaa3c83f6e5). Tested on a dual Opteron x86-64
machine with 4GB of memory and a tg3 modified to only DMA below 2GB.

- swiotlb_dma_supported() checked that the device DMA mask was equal
or bigger than 4GB, when in fact all that's needed is that the device
be able to DMA into the swiotlb aperture (1GB on my AMD x86-64
machine). Some device are actually only 31-bit DMA capable, so this
would've tripped them.

- On some platforms, PCI unmaps and syncs are nops, so there's no need to
keep track of the dma_addr they need after the initial mapping. The
DMA API supports this via the DECLARE_PCI_UNMAP_ADDR macros (see
Documentation/DMA-mapping.txt). Since the swiotlb code does make us of
the dma_addr for swiotlb_unmap_xxx and (more importantly)
swiotlb_dma_sync_xxx, we need to define them to something
meaningful.

Signed-Off-By: Muli Ben-Yehuda <mulix@mulix.org>
author kaf24@firebug.cl.cam.ac.uk
date Tue Sep 06 18:25:00 2005 +0000 (2005-09-06)
parents d0a4f770a5f4
children 28a10ec0fd6b
files linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c linux-2.6-xen-sparse/include/asm-xen/asm-i386/pci.h linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pci.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c	Tue Sep 06 18:01:24 2005 +0000
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c	Tue Sep 06 18:25:00 2005 +0000
     1.3 @@ -51,7 +51,7 @@ static unsigned long iotlb_nslabs;
     1.4   * swiotlb_sync_single_*, to see if the memory was in fact allocated by this
     1.5   * API.
     1.6   */
     1.7 -static dma_addr_t iotlb_bus_start, iotlb_bus_mask;
     1.8 +static dma_addr_t iotlb_bus_start, iotlb_bus_end, iotlb_bus_mask;
     1.9  
    1.10  /* Does the given dma address reside within the swiotlb aperture? */
    1.11  #define in_swiotlb_aperture(a) (!(((a) ^ iotlb_bus_start) & iotlb_bus_mask))
    1.12 @@ -157,6 +157,7 @@ swiotlb_init_with_default_size (size_t d
    1.13  	io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow);
    1.14  
    1.15  	iotlb_bus_start = virt_to_bus(iotlb_virt_start);
    1.16 +	iotlb_bus_end   = iotlb_bus_start + bytes;
    1.17  	iotlb_bus_mask  = ~(dma_addr_t)(bytes - 1);
    1.18  
    1.19  	printk(KERN_INFO "Software IO TLB enabled: \n"
    1.20 @@ -165,7 +166,7 @@ swiotlb_init_with_default_size (size_t d
    1.21  	       " Kernel range: 0x%016lx - 0x%016lx\n",
    1.22  	       bytes >> 20,
    1.23  	       (unsigned long)iotlb_bus_start,
    1.24 -	       (unsigned long)iotlb_bus_start + bytes,
    1.25 +	       (unsigned long)iotlb_bus_end,
    1.26  	       (unsigned long)iotlb_virt_start,
    1.27  	       (unsigned long)iotlb_virt_start + bytes);
    1.28  }
    1.29 @@ -191,6 +192,10 @@ swiotlb_init(void)
    1.30  
    1.31  	if (swiotlb)
    1.32  		swiotlb_init_with_default_size(64 * (1<<20));
    1.33 +
    1.34 +	printk(KERN_INFO "swiotlb is %sabled%s\n", 
    1.35 +	       (swiotlb ? "en" : "dis"), 
    1.36 +	       (swiotlb_force ? " (forced)" : ""));
    1.37  }
    1.38  
    1.39  static void
    1.40 @@ -424,13 +429,6 @@ swiotlb_map_single(struct device *hwdev,
    1.41  	}
    1.42  
    1.43  	dev_addr = virt_to_bus(map);
    1.44 -
    1.45 -	/*
    1.46 -	 * Ensure that the address returned is DMA'ble
    1.47 -	 */
    1.48 -	if (address_needs_mapping(hwdev, dev_addr))
    1.49 -		panic("map_single: bounce buffer is not DMA'ble");
    1.50 -
    1.51  	return dev_addr;
    1.52  }
    1.53  
    1.54 @@ -632,7 +630,7 @@ swiotlb_dma_mapping_error(dma_addr_t dma
    1.55  int
    1.56  swiotlb_dma_supported (struct device *hwdev, u64 mask)
    1.57  {
    1.58 -	return (mask >= 0xffffffffUL);
    1.59 +	return (mask >= (iotlb_bus_end - 1));
    1.60  }
    1.61  
    1.62  EXPORT_SYMBOL(swiotlb_init);
     2.1 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pci.h	Tue Sep 06 18:01:24 2005 +0000
     2.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pci.h	Tue Sep 06 18:25:00 2005 +0000
     2.3 @@ -43,9 +43,33 @@ int pcibios_set_irq_routing(struct pci_d
     2.4  
     2.5  struct pci_dev;
     2.6  
     2.7 +#ifdef CONFIG_SWIOTLB
     2.8 +
     2.9 +
    2.10  /* On Xen we use SWIOTLB instead of blk-specific bounce buffers. */
    2.11  #define PCI_DMA_BUS_IS_PHYS	(0)
    2.12  
    2.13 +#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
    2.14 +	dma_addr_t ADDR_NAME;
    2.15 +#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
    2.16 +	__u32 LEN_NAME;
    2.17 +#define pci_unmap_addr(PTR, ADDR_NAME)			\
    2.18 +	((PTR)->ADDR_NAME)
    2.19 +#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
    2.20 +	(((PTR)->ADDR_NAME) = (VAL))
    2.21 +#define pci_unmap_len(PTR, LEN_NAME)			\
    2.22 +	((PTR)->LEN_NAME)
    2.23 +#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
    2.24 +	(((PTR)->LEN_NAME) = (VAL))
    2.25 +
    2.26 +#else
    2.27 +
    2.28 +/* The PCI address space does equal the physical memory
    2.29 + * address space.  The networking and block device layers use
    2.30 + * this boolean for bounce buffer decisions.
    2.31 + */
    2.32 +#define PCI_DMA_BUS_IS_PHYS	(1)
    2.33 +
    2.34  /* pci_unmap_{page,single} is a nop so... */
    2.35  #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
    2.36  #define DECLARE_PCI_UNMAP_LEN(LEN_NAME)
    2.37 @@ -54,6 +78,8 @@ struct pci_dev;
    2.38  #define pci_unmap_len(PTR, LEN_NAME)		(0)
    2.39  #define pci_unmap_len_set(PTR, LEN_NAME, VAL)	do { } while (0)
    2.40  
    2.41 +#endif
    2.42 +
    2.43  /* This is always fine. */
    2.44  #define pci_dac_dma_supported(pci_dev, mask)	(1)
    2.45  
     3.1 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pci.h	Tue Sep 06 18:01:24 2005 +0000
     3.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pci.h	Tue Sep 06 18:25:00 2005 +0000
     3.3 @@ -76,12 +76,29 @@ extern int iommu_sac_force;
     3.4  #define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
     3.5  	(((PTR)->LEN_NAME) = (VAL))
     3.6  
     3.7 +#elif defined(CONFIG_SWIOTLB)
     3.8 +
     3.9 +#define PCI_DMA_BUS_IS_PHYS	0
    3.10 +
    3.11 +#define pci_dac_dma_supported(pci_dev, mask)    1
    3.12 +
    3.13 +#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)	\
    3.14 +	dma_addr_t ADDR_NAME;
    3.15 +#define DECLARE_PCI_UNMAP_LEN(LEN_NAME)		\
    3.16 +	__u32 LEN_NAME;
    3.17 +#define pci_unmap_addr(PTR, ADDR_NAME)			\
    3.18 +	((PTR)->ADDR_NAME)
    3.19 +#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL)		\
    3.20 +	(((PTR)->ADDR_NAME) = (VAL))
    3.21 +#define pci_unmap_len(PTR, LEN_NAME)			\
    3.22 +	((PTR)->LEN_NAME)
    3.23 +#define pci_unmap_len_set(PTR, LEN_NAME, VAL)		\
    3.24 +	(((PTR)->LEN_NAME) = (VAL))
    3.25 +
    3.26  #else
    3.27  /* No IOMMU */
    3.28  
    3.29 -/* On Xen we use SWIOTLB instead of blk-specific bounce buffers. */
    3.30 -#define PCI_DMA_BUS_IS_PHYS	(0)
    3.31 -
    3.32 +#define PCI_DMA_BUS_IS_PHYS	1
    3.33  #define pci_dac_dma_supported(pci_dev, mask)    1
    3.34  
    3.35  #define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)