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@xxxxxxxxx>
diff -r aeaa3c83f6e5 linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c Mon Sep 5
20:05:58 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c Tue Sep 6
20:02:44 2005
@@ -51,7 +51,7 @@
* swiotlb_sync_single_*, to see if the memory was in fact allocated by this
* API.
*/
-static dma_addr_t iotlb_bus_start, iotlb_bus_mask;
+static dma_addr_t iotlb_bus_start, iotlb_bus_mask, iotlb_bus_end;
/* Does the given dma address reside within the swiotlb aperture? */
#define in_swiotlb_aperture(a) (!(((a) ^ iotlb_bus_start) & iotlb_bus_mask))
@@ -157,6 +157,7 @@
io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow);
iotlb_bus_start = virt_to_bus(iotlb_virt_start);
+ iotlb_bus_end = iotlb_bus_start + bytes;
iotlb_bus_mask = ~(dma_addr_t)(bytes - 1);
printk(KERN_INFO "Software IO TLB enabled: \n"
@@ -165,7 +166,7 @@
" Kernel range: 0x%016lx - 0x%016lx\n",
bytes >> 20,
(unsigned long)iotlb_bus_start,
- (unsigned long)iotlb_bus_start + bytes,
+ (unsigned long)iotlb_bus_end,
(unsigned long)iotlb_virt_start,
(unsigned long)iotlb_virt_start + bytes);
}
@@ -191,6 +192,10 @@
if (swiotlb)
swiotlb_init_with_default_size(64 * (1<<20));
+
+ printk(KERN_INFO "swiotlb is %sabled%s\n",
+ (swiotlb ? "en" : "dis"),
+ (swiotlb_force ? " (forced)" : ""));
}
static void
@@ -428,8 +433,12 @@
/*
* Ensure that the address returned is DMA'ble
*/
- if (address_needs_mapping(hwdev, dev_addr))
- panic("map_single: bounce buffer is not DMA'ble");
+ if (address_needs_mapping(hwdev, dev_addr)) {
+ printk(KERN_CRIT "swiotlb returning 0x%Lx for ptr %p, but "
+ "address still needs remapping!\n",
+ dev_addr, ptr);
+ BUG_ON(dev_addr);
+ }
return dev_addr;
}
@@ -632,7 +641,8 @@
int
swiotlb_dma_supported (struct device *hwdev, u64 mask)
{
- return (mask >= 0xffffffffUL);
+ /* we can DMA if the mask covers the entire aperture */
+ return ((mask & iotlb_bus_end) == iotlb_bus_end);
}
EXPORT_SYMBOL(swiotlb_init);
diff -r aeaa3c83f6e5 linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pci.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pci.h Mon Sep 5
20:05:58 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pci.h Tue Sep 6
20:02:44 2005
@@ -76,10 +76,31 @@
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
(((PTR)->LEN_NAME) = (VAL))
-#else
-/* No IOMMU */
+#else /* !defined(CONFIG_GART_IOMMU) */
-/* On Xen we use SWIOTLB instead of blk-specific bounce buffers. */
+#ifdef CONFIG_SWIOTLB
+
+/* SWIOTLB (bounce buffer) support */
+#define PCI_DMA_BUS_IS_PHYS (0)
+
+#define pci_dac_dma_supported(pci_dev, mask) 1
+
+#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \
+ dma_addr_t ADDR_NAME;
+#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \
+ __u32 LEN_NAME;
+#define pci_unmap_addr(PTR, ADDR_NAME) \
+ ((PTR)->ADDR_NAME)
+#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \
+ (((PTR)->ADDR_NAME) = (VAL))
+#define pci_unmap_len(PTR, LEN_NAME) \
+ ((PTR)->LEN_NAME)
+#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
+ (((PTR)->LEN_NAME) = (VAL))
+
+#else /* !defined(CONFIG_SWIOTLB) */
+
+/* no IOMMU at all */
#define PCI_DMA_BUS_IS_PHYS (0)
#define pci_dac_dma_supported(pci_dev, mask) 1
@@ -91,7 +112,8 @@
#define pci_unmap_len(PTR, LEN_NAME) (0)
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
-#endif
+#endif /* defined(CONFIG_SWIOTLB) */
+#endif /* defined(CONFIG_GART_IOMMU) */
#include <asm-generic/pci-dma-compat.h>
--
Muli Ben-Yehuda
http://www.mulix.org | http://mulix.livejournal.com/
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|