diff options
-rw-r--r-- | lib/swiotlb.c | 120 |
1 files changed, 30 insertions, 90 deletions
diff --git a/lib/swiotlb.c b/lib/swiotlb.c index 3657da8ebbc3..98a7a4450e02 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c | |||
@@ -89,10 +89,7 @@ static unsigned int io_tlb_index; | |||
89 | * We need to save away the original address corresponding to a mapped entry | 89 | * We need to save away the original address corresponding to a mapped entry |
90 | * for the sync operations. | 90 | * for the sync operations. |
91 | */ | 91 | */ |
92 | static struct swiotlb_phys_addr { | 92 | static phys_addr_t *io_tlb_orig_addr; |
93 | struct page *page; | ||
94 | unsigned int offset; | ||
95 | } *io_tlb_orig_addr; | ||
96 | 93 | ||
97 | /* | 94 | /* |
98 | * Protect the above data structures in the map and unmap calls | 95 | * Protect the above data structures in the map and unmap calls |
@@ -204,7 +201,7 @@ swiotlb_init_with_default_size(size_t default_size) | |||
204 | for (i = 0; i < io_tlb_nslabs; i++) | 201 | for (i = 0; i < io_tlb_nslabs; i++) |
205 | io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); | 202 | io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); |
206 | io_tlb_index = 0; | 203 | io_tlb_index = 0; |
207 | io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(struct swiotlb_phys_addr)); | 204 | io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(phys_addr_t)); |
208 | 205 | ||
209 | /* | 206 | /* |
210 | * Get the overflow emergency buffer | 207 | * Get the overflow emergency buffer |
@@ -278,12 +275,14 @@ swiotlb_late_init_with_default_size(size_t default_size) | |||
278 | io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); | 275 | io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); |
279 | io_tlb_index = 0; | 276 | io_tlb_index = 0; |
280 | 277 | ||
281 | io_tlb_orig_addr = (struct swiotlb_phys_addr *)__get_free_pages(GFP_KERNEL, | 278 | io_tlb_orig_addr = (phys_addr_t *) |
282 | get_order(io_tlb_nslabs * sizeof(struct swiotlb_phys_addr))); | 279 | __get_free_pages(GFP_KERNEL, |
280 | get_order(io_tlb_nslabs * | ||
281 | sizeof(phys_addr_t))); | ||
283 | if (!io_tlb_orig_addr) | 282 | if (!io_tlb_orig_addr) |
284 | goto cleanup3; | 283 | goto cleanup3; |
285 | 284 | ||
286 | memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(struct swiotlb_phys_addr)); | 285 | memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(phys_addr_t)); |
287 | 286 | ||
288 | /* | 287 | /* |
289 | * Get the overflow emergency buffer | 288 | * Get the overflow emergency buffer |
@@ -298,8 +297,8 @@ swiotlb_late_init_with_default_size(size_t default_size) | |||
298 | return 0; | 297 | return 0; |
299 | 298 | ||
300 | cleanup4: | 299 | cleanup4: |
301 | free_pages((unsigned long)io_tlb_orig_addr, get_order(io_tlb_nslabs * | 300 | free_pages((unsigned long)io_tlb_orig_addr, |
302 | sizeof(char *))); | 301 | get_order(io_tlb_nslabs * sizeof(phys_addr_t))); |
303 | io_tlb_orig_addr = NULL; | 302 | io_tlb_orig_addr = NULL; |
304 | cleanup3: | 303 | cleanup3: |
305 | free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs * | 304 | free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs * |
@@ -330,59 +329,11 @@ static int is_swiotlb_buffer(char *addr) | |||
330 | return addr >= io_tlb_start && addr < io_tlb_end; | 329 | return addr >= io_tlb_start && addr < io_tlb_end; |
331 | } | 330 | } |
332 | 331 | ||
333 | static struct swiotlb_phys_addr swiotlb_bus_to_phys_addr(char *dma_addr) | ||
334 | { | ||
335 | int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; | ||
336 | struct swiotlb_phys_addr buffer = io_tlb_orig_addr[index]; | ||
337 | buffer.offset += (long)dma_addr & ((1 << IO_TLB_SHIFT) - 1); | ||
338 | buffer.page += buffer.offset >> PAGE_SHIFT; | ||
339 | buffer.offset &= PAGE_SIZE - 1; | ||
340 | return buffer; | ||
341 | } | ||
342 | |||
343 | static void | ||
344 | __sync_single(struct swiotlb_phys_addr buffer, char *dma_addr, size_t size, int dir) | ||
345 | { | ||
346 | if (PageHighMem(buffer.page)) { | ||
347 | size_t len, bytes; | ||
348 | char *dev, *host, *kmp; | ||
349 | |||
350 | len = size; | ||
351 | while (len != 0) { | ||
352 | unsigned long flags; | ||
353 | |||
354 | bytes = len; | ||
355 | if ((bytes + buffer.offset) > PAGE_SIZE) | ||
356 | bytes = PAGE_SIZE - buffer.offset; | ||
357 | local_irq_save(flags); /* protects KM_BOUNCE_READ */ | ||
358 | kmp = kmap_atomic(buffer.page, KM_BOUNCE_READ); | ||
359 | dev = dma_addr + size - len; | ||
360 | host = kmp + buffer.offset; | ||
361 | if (dir == DMA_FROM_DEVICE) | ||
362 | memcpy(host, dev, bytes); | ||
363 | else | ||
364 | memcpy(dev, host, bytes); | ||
365 | kunmap_atomic(kmp, KM_BOUNCE_READ); | ||
366 | local_irq_restore(flags); | ||
367 | len -= bytes; | ||
368 | buffer.page++; | ||
369 | buffer.offset = 0; | ||
370 | } | ||
371 | } else { | ||
372 | void *v = page_address(buffer.page) + buffer.offset; | ||
373 | |||
374 | if (dir == DMA_TO_DEVICE) | ||
375 | memcpy(dma_addr, v, size); | ||
376 | else | ||
377 | memcpy(v, dma_addr, size); | ||
378 | } | ||
379 | } | ||
380 | |||
381 | /* | 332 | /* |
382 | * Allocates bounce buffer and returns its kernel virtual address. | 333 | * Allocates bounce buffer and returns its kernel virtual address. |
383 | */ | 334 | */ |
384 | static void * | 335 | static void * |
385 | map_single(struct device *hwdev, struct swiotlb_phys_addr buffer, size_t size, int dir) | 336 | map_single(struct device *hwdev, phys_addr_t phys, size_t size, int dir) |
386 | { | 337 | { |
387 | unsigned long flags; | 338 | unsigned long flags; |
388 | char *dma_addr; | 339 | char *dma_addr; |
@@ -392,7 +343,6 @@ map_single(struct device *hwdev, struct swiotlb_phys_addr buffer, size_t size, i | |||
392 | unsigned long mask; | 343 | unsigned long mask; |
393 | unsigned long offset_slots; | 344 | unsigned long offset_slots; |
394 | unsigned long max_slots; | 345 | unsigned long max_slots; |
395 | struct swiotlb_phys_addr slot_buf; | ||
396 | 346 | ||
397 | mask = dma_get_seg_boundary(hwdev); | 347 | mask = dma_get_seg_boundary(hwdev); |
398 | start_dma_addr = swiotlb_virt_to_bus(hwdev, io_tlb_start) & mask; | 348 | start_dma_addr = swiotlb_virt_to_bus(hwdev, io_tlb_start) & mask; |
@@ -477,15 +427,10 @@ found: | |||
477 | * This is needed when we sync the memory. Then we sync the buffer if | 427 | * This is needed when we sync the memory. Then we sync the buffer if |
478 | * needed. | 428 | * needed. |
479 | */ | 429 | */ |
480 | slot_buf = buffer; | 430 | for (i = 0; i < nslots; i++) |
481 | for (i = 0; i < nslots; i++) { | 431 | io_tlb_orig_addr[index+i] = phys + (i << IO_TLB_SHIFT); |
482 | slot_buf.page += slot_buf.offset >> PAGE_SHIFT; | ||
483 | slot_buf.offset &= PAGE_SIZE - 1; | ||
484 | io_tlb_orig_addr[index+i] = slot_buf; | ||
485 | slot_buf.offset += 1 << IO_TLB_SHIFT; | ||
486 | } | ||
487 | if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) | 432 | if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) |
488 | __sync_single(buffer, dma_addr, size, DMA_TO_DEVICE); | 433 | memcpy(dma_addr, phys_to_virt(phys), size); |
489 | 434 | ||
490 | return dma_addr; | 435 | return dma_addr; |
491 | } | 436 | } |
@@ -499,17 +444,17 @@ unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir) | |||
499 | unsigned long flags; | 444 | unsigned long flags; |
500 | int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT; | 445 | int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT; |
501 | int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; | 446 | int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; |
502 | struct swiotlb_phys_addr buffer = swiotlb_bus_to_phys_addr(dma_addr); | 447 | phys_addr_t phys = io_tlb_orig_addr[index]; |
503 | 448 | ||
504 | /* | 449 | /* |
505 | * First, sync the memory before unmapping the entry | 450 | * First, sync the memory before unmapping the entry |
506 | */ | 451 | */ |
507 | if ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)) | 452 | if (phys && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL))) |
508 | /* | 453 | /* |
509 | * bounce... copy the data back into the original buffer * and | 454 | * bounce... copy the data back into the original buffer * and |
510 | * delete the bounce buffer. | 455 | * delete the bounce buffer. |
511 | */ | 456 | */ |
512 | __sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE); | 457 | memcpy(phys_to_virt(phys), dma_addr, size); |
513 | 458 | ||
514 | /* | 459 | /* |
515 | * Return the buffer to the free list by setting the corresponding | 460 | * Return the buffer to the free list by setting the corresponding |
@@ -541,18 +486,21 @@ static void | |||
541 | sync_single(struct device *hwdev, char *dma_addr, size_t size, | 486 | sync_single(struct device *hwdev, char *dma_addr, size_t size, |
542 | int dir, int target) | 487 | int dir, int target) |
543 | { | 488 | { |
544 | struct swiotlb_phys_addr buffer = swiotlb_bus_to_phys_addr(dma_addr); | 489 | int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; |
490 | phys_addr_t phys = io_tlb_orig_addr[index]; | ||
491 | |||
492 | phys += ((unsigned long)dma_addr & ((1 << IO_TLB_SHIFT) - 1)); | ||
545 | 493 | ||
546 | switch (target) { | 494 | switch (target) { |
547 | case SYNC_FOR_CPU: | 495 | case SYNC_FOR_CPU: |
548 | if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)) | 496 | if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)) |
549 | __sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE); | 497 | memcpy(phys_to_virt(phys), dma_addr, size); |
550 | else | 498 | else |
551 | BUG_ON(dir != DMA_TO_DEVICE); | 499 | BUG_ON(dir != DMA_TO_DEVICE); |
552 | break; | 500 | break; |
553 | case SYNC_FOR_DEVICE: | 501 | case SYNC_FOR_DEVICE: |
554 | if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)) | 502 | if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)) |
555 | __sync_single(buffer, dma_addr, size, DMA_TO_DEVICE); | 503 | memcpy(dma_addr, phys_to_virt(phys), size); |
556 | else | 504 | else |
557 | BUG_ON(dir != DMA_FROM_DEVICE); | 505 | BUG_ON(dir != DMA_FROM_DEVICE); |
558 | break; | 506 | break; |
@@ -591,10 +539,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size, | |||
591 | * swiotlb_map_single(), which will grab memory from | 539 | * swiotlb_map_single(), which will grab memory from |
592 | * the lowest available address range. | 540 | * the lowest available address range. |
593 | */ | 541 | */ |
594 | struct swiotlb_phys_addr buffer; | 542 | ret = map_single(hwdev, 0, size, DMA_FROM_DEVICE); |
595 | buffer.page = virt_to_page(NULL); | ||
596 | buffer.offset = 0; | ||
597 | ret = map_single(hwdev, buffer, size, DMA_FROM_DEVICE); | ||
598 | if (!ret) | 543 | if (!ret) |
599 | return NULL; | 544 | return NULL; |
600 | } | 545 | } |
@@ -662,7 +607,6 @@ swiotlb_map_single_attrs(struct device *hwdev, void *ptr, size_t size, | |||
662 | { | 607 | { |
663 | dma_addr_t dev_addr = swiotlb_virt_to_bus(hwdev, ptr); | 608 | dma_addr_t dev_addr = swiotlb_virt_to_bus(hwdev, ptr); |
664 | void *map; | 609 | void *map; |
665 | struct swiotlb_phys_addr buffer; | ||
666 | 610 | ||
667 | BUG_ON(dir == DMA_NONE); | 611 | BUG_ON(dir == DMA_NONE); |
668 | /* | 612 | /* |
@@ -677,9 +621,7 @@ swiotlb_map_single_attrs(struct device *hwdev, void *ptr, size_t size, | |||
677 | /* | 621 | /* |
678 | * Oh well, have to allocate and map a bounce buffer. | 622 | * Oh well, have to allocate and map a bounce buffer. |
679 | */ | 623 | */ |
680 | buffer.page = virt_to_page(ptr); | 624 | map = map_single(hwdev, virt_to_phys(ptr), size, dir); |
681 | buffer.offset = (unsigned long)ptr & ~PAGE_MASK; | ||
682 | map = map_single(hwdev, buffer, size, dir); | ||
683 | if (!map) { | 625 | if (!map) { |
684 | swiotlb_full(hwdev, size, dir, 1); | 626 | swiotlb_full(hwdev, size, dir, 1); |
685 | map = io_tlb_overflow_buffer; | 627 | map = io_tlb_overflow_buffer; |
@@ -824,20 +766,18 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems, | |||
824 | int dir, struct dma_attrs *attrs) | 766 | int dir, struct dma_attrs *attrs) |
825 | { | 767 | { |
826 | struct scatterlist *sg; | 768 | struct scatterlist *sg; |
827 | struct swiotlb_phys_addr buffer; | ||
828 | dma_addr_t dev_addr; | ||
829 | int i; | 769 | int i; |
830 | 770 | ||
831 | BUG_ON(dir == DMA_NONE); | 771 | BUG_ON(dir == DMA_NONE); |
832 | 772 | ||
833 | for_each_sg(sgl, sg, nelems, i) { | 773 | for_each_sg(sgl, sg, nelems, i) { |
834 | dev_addr = swiotlb_sg_to_bus(hwdev, sg); | 774 | void *addr = sg_virt(sg); |
835 | if (range_needs_mapping(sg_virt(sg), sg->length) || | 775 | dma_addr_t dev_addr = swiotlb_virt_to_bus(hwdev, addr); |
776 | |||
777 | if (range_needs_mapping(addr, sg->length) || | ||
836 | address_needs_mapping(hwdev, dev_addr, sg->length)) { | 778 | address_needs_mapping(hwdev, dev_addr, sg->length)) { |
837 | void *map; | 779 | void *map = map_single(hwdev, sg_phys(sg), |
838 | buffer.page = sg_page(sg); | 780 | sg->length, dir); |
839 | buffer.offset = sg->offset; | ||
840 | map = map_single(hwdev, buffer, sg->length, dir); | ||
841 | if (!map) { | 781 | if (!map) { |
842 | /* Don't panic here, we expect map_sg users | 782 | /* Don't panic here, we expect map_sg users |
843 | to do proper error handling. */ | 783 | to do proper error handling. */ |