aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>2009-11-10 05:46:18 -0500
committerIngo Molnar <mingo@elte.hu>2009-11-10 06:31:52 -0500
commit5740afdb68abadc473fd5392df733558a58c1254 (patch)
tree82f87512446607118d48b0e6db9f011abd5e1124
parent9f993ac3f708b661207ed7de521f245586217a68 (diff)
swiotlb: Add swiotlb_free() function
swiotlb_free() function frees all allocated memory for swiotlb. We need to initialize swiotlb before IOMMU initialization (x86 and powerpc needs to allocate memory from bootmem allocator). If IOMMU initialization is successful, we need to free swiotlb resource (don't want to waste 64MB). Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Cc: chrisw@sous-sol.org Cc: dwmw2@infradead.org Cc: joerg.roedel@amd.com Cc: muli@il.ibm.com LKML-Reference: <1257849980-22640-8-git-send-email-fujita.tomonori@lab.ntt.co.jp> [ -v2: build fix for the !CONFIG_SWIOTLB case ] Signed-off-by: Ingo Molnar <mingo@elte.hu>
-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) &&