diff options
-rw-r--r-- | arch/mips/cavium-octeon/dma-octeon.c | 3 | ||||
-rw-r--r-- | drivers/xen/swiotlb-xen.c | 4 | ||||
-rw-r--r-- | include/linux/swiotlb.h | 2 | ||||
-rw-r--r-- | lib/swiotlb.c | 47 |
4 files changed, 35 insertions, 21 deletions
diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c index 41dd00884975..02f244475207 100644 --- a/arch/mips/cavium-octeon/dma-octeon.c +++ b/arch/mips/cavium-octeon/dma-octeon.c | |||
@@ -317,7 +317,8 @@ void __init plat_swiotlb_setup(void) | |||
317 | 317 | ||
318 | octeon_swiotlb = alloc_bootmem_low_pages(swiotlbsize); | 318 | octeon_swiotlb = alloc_bootmem_low_pages(swiotlbsize); |
319 | 319 | ||
320 | swiotlb_init_with_tbl(octeon_swiotlb, swiotlb_nslabs, 1); | 320 | if (swiotlb_init_with_tbl(octeon_swiotlb, swiotlb_nslabs, 1) == -ENOMEM) |
321 | panic("Cannot allocate SWIOTLB buffer"); | ||
321 | 322 | ||
322 | mips_dma_map_ops = &octeon_linear_dma_map_ops.dma_map_ops; | 323 | mips_dma_map_ops = &octeon_linear_dma_map_ops.dma_map_ops; |
323 | } | 324 | } |
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index af47e7594460..1d94316f0ea4 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c | |||
@@ -231,7 +231,9 @@ retry: | |||
231 | } | 231 | } |
232 | start_dma_addr = xen_virt_to_bus(xen_io_tlb_start); | 232 | start_dma_addr = xen_virt_to_bus(xen_io_tlb_start); |
233 | if (early) { | 233 | if (early) { |
234 | swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs, verbose); | 234 | if (swiotlb_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs, |
235 | verbose)) | ||
236 | panic("Cannot allocate SWIOTLB buffer"); | ||
235 | rc = 0; | 237 | rc = 0; |
236 | } else | 238 | } else |
237 | rc = swiotlb_late_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs); | 239 | rc = swiotlb_late_init_with_tbl(xen_io_tlb_start, xen_io_tlb_nslabs); |
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h index 071d62c214a6..2de42f9401d2 100644 --- a/include/linux/swiotlb.h +++ b/include/linux/swiotlb.h | |||
@@ -23,7 +23,7 @@ extern int swiotlb_force; | |||
23 | #define IO_TLB_SHIFT 11 | 23 | #define IO_TLB_SHIFT 11 |
24 | 24 | ||
25 | extern void swiotlb_init(int verbose); | 25 | extern void swiotlb_init(int verbose); |
26 | extern void swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose); | 26 | int swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose); |
27 | extern unsigned long swiotlb_nr_tbl(void); | 27 | extern unsigned long swiotlb_nr_tbl(void); |
28 | extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs); | 28 | extern int swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs); |
29 | 29 | ||
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, | |||
122 | return phys_to_dma(hwdev, virt_to_phys(address)); | 122 | return phys_to_dma(hwdev, virt_to_phys(address)); |
123 | } | 123 | } |
124 | 124 | ||
125 | static bool no_iotlb_memory; | ||
126 | |||
125 | void swiotlb_print_info(void) | 127 | void swiotlb_print_info(void) |
126 | { | 128 | { |
127 | unsigned long bytes = io_tlb_nslabs << IO_TLB_SHIFT; | 129 | unsigned long bytes = io_tlb_nslabs << IO_TLB_SHIFT; |
128 | unsigned char *vstart, *vend; | 130 | unsigned char *vstart, *vend; |
129 | 131 | ||
132 | if (no_iotlb_memory) { | ||
133 | pr_warn("software IO TLB: No low mem\n"); | ||
134 | return; | ||
135 | } | ||
136 | |||
130 | vstart = phys_to_virt(io_tlb_start); | 137 | vstart = phys_to_virt(io_tlb_start); |
131 | vend = phys_to_virt(io_tlb_end); | 138 | vend = phys_to_virt(io_tlb_end); |
132 | 139 | ||
@@ -136,7 +143,7 @@ void swiotlb_print_info(void) | |||
136 | bytes >> 20, vstart, vend - 1); | 143 | bytes >> 20, vstart, vend - 1); |
137 | } | 144 | } |
138 | 145 | ||
139 | void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) | 146 | int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) |
140 | { | 147 | { |
141 | void *v_overflow_buffer; | 148 | void *v_overflow_buffer; |
142 | unsigned long i, bytes; | 149 | unsigned long i, bytes; |
@@ -150,9 +157,10 @@ void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) | |||
150 | /* | 157 | /* |
151 | * Get the overflow emergency buffer | 158 | * Get the overflow emergency buffer |
152 | */ | 159 | */ |
153 | v_overflow_buffer = alloc_bootmem_low_pages(PAGE_ALIGN(io_tlb_overflow)); | 160 | v_overflow_buffer = alloc_bootmem_low_pages_nopanic( |
161 | PAGE_ALIGN(io_tlb_overflow)); | ||
154 | if (!v_overflow_buffer) | 162 | if (!v_overflow_buffer) |
155 | panic("Cannot allocate SWIOTLB overflow buffer!\n"); | 163 | return -ENOMEM; |
156 | 164 | ||
157 | io_tlb_overflow_buffer = __pa(v_overflow_buffer); | 165 | io_tlb_overflow_buffer = __pa(v_overflow_buffer); |
158 | 166 | ||
@@ -169,15 +177,19 @@ void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) | |||
169 | 177 | ||
170 | if (verbose) | 178 | if (verbose) |
171 | swiotlb_print_info(); | 179 | swiotlb_print_info(); |
180 | |||
181 | return 0; | ||
172 | } | 182 | } |
173 | 183 | ||
174 | /* | 184 | /* |
175 | * Statically reserve bounce buffer space and initialize bounce buffer data | 185 | * Statically reserve bounce buffer space and initialize bounce buffer data |
176 | * structures for the software IO TLB used to implement the DMA API. | 186 | * structures for the software IO TLB used to implement the DMA API. |
177 | */ | 187 | */ |
178 | static void __init | 188 | void __init |
179 | swiotlb_init_with_default_size(size_t default_size, int verbose) | 189 | swiotlb_init(int verbose) |
180 | { | 190 | { |
191 | /* default to 64MB */ | ||
192 | size_t default_size = 64UL<<20; | ||
181 | unsigned char *vstart; | 193 | unsigned char *vstart; |
182 | unsigned long bytes; | 194 | unsigned long bytes; |
183 | 195 | ||
@@ -188,20 +200,16 @@ swiotlb_init_with_default_size(size_t default_size, int verbose) | |||
188 | 200 | ||
189 | bytes = io_tlb_nslabs << IO_TLB_SHIFT; | 201 | bytes = io_tlb_nslabs << IO_TLB_SHIFT; |
190 | 202 | ||
191 | /* | 203 | /* Get IO TLB memory from the low pages */ |
192 | * Get IO TLB memory from the low pages | 204 | vstart = alloc_bootmem_low_pages_nopanic(PAGE_ALIGN(bytes)); |
193 | */ | 205 | if (vstart && !swiotlb_init_with_tbl(vstart, io_tlb_nslabs, verbose)) |
194 | vstart = alloc_bootmem_low_pages(PAGE_ALIGN(bytes)); | 206 | return; |
195 | if (!vstart) | ||
196 | panic("Cannot allocate SWIOTLB buffer"); | ||
197 | |||
198 | swiotlb_init_with_tbl(vstart, io_tlb_nslabs, verbose); | ||
199 | } | ||
200 | 207 | ||
201 | void __init | 208 | if (io_tlb_start) |
202 | swiotlb_init(int verbose) | 209 | free_bootmem(io_tlb_start, |
203 | { | 210 | PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT)); |
204 | swiotlb_init_with_default_size(64 * (1<<20), verbose); /* default to 64MB */ | 211 | pr_warn("Cannot allocate SWIOTLB buffer"); |
212 | no_iotlb_memory = true; | ||
205 | } | 213 | } |
206 | 214 | ||
207 | /* | 215 | /* |
@@ -405,6 +413,9 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev, | |||
405 | unsigned long offset_slots; | 413 | unsigned long offset_slots; |
406 | unsigned long max_slots; | 414 | unsigned long max_slots; |
407 | 415 | ||
416 | if (no_iotlb_memory) | ||
417 | panic("Can not allocate SWIOTLB buffer earlier and can't now provide you with the DMA bounce buffer"); | ||
418 | |||
408 | mask = dma_get_seg_boundary(hwdev); | 419 | mask = dma_get_seg_boundary(hwdev); |
409 | 420 | ||
410 | tbl_dma_addr &= mask; | 421 | tbl_dma_addr &= mask; |