diff options
Diffstat (limited to 'lib')
-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, | |||
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; |