summaryrefslogtreecommitdiffstats
path: root/lib/swiotlb.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2013-04-20 09:16:44 -0700
committerH. Peter Anvin <hpa@linux.intel.com>2013-04-20 09:16:44 -0700
commitf53f292eeaa234615c31a1306babe703fc4263f2 (patch)
tree707b0933a20f7dc05495e974243a23b5c9f8c918 /lib/swiotlb.c
parent15b9c359f288b09003cb70f7ed204affc0c6614d (diff)
parenta9499fa7cd3fd4824a7202d00c766b269fa3bda6 (diff)
downloadlinux-f53f292eeaa234615c31a1306babe703fc4263f2.tar.bz2
Merge remote-tracking branch 'efi/chainsaw' into x86/efi
Resolved Conflicts: drivers/firmware/efivars.c fs/efivarsfs/file.c Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'lib/swiotlb.c')
-rw-r--r--lib/swiotlb.c47
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;