# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID d647c3d381d23e504e96117853bcef0bb8905bb7
# Parent d0a4f770a5f493d4459452ab11c164187a282945
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 d0a4f770a5f4 -r d647c3d381d2
linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c Tue Sep 6
18:01:24 2005
+++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c Tue Sep 6
18:25:00 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_end, iotlb_bus_mask;
/* 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
@@ -424,13 +429,6 @@
}
dev_addr = virt_to_bus(map);
-
- /*
- * Ensure that the address returned is DMA'ble
- */
- if (address_needs_mapping(hwdev, dev_addr))
- panic("map_single: bounce buffer is not DMA'ble");
-
return dev_addr;
}
@@ -632,7 +630,7 @@
int
swiotlb_dma_supported (struct device *hwdev, u64 mask)
{
- return (mask >= 0xffffffffUL);
+ return (mask >= (iotlb_bus_end - 1));
}
EXPORT_SYMBOL(swiotlb_init);
diff -r d0a4f770a5f4 -r d647c3d381d2
linux-2.6-xen-sparse/include/asm-xen/asm-i386/pci.h
--- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pci.h Tue Sep 6
18:01:24 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/pci.h Tue Sep 6
18:25:00 2005
@@ -43,8 +43,32 @@
struct pci_dev;
+#ifdef CONFIG_SWIOTLB
+
+
/* On Xen we use SWIOTLB instead of blk-specific bounce buffers. */
#define PCI_DMA_BUS_IS_PHYS (0)
+
+#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
+
+/* The PCI address space does equal the physical memory
+ * address space. The networking and block device layers use
+ * this boolean for bounce buffer decisions.
+ */
+#define PCI_DMA_BUS_IS_PHYS (1)
/* pci_unmap_{page,single} is a nop so... */
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
@@ -53,6 +77,8 @@
#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0)
#define pci_unmap_len(PTR, LEN_NAME) (0)
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0)
+
+#endif
/* This is always fine. */
#define pci_dac_dma_supported(pci_dev, mask) (1)
diff -r d0a4f770a5f4 -r d647c3d381d2
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 Tue Sep 6
18:01:24 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/asm-x86_64/pci.h Tue Sep 6
18:25:00 2005
@@ -76,12 +76,29 @@
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
(((PTR)->LEN_NAME) = (VAL))
+#elif defined(CONFIG_SWIOTLB)
+
+#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
/* No IOMMU */
-/* On Xen we use SWIOTLB instead of blk-specific bounce buffers. */
-#define PCI_DMA_BUS_IS_PHYS (0)
-
+#define PCI_DMA_BUS_IS_PHYS 1
#define pci_dac_dma_supported(pci_dev, mask) 1
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME)
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|