aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/swiotlb.h6
-rw-r--r--lib/swiotlb.c30
2 files changed, 36 insertions, 0 deletions
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index 73b1f1cec423..59bafa690290 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -88,4 +88,10 @@ swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr);
88extern int 88extern int
89swiotlb_dma_supported(struct device *hwdev, u64 mask); 89swiotlb_dma_supported(struct device *hwdev, u64 mask);
90 90
91#ifdef CONFIG_SWIOTLB
92extern void __init swiotlb_free(void);
93#else
94static inline void swiotlb_free(void) { }
95#endif
96
91#endif /* __LINUX_SWIOTLB_H */ 97#endif /* __LINUX_SWIOTLB_H */
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index ac25cd28e807..eee512b63f17 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -97,6 +97,8 @@ static phys_addr_t *io_tlb_orig_addr;
97 */ 97 */
98static DEFINE_SPINLOCK(io_tlb_lock); 98static DEFINE_SPINLOCK(io_tlb_lock);
99 99
100static int late_alloc;
101
100static int __init 102static int __init
101setup_io_tlb_npages(char *str) 103setup_io_tlb_npages(char *str)
102{ 104{
@@ -262,6 +264,8 @@ swiotlb_late_init_with_default_size(size_t default_size)
262 264
263 swiotlb_print_info(bytes); 265 swiotlb_print_info(bytes);
264 266
267 late_alloc = 1;
268
265 return 0; 269 return 0;
266 270
267cleanup4: 271cleanup4:
@@ -281,6 +285,32 @@ cleanup1:
281 return -ENOMEM; 285 return -ENOMEM;
282} 286}
283 287
288void __init swiotlb_free(void)
289{
290 if (!io_tlb_overflow_buffer)
291 return;
292
293 if (late_alloc) {
294 free_pages((unsigned long)io_tlb_overflow_buffer,
295 get_order(io_tlb_overflow));
296 free_pages((unsigned long)io_tlb_orig_addr,
297 get_order(io_tlb_nslabs * sizeof(phys_addr_t)));
298 free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs *
299 sizeof(int)));
300 free_pages((unsigned long)io_tlb_start,
301 get_order(io_tlb_nslabs << IO_TLB_SHIFT));
302 } else {
303 free_bootmem_late(__pa(io_tlb_overflow_buffer),
304 io_tlb_overflow);
305 free_bootmem_late(__pa(io_tlb_orig_addr),
306 io_tlb_nslabs * sizeof(phys_addr_t));
307 free_bootmem_late(__pa(io_tlb_list),
308 io_tlb_nslabs * sizeof(int));
309 free_bootmem_late(__pa(io_tlb_start),
310 io_tlb_nslabs << IO_TLB_SHIFT);
311 }
312}
313
284static int is_swiotlb_buffer(phys_addr_t paddr) 314static int is_swiotlb_buffer(phys_addr_t paddr)
285{ 315{
286 return paddr >= virt_to_phys(io_tlb_start) && 316 return paddr >= virt_to_phys(io_tlb_start) &&