diff options
Diffstat (limited to 'lib/swiotlb.c')
| -rw-r--r-- | lib/swiotlb.c | 47 | 
1 files changed, 29 insertions, 18 deletions
| diff --git a/lib/swiotlb.c b/lib/swiotlb.c index 196b06984dec..bfe02b8fc55b 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c @@ -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; |