diff options
-rw-r--r-- | include/linux/swiotlb.h | 6 | ||||
-rw-r--r-- | lib/swiotlb.c | 30 |
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); | |||
88 | extern int | 88 | extern int |
89 | swiotlb_dma_supported(struct device *hwdev, u64 mask); | 89 | swiotlb_dma_supported(struct device *hwdev, u64 mask); |
90 | 90 | ||
91 | #ifdef CONFIG_SWIOTLB | ||
92 | extern void __init swiotlb_free(void); | ||
93 | #else | ||
94 | static 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 | */ |
98 | static DEFINE_SPINLOCK(io_tlb_lock); | 98 | static DEFINE_SPINLOCK(io_tlb_lock); |
99 | 99 | ||
100 | static int late_alloc; | ||
101 | |||
100 | static int __init | 102 | static int __init |
101 | setup_io_tlb_npages(char *str) | 103 | setup_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 | ||
267 | cleanup4: | 271 | cleanup4: |
@@ -281,6 +285,32 @@ cleanup1: | |||
281 | return -ENOMEM; | 285 | return -ENOMEM; |
282 | } | 286 | } |
283 | 287 | ||
288 | void __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 | |||
284 | static int is_swiotlb_buffer(phys_addr_t paddr) | 314 | static 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) && |