|
@@ -122,11 +122,18 @@ static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
|
|
|
return phys_to_dma(hwdev, virt_to_phys(address));
|
|
|
}
|
|
|
|
|
|
+static bool no_iotlb_memory;
|
|
|
+
|
|
|
void swiotlb_print_info(void)
|
|
|
{
|
|
|
unsigned long bytes = io_tlb_nslabs << IO_TLB_SHIFT;
|
|
|
unsigned char *vstart, *vend;
|
|
|
|
|
|
+ if (no_iotlb_memory) {
|
|
|
+ pr_warn("software IO TLB: No low mem\n");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
vstart = phys_to_virt(io_tlb_start);
|
|
|
vend = phys_to_virt(io_tlb_end);
|
|
|
|
|
@@ -136,7 +143,7 @@ void swiotlb_print_info(void)
|
|
|
bytes >> 20, vstart, vend - 1);
|
|
|
}
|
|
|
|
|
|
-void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
|
|
|
+int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
|
|
|
{
|
|
|
void *v_overflow_buffer;
|
|
|
unsigned long i, bytes;
|
|
@@ -150,9 +157,10 @@ void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
|
|
|
/*
|
|
|
* Get the overflow emergency buffer
|
|
|
*/
|
|
|
- v_overflow_buffer = alloc_bootmem_low_pages(PAGE_ALIGN(io_tlb_overflow));
|
|
|
+ v_overflow_buffer = alloc_bootmem_low_pages_nopanic(
|
|
|
+ PAGE_ALIGN(io_tlb_overflow));
|
|
|
if (!v_overflow_buffer)
|
|
|
- panic("Cannot allocate SWIOTLB overflow buffer!\n");
|
|
|
+ return -ENOMEM;
|
|
|
|
|
|
io_tlb_overflow_buffer = __pa(v_overflow_buffer);
|
|
|
|
|
@@ -169,15 +177,19 @@ void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
|
|
|
|
|
|
if (verbose)
|
|
|
swiotlb_print_info();
|
|
|
+
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
* Statically reserve bounce buffer space and initialize bounce buffer data
|
|
|
* structures for the software IO TLB used to implement the DMA API.
|
|
|
*/
|
|
|
-static void __init
|
|
|
-swiotlb_init_with_default_size(size_t default_size, int verbose)
|
|
|
+void __init
|
|
|
+swiotlb_init(int verbose)
|
|
|
{
|
|
|
+ /* default to 64MB */
|
|
|
+ size_t default_size = 64UL<<20;
|
|
|
unsigned char *vstart;
|
|
|
unsigned long bytes;
|
|
|
|
|
@@ -188,20 +200,16 @@ swiotlb_init_with_default_size(size_t default_size, int verbose)
|
|
|
|
|
|
bytes = io_tlb_nslabs << IO_TLB_SHIFT;
|
|
|
|
|
|
- /*
|
|
|
- * Get IO TLB memory from the low pages
|
|
|
- */
|
|
|
- vstart = alloc_bootmem_low_pages(PAGE_ALIGN(bytes));
|
|
|
- if (!vstart)
|
|
|
- panic("Cannot allocate SWIOTLB buffer");
|
|
|
-
|
|
|
- swiotlb_init_with_tbl(vstart, io_tlb_nslabs, verbose);
|
|
|
-}
|
|
|
+ /* Get IO TLB memory from the low pages */
|
|
|
+ vstart = alloc_bootmem_low_pages_nopanic(PAGE_ALIGN(bytes));
|
|
|
+ if (vstart && !swiotlb_init_with_tbl(vstart, io_tlb_nslabs, verbose))
|
|
|
+ return;
|
|
|
|
|
|
-void __init
|
|
|
-swiotlb_init(int verbose)
|
|
|
-{
|
|
|
- swiotlb_init_with_default_size(64 * (1<<20), verbose); /* default to 64MB */
|
|
|
+ if (io_tlb_start)
|
|
|
+ free_bootmem(io_tlb_start,
|
|
|
+ PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT));
|
|
|
+ pr_warn("Cannot allocate SWIOTLB buffer");
|
|
|
+ no_iotlb_memory = true;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -405,6 +413,9 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
|
|
|
unsigned long offset_slots;
|
|
|
unsigned long max_slots;
|
|
|
|
|
|
+ if (no_iotlb_memory)
|
|
|
+ panic("Can not allocate SWIOTLB buffer earlier and can't now provide you with the DMA bounce buffer");
|
|
|
+
|
|
|
mask = dma_get_seg_boundary(hwdev);
|
|
|
|
|
|
tbl_dma_addr &= mask;
|