aboutsummaryrefslogtreecommitdiffstats
path: root/lib/swiotlb.c
diff options
context:
space:
mode:
authorAlexander Duyck <alexander.h.duyck@intel.com>2012-10-15 13:19:28 -0400
committerKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>2012-10-30 09:32:06 -0400
commitff7204a74931fc67ed13d8febbc322a46833c1fa (patch)
tree3f1eccbd9bedf1109c6bbc434805feb52c1dd1d0 /lib/swiotlb.c
parentc40dba06e9a27d673197a2083828f13eff16b2ab (diff)
swiotlb: Make io_tlb_start a physical address instead of a virtual one
This change replaces all references to the virtual address for io_tlb_start with references to the physical address io_tlb_end. The main advantage of replacing the virtual address with a physical address is that we can avoid having to do multiple translations from the virtual address to the physical one needed for testing an existing DMA address. Signed-off-by: Alexander Duyck <alexander.h.duyck@intel.com> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Diffstat (limited to 'lib/swiotlb.c')
-rw-r--r--lib/swiotlb.c58
1 files changed, 29 insertions, 29 deletions
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index c0cbfa1116c0..8c4791f17ec1 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -57,8 +57,7 @@ int swiotlb_force;
57 * swiotlb_tbl_sync_single_*, to see if the memory was in fact allocated by this 57 * swiotlb_tbl_sync_single_*, to see if the memory was in fact allocated by this
58 * API. 58 * API.
59 */ 59 */
60static char *io_tlb_start; 60static phys_addr_t io_tlb_start, io_tlb_end;
61static phys_addr_t io_tlb_end;
62 61
63/* 62/*
64 * The number of IO TLB blocks (in groups of 64) between io_tlb_start and 63 * The number of IO TLB blocks (in groups of 64) between io_tlb_start and
@@ -126,16 +125,15 @@ static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
126void swiotlb_print_info(void) 125void swiotlb_print_info(void)
127{ 126{
128 unsigned long bytes = io_tlb_nslabs << IO_TLB_SHIFT; 127 unsigned long bytes = io_tlb_nslabs << IO_TLB_SHIFT;
129 phys_addr_t pstart; 128 unsigned char *vstart, *vend;
130 unsigned char *vend;
131 129
132 pstart = virt_to_phys(io_tlb_start); 130 vstart = phys_to_virt(io_tlb_start);
133 vend = phys_to_virt(io_tlb_end); 131 vend = phys_to_virt(io_tlb_end);
134 132
135 printk(KERN_INFO "software IO TLB [mem %#010llx-%#010llx] (%luMB) mapped at [%p-%p]\n", 133 printk(KERN_INFO "software IO TLB [mem %#010llx-%#010llx] (%luMB) mapped at [%p-%p]\n",
136 (unsigned long long)pstart, 134 (unsigned long long)io_tlb_start,
137 (unsigned long long)io_tlb_end, 135 (unsigned long long)io_tlb_end,
138 bytes >> 20, io_tlb_start, vend - 1); 136 bytes >> 20, vstart, vend - 1);
139} 137}
140 138
141void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) 139void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
@@ -145,8 +143,8 @@ void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
145 bytes = nslabs << IO_TLB_SHIFT; 143 bytes = nslabs << IO_TLB_SHIFT;
146 144
147 io_tlb_nslabs = nslabs; 145 io_tlb_nslabs = nslabs;
148 io_tlb_start = tlb; 146 io_tlb_start = __pa(tlb);
149 io_tlb_end = __pa(io_tlb_start) + bytes; 147 io_tlb_end = io_tlb_start + bytes;
150 148
151 /* 149 /*
152 * Allocate and initialize the free list array. This array is used 150 * Allocate and initialize the free list array. This array is used
@@ -176,6 +174,7 @@ void __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
176static void __init 174static void __init
177swiotlb_init_with_default_size(size_t default_size, int verbose) 175swiotlb_init_with_default_size(size_t default_size, int verbose)
178{ 176{
177 unsigned char *vstart;
179 unsigned long bytes; 178 unsigned long bytes;
180 179
181 if (!io_tlb_nslabs) { 180 if (!io_tlb_nslabs) {
@@ -188,11 +187,11 @@ swiotlb_init_with_default_size(size_t default_size, int verbose)
188 /* 187 /*
189 * Get IO TLB memory from the low pages 188 * Get IO TLB memory from the low pages
190 */ 189 */
191 io_tlb_start = alloc_bootmem_low_pages(PAGE_ALIGN(bytes)); 190 vstart = alloc_bootmem_low_pages(PAGE_ALIGN(bytes));
192 if (!io_tlb_start) 191 if (!vstart)
193 panic("Cannot allocate SWIOTLB buffer"); 192 panic("Cannot allocate SWIOTLB buffer");
194 193
195 swiotlb_init_with_tbl(io_tlb_start, io_tlb_nslabs, verbose); 194 swiotlb_init_with_tbl(vstart, io_tlb_nslabs, verbose);
196} 195}
197 196
198void __init 197void __init
@@ -210,6 +209,7 @@ int
210swiotlb_late_init_with_default_size(size_t default_size) 209swiotlb_late_init_with_default_size(size_t default_size)
211{ 210{
212 unsigned long bytes, req_nslabs = io_tlb_nslabs; 211 unsigned long bytes, req_nslabs = io_tlb_nslabs;
212 unsigned char *vstart = NULL;
213 unsigned int order; 213 unsigned int order;
214 int rc = 0; 214 int rc = 0;
215 215
@@ -226,14 +226,14 @@ swiotlb_late_init_with_default_size(size_t default_size)
226 bytes = io_tlb_nslabs << IO_TLB_SHIFT; 226 bytes = io_tlb_nslabs << IO_TLB_SHIFT;
227 227
228 while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) { 228 while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) {
229 io_tlb_start = (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN, 229 vstart = (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN,
230 order); 230 order);
231 if (io_tlb_start) 231 if (vstart)
232 break; 232 break;
233 order--; 233 order--;
234 } 234 }
235 235
236 if (!io_tlb_start) { 236 if (!vstart) {
237 io_tlb_nslabs = req_nslabs; 237 io_tlb_nslabs = req_nslabs;
238 return -ENOMEM; 238 return -ENOMEM;
239 } 239 }
@@ -242,9 +242,9 @@ swiotlb_late_init_with_default_size(size_t default_size)
242 "for software IO TLB\n", (PAGE_SIZE << order) >> 20); 242 "for software IO TLB\n", (PAGE_SIZE << order) >> 20);
243 io_tlb_nslabs = SLABS_PER_PAGE << order; 243 io_tlb_nslabs = SLABS_PER_PAGE << order;
244 } 244 }
245 rc = swiotlb_late_init_with_tbl(io_tlb_start, io_tlb_nslabs); 245 rc = swiotlb_late_init_with_tbl(vstart, io_tlb_nslabs);
246 if (rc) 246 if (rc)
247 free_pages((unsigned long)io_tlb_start, order); 247 free_pages((unsigned long)vstart, order);
248 return rc; 248 return rc;
249} 249}
250 250
@@ -256,10 +256,10 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs)
256 bytes = nslabs << IO_TLB_SHIFT; 256 bytes = nslabs << IO_TLB_SHIFT;
257 257
258 io_tlb_nslabs = nslabs; 258 io_tlb_nslabs = nslabs;
259 io_tlb_start = tlb; 259 io_tlb_start = virt_to_phys(tlb);
260 io_tlb_end = virt_to_phys(io_tlb_start) + bytes; 260 io_tlb_end = io_tlb_start + bytes;
261 261
262 memset(io_tlb_start, 0, bytes); 262 memset(tlb, 0, bytes);
263 263
264 /* 264 /*
265 * Allocate and initialize the free list array. This array is used 265 * Allocate and initialize the free list array. This array is used
@@ -308,7 +308,7 @@ cleanup3:
308 io_tlb_list = NULL; 308 io_tlb_list = NULL;
309cleanup2: 309cleanup2:
310 io_tlb_end = 0; 310 io_tlb_end = 0;
311 io_tlb_start = NULL; 311 io_tlb_start = 0;
312 io_tlb_nslabs = 0; 312 io_tlb_nslabs = 0;
313 return -ENOMEM; 313 return -ENOMEM;
314} 314}
@@ -325,7 +325,7 @@ void __init swiotlb_free(void)
325 get_order(io_tlb_nslabs * sizeof(phys_addr_t))); 325 get_order(io_tlb_nslabs * sizeof(phys_addr_t)));
326 free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs * 326 free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs *
327 sizeof(int))); 327 sizeof(int)));
328 free_pages((unsigned long)io_tlb_start, 328 free_pages((unsigned long)phys_to_virt(io_tlb_start),
329 get_order(io_tlb_nslabs << IO_TLB_SHIFT)); 329 get_order(io_tlb_nslabs << IO_TLB_SHIFT));
330 } else { 330 } else {
331 free_bootmem_late(__pa(io_tlb_overflow_buffer), 331 free_bootmem_late(__pa(io_tlb_overflow_buffer),
@@ -334,7 +334,7 @@ void __init swiotlb_free(void)
334 PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t))); 334 PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t)));
335 free_bootmem_late(__pa(io_tlb_list), 335 free_bootmem_late(__pa(io_tlb_list),
336 PAGE_ALIGN(io_tlb_nslabs * sizeof(int))); 336 PAGE_ALIGN(io_tlb_nslabs * sizeof(int)));
337 free_bootmem_late(__pa(io_tlb_start), 337 free_bootmem_late(io_tlb_start,
338 PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT)); 338 PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT));
339 } 339 }
340 io_tlb_nslabs = 0; 340 io_tlb_nslabs = 0;
@@ -342,7 +342,7 @@ void __init swiotlb_free(void)
342 342
343static int is_swiotlb_buffer(phys_addr_t paddr) 343static int is_swiotlb_buffer(phys_addr_t paddr)
344{ 344{
345 return paddr >= virt_to_phys(io_tlb_start) && paddr < io_tlb_end; 345 return paddr >= io_tlb_start && paddr < io_tlb_end;
346} 346}
347 347
348/* 348/*
@@ -455,7 +455,7 @@ void *swiotlb_tbl_map_single(struct device *hwdev, dma_addr_t tbl_dma_addr,
455 io_tlb_list[i] = 0; 455 io_tlb_list[i] = 0;
456 for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE - 1) && io_tlb_list[i]; i--) 456 for (i = index - 1; (OFFSET(i, IO_TLB_SEGSIZE) != IO_TLB_SEGSIZE - 1) && io_tlb_list[i]; i--)
457 io_tlb_list[i] = ++count; 457 io_tlb_list[i] = ++count;
458 dma_addr = io_tlb_start + (index << IO_TLB_SHIFT); 458 dma_addr = (char *)phys_to_virt(io_tlb_start) + (index << IO_TLB_SHIFT);
459 459
460 /* 460 /*
461 * Update the indices to avoid searching in the next 461 * Update the indices to avoid searching in the next
@@ -499,7 +499,7 @@ static void *
499map_single(struct device *hwdev, phys_addr_t phys, size_t size, 499map_single(struct device *hwdev, phys_addr_t phys, size_t size,
500 enum dma_data_direction dir) 500 enum dma_data_direction dir)
501{ 501{
502 dma_addr_t start_dma_addr = swiotlb_virt_to_bus(hwdev, io_tlb_start); 502 dma_addr_t start_dma_addr = phys_to_dma(hwdev, io_tlb_start);
503 503
504 return swiotlb_tbl_map_single(hwdev, start_dma_addr, phys, size, dir); 504 return swiotlb_tbl_map_single(hwdev, start_dma_addr, phys, size, dir);
505} 505}
@@ -513,7 +513,7 @@ swiotlb_tbl_unmap_single(struct device *hwdev, char *dma_addr, size_t size,
513{ 513{
514 unsigned long flags; 514 unsigned long flags;
515 int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT; 515 int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
516 int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; 516 int index = (dma_addr - (char *)phys_to_virt(io_tlb_start)) >> IO_TLB_SHIFT;
517 phys_addr_t phys = io_tlb_orig_addr[index]; 517 phys_addr_t phys = io_tlb_orig_addr[index];
518 518
519 /* 519 /*
@@ -554,7 +554,7 @@ swiotlb_tbl_sync_single(struct device *hwdev, char *dma_addr, size_t size,
554 enum dma_data_direction dir, 554 enum dma_data_direction dir,
555 enum dma_sync_target target) 555 enum dma_sync_target target)
556{ 556{
557 int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; 557 int index = (dma_addr - (char *)phys_to_virt(io_tlb_start)) >> IO_TLB_SHIFT;
558 phys_addr_t phys = io_tlb_orig_addr[index]; 558 phys_addr_t phys = io_tlb_orig_addr[index];
559 559
560 phys += ((unsigned long)dma_addr & ((1 << IO_TLB_SHIFT) - 1)); 560 phys += ((unsigned long)dma_addr & ((1 << IO_TLB_SHIFT) - 1));