mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
[LINUX] swiotlb allocates multiple smaller contiguous DMA regions,
rather than a single big one. Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
1 parent
b5e40184be
commit
80c6044fb3
1 file changed
+21
-14
@@ -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 @@ void
|
||||
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 default_size)
|
||||
"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 default_size)
|
||||
*/
|
||||
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 @@ swiotlb_dma_mapping_error(dma_addr_t dma_addr)
|
||||
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);
|
||||
|
||||