diff options
Diffstat (limited to 'lib/swiotlb.c')
-rw-r--r-- | lib/swiotlb.c | 46 |
1 files changed, 39 insertions, 7 deletions
diff --git a/lib/swiotlb.c b/lib/swiotlb.c index ac25cd28e807..795472d8ae24 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 | { |
@@ -109,6 +111,7 @@ setup_io_tlb_npages(char *str) | |||
109 | ++str; | 111 | ++str; |
110 | if (!strcmp(str, "force")) | 112 | if (!strcmp(str, "force")) |
111 | swiotlb_force = 1; | 113 | swiotlb_force = 1; |
114 | |||
112 | return 1; | 115 | return 1; |
113 | } | 116 | } |
114 | __setup("swiotlb=", setup_io_tlb_npages); | 117 | __setup("swiotlb=", setup_io_tlb_npages); |
@@ -121,8 +124,9 @@ static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev, | |||
121 | return phys_to_dma(hwdev, virt_to_phys(address)); | 124 | return phys_to_dma(hwdev, virt_to_phys(address)); |
122 | } | 125 | } |
123 | 126 | ||
124 | static void swiotlb_print_info(unsigned long bytes) | 127 | void swiotlb_print_info(void) |
125 | { | 128 | { |
129 | unsigned long bytes = io_tlb_nslabs << IO_TLB_SHIFT; | ||
126 | phys_addr_t pstart, pend; | 130 | phys_addr_t pstart, pend; |
127 | 131 | ||
128 | pstart = virt_to_phys(io_tlb_start); | 132 | pstart = virt_to_phys(io_tlb_start); |
@@ -140,7 +144,7 @@ static void swiotlb_print_info(unsigned long bytes) | |||
140 | * structures for the software IO TLB used to implement the DMA API. | 144 | * structures for the software IO TLB used to implement the DMA API. |
141 | */ | 145 | */ |
142 | void __init | 146 | void __init |
143 | swiotlb_init_with_default_size(size_t default_size) | 147 | swiotlb_init_with_default_size(size_t default_size, int verbose) |
144 | { | 148 | { |
145 | unsigned long i, bytes; | 149 | unsigned long i, bytes; |
146 | 150 | ||
@@ -176,14 +180,14 @@ swiotlb_init_with_default_size(size_t default_size) | |||
176 | io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow); | 180 | io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow); |
177 | if (!io_tlb_overflow_buffer) | 181 | if (!io_tlb_overflow_buffer) |
178 | panic("Cannot allocate SWIOTLB overflow buffer!\n"); | 182 | panic("Cannot allocate SWIOTLB overflow buffer!\n"); |
179 | 183 | if (verbose) | |
180 | swiotlb_print_info(bytes); | 184 | swiotlb_print_info(); |
181 | } | 185 | } |
182 | 186 | ||
183 | void __init | 187 | void __init |
184 | swiotlb_init(void) | 188 | swiotlb_init(int verbose) |
185 | { | 189 | { |
186 | swiotlb_init_with_default_size(64 * (1<<20)); /* default to 64MB */ | 190 | swiotlb_init_with_default_size(64 * (1<<20), verbose); /* default to 64MB */ |
187 | } | 191 | } |
188 | 192 | ||
189 | /* | 193 | /* |
@@ -260,7 +264,9 @@ swiotlb_late_init_with_default_size(size_t default_size) | |||
260 | if (!io_tlb_overflow_buffer) | 264 | if (!io_tlb_overflow_buffer) |
261 | goto cleanup4; | 265 | goto cleanup4; |
262 | 266 | ||
263 | swiotlb_print_info(bytes); | 267 | swiotlb_print_info(); |
268 | |||
269 | late_alloc = 1; | ||
264 | 270 | ||
265 | return 0; | 271 | return 0; |
266 | 272 | ||
@@ -281,6 +287,32 @@ cleanup1: | |||
281 | return -ENOMEM; | 287 | return -ENOMEM; |
282 | } | 288 | } |
283 | 289 | ||
290 | void __init swiotlb_free(void) | ||
291 | { | ||
292 | if (!io_tlb_overflow_buffer) | ||
293 | return; | ||
294 | |||
295 | if (late_alloc) { | ||
296 | free_pages((unsigned long)io_tlb_overflow_buffer, | ||
297 | get_order(io_tlb_overflow)); | ||
298 | free_pages((unsigned long)io_tlb_orig_addr, | ||
299 | get_order(io_tlb_nslabs * sizeof(phys_addr_t))); | ||
300 | free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs * | ||
301 | sizeof(int))); | ||
302 | free_pages((unsigned long)io_tlb_start, | ||
303 | get_order(io_tlb_nslabs << IO_TLB_SHIFT)); | ||
304 | } else { | ||
305 | free_bootmem_late(__pa(io_tlb_overflow_buffer), | ||
306 | io_tlb_overflow); | ||
307 | free_bootmem_late(__pa(io_tlb_orig_addr), | ||
308 | io_tlb_nslabs * sizeof(phys_addr_t)); | ||
309 | free_bootmem_late(__pa(io_tlb_list), | ||
310 | io_tlb_nslabs * sizeof(int)); | ||
311 | free_bootmem_late(__pa(io_tlb_start), | ||
312 | io_tlb_nslabs << IO_TLB_SHIFT); | ||
313 | } | ||
314 | } | ||
315 | |||
284 | static int is_swiotlb_buffer(phys_addr_t paddr) | 316 | static int is_swiotlb_buffer(phys_addr_t paddr) |
285 | { | 317 | { |
286 | return paddr >= virt_to_phys(io_tlb_start) && | 318 | return paddr >= virt_to_phys(io_tlb_start) && |