diff options
| -rw-r--r-- | lib/swiotlb.c | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/lib/swiotlb.c b/lib/swiotlb.c index 649d097853a1..4abda074ea45 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c | |||
| @@ -86,6 +86,7 @@ static unsigned int io_tlb_index; | |||
| 86 | * We need to save away the original address corresponding to a mapped entry | 86 | * We need to save away the original address corresponding to a mapped entry |
| 87 | * for the sync operations. | 87 | * for the sync operations. |
| 88 | */ | 88 | */ |
| 89 | #define INVALID_PHYS_ADDR (~(phys_addr_t)0) | ||
| 89 | static phys_addr_t *io_tlb_orig_addr; | 90 | static phys_addr_t *io_tlb_orig_addr; |
| 90 | 91 | ||
| 91 | /* | 92 | /* |
| @@ -188,12 +189,14 @@ int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose) | |||
| 188 | io_tlb_list = memblock_virt_alloc( | 189 | io_tlb_list = memblock_virt_alloc( |
| 189 | PAGE_ALIGN(io_tlb_nslabs * sizeof(int)), | 190 | PAGE_ALIGN(io_tlb_nslabs * sizeof(int)), |
| 190 | PAGE_SIZE); | 191 | PAGE_SIZE); |
| 191 | for (i = 0; i < io_tlb_nslabs; i++) | ||
| 192 | io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); | ||
| 193 | io_tlb_index = 0; | ||
| 194 | io_tlb_orig_addr = memblock_virt_alloc( | 192 | io_tlb_orig_addr = memblock_virt_alloc( |
| 195 | PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t)), | 193 | PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t)), |
| 196 | PAGE_SIZE); | 194 | PAGE_SIZE); |
| 195 | for (i = 0; i < io_tlb_nslabs; i++) { | ||
| 196 | io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); | ||
| 197 | io_tlb_orig_addr[i] = INVALID_PHYS_ADDR; | ||
| 198 | } | ||
| 199 | io_tlb_index = 0; | ||
| 197 | 200 | ||
| 198 | if (verbose) | 201 | if (verbose) |
| 199 | swiotlb_print_info(); | 202 | swiotlb_print_info(); |
| @@ -313,10 +316,6 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs) | |||
| 313 | if (!io_tlb_list) | 316 | if (!io_tlb_list) |
| 314 | goto cleanup3; | 317 | goto cleanup3; |
| 315 | 318 | ||
| 316 | for (i = 0; i < io_tlb_nslabs; i++) | ||
| 317 | io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); | ||
| 318 | io_tlb_index = 0; | ||
| 319 | |||
| 320 | io_tlb_orig_addr = (phys_addr_t *) | 319 | io_tlb_orig_addr = (phys_addr_t *) |
| 321 | __get_free_pages(GFP_KERNEL, | 320 | __get_free_pages(GFP_KERNEL, |
| 322 | get_order(io_tlb_nslabs * | 321 | get_order(io_tlb_nslabs * |
| @@ -324,7 +323,11 @@ swiotlb_late_init_with_tbl(char *tlb, unsigned long nslabs) | |||
| 324 | if (!io_tlb_orig_addr) | 323 | if (!io_tlb_orig_addr) |
| 325 | goto cleanup4; | 324 | goto cleanup4; |
| 326 | 325 | ||
| 327 | memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(phys_addr_t)); | 326 | for (i = 0; i < io_tlb_nslabs; i++) { |
| 327 | io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); | ||
| 328 | io_tlb_orig_addr[i] = INVALID_PHYS_ADDR; | ||
| 329 | } | ||
| 330 | io_tlb_index = 0; | ||
| 328 | 331 | ||
| 329 | swiotlb_print_info(); | 332 | swiotlb_print_info(); |
| 330 | 333 | ||
| @@ -556,7 +559,8 @@ void swiotlb_tbl_unmap_single(struct device *hwdev, phys_addr_t tlb_addr, | |||
| 556 | /* | 559 | /* |
| 557 | * First, sync the memory before unmapping the entry | 560 | * First, sync the memory before unmapping the entry |
| 558 | */ | 561 | */ |
| 559 | if (orig_addr && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL))) | 562 | if (orig_addr != INVALID_PHYS_ADDR && |
| 563 | ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL))) | ||
| 560 | swiotlb_bounce(orig_addr, tlb_addr, size, DMA_FROM_DEVICE); | 564 | swiotlb_bounce(orig_addr, tlb_addr, size, DMA_FROM_DEVICE); |
| 561 | 565 | ||
| 562 | /* | 566 | /* |
| @@ -573,8 +577,10 @@ void swiotlb_tbl_unmap_single(struct device *hwdev, phys_addr_t tlb_addr, | |||
| 573 | * Step 1: return the slots to the free list, merging the | 577 | * Step 1: return the slots to the free list, merging the |
| 574 | * slots with superceeding slots | 578 | * slots with superceeding slots |
| 575 | */ | 579 | */ |
| 576 | for (i = index + nslots - 1; i >= index; i--) | 580 | for (i = index + nslots - 1; i >= index; i--) { |
| 577 | io_tlb_list[i] = ++count; | 581 | io_tlb_list[i] = ++count; |
| 582 | io_tlb_orig_addr[i] = INVALID_PHYS_ADDR; | ||
| 583 | } | ||
| 578 | /* | 584 | /* |
| 579 | * Step 2: merge the returned slots with the preceding slots, | 585 | * Step 2: merge the returned slots with the preceding slots, |
| 580 | * if available (non zero) | 586 | * if available (non zero) |
| @@ -593,6 +599,8 @@ void swiotlb_tbl_sync_single(struct device *hwdev, phys_addr_t tlb_addr, | |||
| 593 | int index = (tlb_addr - io_tlb_start) >> IO_TLB_SHIFT; | 599 | int index = (tlb_addr - io_tlb_start) >> IO_TLB_SHIFT; |
| 594 | phys_addr_t orig_addr = io_tlb_orig_addr[index]; | 600 | phys_addr_t orig_addr = io_tlb_orig_addr[index]; |
| 595 | 601 | ||
| 602 | if (orig_addr == INVALID_PHYS_ADDR) | ||
| 603 | return; | ||
| 596 | orig_addr += (unsigned long)tlb_addr & ((1 << IO_TLB_SHIFT) - 1); | 604 | orig_addr += (unsigned long)tlb_addr & ((1 << IO_TLB_SHIFT) - 1); |
| 597 | 605 | ||
| 598 | switch (target) { | 606 | switch (target) { |
