# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 2db7b3627da4d38134ba0cfd740ce3ee73c3865e
# Parent a1b83fedc4edcc00941d972484ff398e98a62186
[LINUX] swiotlb allocates multiple smaller contiguous DMA regions,
rather than a single big one.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c | 35 ++++++++++++++----------
1 files changed, 21 insertions(+), 14 deletions(-)
diff -r a1b83fedc4ed -r 2db7b3627da4
linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c Thu Jun 08 11:35:27
2006 +0100
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/swiotlb.c Thu Jun 08 16:48:23
2006 +0100
@@ -47,6 +47,9 @@ EXPORT_SYMBOL(swiotlb);
*/
#define IO_TLB_SHIFT 11
+/* Width of DMA addresses in the IO TLB. 31 bits is an aacraid limitation. */
+#define IO_TLB_DMA_BITS 31
+
static int swiotlb_force;
static char *iotlb_virt_start;
static unsigned long iotlb_nslabs;
@@ -56,10 +59,16 @@ static unsigned long iotlb_nslabs;
* swiotlb_sync_single_*, to see if the memory was in fact allocated by this
* API.
*/
-static dma_addr_t iotlb_bus_start, iotlb_bus_end, iotlb_bus_mask;
+static unsigned long iotlb_pfn_start, iotlb_pfn_end;
/* Does the given dma address reside within the swiotlb aperture? */
-#define in_swiotlb_aperture(a) (!(((a) ^ iotlb_bus_start) & iotlb_bus_mask))
+static inline int in_swiotlb_aperture(dma_addr_t dev_addr)
+{
+ unsigned long pfn = mfn_to_local_pfn(dev_addr >> PAGE_SHIFT);
+ return (pfn_valid(pfn)
+ && (pfn >= iotlb_pfn_start)
+ && (pfn < iotlb_pfn_end));
+}
/*
* When the IOMMU overflows we return a fallback buffer. This sets the size.
@@ -125,7 +134,6 @@ swiotlb_init_with_default_size (size_t d
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);
@@ -146,10 +154,13 @@ swiotlb_init_with_default_size (size_t d
"Use dom0_mem Xen boot parameter to reserve\n"
"some DMA memory (e.g., dom0_mem=-128M).\n");
- /* Hardcode 31 address bits for now: aacraid limitation. */
- rc = xen_create_contiguous_region(
- (unsigned long)iotlb_virt_start, get_order(bytes), 31);
- BUG_ON(rc);
+ 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),
+ IO_TLB_DMA_BITS);
+ BUG_ON(rc);
+ }
/*
* Allocate and initialize the free list array. This array is used
@@ -167,17 +178,13 @@ swiotlb_init_with_default_size (size_t d
*/
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);
+ 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"
- " Bus range: 0x%016lx - 0x%016lx\n"
" Kernel range: 0x%016lx - 0x%016lx\n",
bytes >> 20,
- (unsigned long)iotlb_bus_start,
- (unsigned long)iotlb_bus_end,
(unsigned long)iotlb_virt_start,
(unsigned long)iotlb_virt_start + bytes);
}
@@ -647,7 +654,7 @@ int
int
swiotlb_dma_supported (struct device *hwdev, u64 mask)
{
- return (mask >= (iotlb_bus_end - 1));
+ return (mask >= ((1UL << IO_TLB_DMA_BITS) - 1));
}
EXPORT_SYMBOL(swiotlb_init);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|