diff options
| -rw-r--r-- | include/asm-ia64/swiotlb.h | 9 | ||||
| -rw-r--r-- | include/asm-x86_64/swiotlb.h | 1 | ||||
| -rw-r--r-- | lib/swiotlb.c | 184 |
3 files changed, 159 insertions, 35 deletions
diff --git a/include/asm-ia64/swiotlb.h b/include/asm-ia64/swiotlb.h new file mode 100644 index 000000000000..452c162dee4e --- /dev/null +++ b/include/asm-ia64/swiotlb.h | |||
| @@ -0,0 +1,9 @@ | |||
| 1 | #ifndef _ASM_SWIOTLB_H | ||
| 2 | #define _ASM_SWIOTLB_H 1 | ||
| 3 | |||
| 4 | #include <asm/machvec.h> | ||
| 5 | |||
| 6 | #define SWIOTLB_ARCH_NEED_LATE_INIT | ||
| 7 | #define SWIOTLB_ARCH_NEED_ALLOC | ||
| 8 | |||
| 9 | #endif /* _ASM_SWIOTLB_H */ | ||
diff --git a/include/asm-x86_64/swiotlb.h b/include/asm-x86_64/swiotlb.h index f9c589539a82..ab913ffcad56 100644 --- a/include/asm-x86_64/swiotlb.h +++ b/include/asm-x86_64/swiotlb.h | |||
| @@ -44,6 +44,7 @@ extern void swiotlb_init(void); | |||
| 44 | extern int swiotlb_force; | 44 | extern int swiotlb_force; |
| 45 | 45 | ||
| 46 | #ifdef CONFIG_SWIOTLB | 46 | #ifdef CONFIG_SWIOTLB |
| 47 | #define SWIOTLB_ARCH_NEED_ALLOC | ||
| 47 | extern int swiotlb; | 48 | extern int swiotlb; |
| 48 | #else | 49 | #else |
| 49 | #define swiotlb 0 | 50 | #define swiotlb 0 |
diff --git a/lib/swiotlb.c b/lib/swiotlb.c index 067eed5b2758..50a438010182 100644 --- a/lib/swiotlb.c +++ b/lib/swiotlb.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <asm/io.h> | 28 | #include <asm/io.h> |
| 29 | #include <asm/dma.h> | 29 | #include <asm/dma.h> |
| 30 | #include <asm/scatterlist.h> | 30 | #include <asm/scatterlist.h> |
| 31 | #include <asm/swiotlb.h> | ||
| 31 | 32 | ||
| 32 | #include <linux/init.h> | 33 | #include <linux/init.h> |
| 33 | #include <linux/bootmem.h> | 34 | #include <linux/bootmem.h> |
| @@ -35,8 +36,10 @@ | |||
| 35 | #define OFFSET(val,align) ((unsigned long) \ | 36 | #define OFFSET(val,align) ((unsigned long) \ |
| 36 | ( (val) & ( (align) - 1))) | 37 | ( (val) & ( (align) - 1))) |
| 37 | 38 | ||
| 39 | #ifndef SG_ENT_VIRT_ADDRESS | ||
| 38 | #define SG_ENT_VIRT_ADDRESS(sg) (page_address((sg)->page) + (sg)->offset) | 40 | #define SG_ENT_VIRT_ADDRESS(sg) (page_address((sg)->page) + (sg)->offset) |
| 39 | #define SG_ENT_PHYS_ADDRESS(sg) virt_to_bus(SG_ENT_VIRT_ADDRESS(sg)) | 41 | #define SG_ENT_PHYS_ADDRESS(sg) virt_to_bus(SG_ENT_VIRT_ADDRESS(sg)) |
| 42 | #endif | ||
| 40 | 43 | ||
| 41 | /* | 44 | /* |
| 42 | * Maximum allowable number of contiguous slabs to map, | 45 | * Maximum allowable number of contiguous slabs to map, |
| @@ -101,13 +104,25 @@ static unsigned int io_tlb_index; | |||
| 101 | * We need to save away the original address corresponding to a mapped entry | 104 | * We need to save away the original address corresponding to a mapped entry |
| 102 | * for the sync operations. | 105 | * for the sync operations. |
| 103 | */ | 106 | */ |
| 104 | static unsigned char **io_tlb_orig_addr; | 107 | #ifndef SWIOTLB_ARCH_HAS_IO_TLB_ADDR_T |
| 108 | typedef char *io_tlb_addr_t; | ||
| 109 | #define swiotlb_orig_addr_null(buffer) (!(buffer)) | ||
| 110 | #define ptr_to_io_tlb_addr(ptr) (ptr) | ||
| 111 | #define page_to_io_tlb_addr(pg, off) (page_address(pg) + (off)) | ||
| 112 | #define sg_to_io_tlb_addr(sg) SG_ENT_VIRT_ADDRESS(sg) | ||
| 113 | #endif | ||
| 114 | static io_tlb_addr_t *io_tlb_orig_addr; | ||
| 105 | 115 | ||
| 106 | /* | 116 | /* |
| 107 | * Protect the above data structures in the map and unmap calls | 117 | * Protect the above data structures in the map and unmap calls |
| 108 | */ | 118 | */ |
| 109 | static DEFINE_SPINLOCK(io_tlb_lock); | 119 | static DEFINE_SPINLOCK(io_tlb_lock); |
| 110 | 120 | ||
| 121 | #ifdef SWIOTLB_EXTRA_VARIABLES | ||
| 122 | SWIOTLB_EXTRA_VARIABLES; | ||
| 123 | #endif | ||
| 124 | |||
| 125 | #ifndef SWIOTLB_ARCH_HAS_SETUP_IO_TLB_NPAGES | ||
| 111 | static int __init | 126 | static int __init |
| 112 | setup_io_tlb_npages(char *str) | 127 | setup_io_tlb_npages(char *str) |
| 113 | { | 128 | { |
| @@ -122,9 +137,25 @@ setup_io_tlb_npages(char *str) | |||
| 122 | swiotlb_force = 1; | 137 | swiotlb_force = 1; |
| 123 | return 1; | 138 | return 1; |
| 124 | } | 139 | } |
| 140 | #endif | ||
| 125 | __setup("swiotlb=", setup_io_tlb_npages); | 141 | __setup("swiotlb=", setup_io_tlb_npages); |
| 126 | /* make io_tlb_overflow tunable too? */ | 142 | /* make io_tlb_overflow tunable too? */ |
| 127 | 143 | ||
| 144 | #ifndef swiotlb_adjust_size | ||
| 145 | #define swiotlb_adjust_size(size) ((void)0) | ||
| 146 | #endif | ||
| 147 | |||
| 148 | #ifndef swiotlb_adjust_seg | ||
| 149 | #define swiotlb_adjust_seg(start, size) ((void)0) | ||
| 150 | #endif | ||
| 151 | |||
| 152 | #ifndef swiotlb_print_info | ||
| 153 | #define swiotlb_print_info(bytes) \ | ||
| 154 | printk(KERN_INFO "Placing %luMB software IO TLB between 0x%lx - " \ | ||
| 155 | "0x%lx\n", bytes >> 20, \ | ||
| 156 | virt_to_bus(io_tlb_start), virt_to_bus(io_tlb_end)) | ||
| 157 | #endif | ||
| 158 | |||
| 128 | /* | 159 | /* |
| 129 | * Statically reserve bounce buffer space and initialize bounce buffer data | 160 | * Statically reserve bounce buffer space and initialize bounce buffer data |
| 130 | * structures for the software IO TLB used to implement the DMA API. | 161 | * structures for the software IO TLB used to implement the DMA API. |
| @@ -138,6 +169,8 @@ swiotlb_init_with_default_size(size_t default_size) | |||
| 138 | io_tlb_nslabs = (default_size >> IO_TLB_SHIFT); | 169 | io_tlb_nslabs = (default_size >> IO_TLB_SHIFT); |
| 139 | io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE); | 170 | io_tlb_nslabs = ALIGN(io_tlb_nslabs, IO_TLB_SEGSIZE); |
| 140 | } | 171 | } |
| 172 | swiotlb_adjust_size(io_tlb_nslabs); | ||
| 173 | swiotlb_adjust_size(io_tlb_overflow); | ||
| 141 | 174 | ||
| 142 | bytes = io_tlb_nslabs << IO_TLB_SHIFT; | 175 | bytes = io_tlb_nslabs << IO_TLB_SHIFT; |
| 143 | 176 | ||
| @@ -155,10 +188,14 @@ swiotlb_init_with_default_size(size_t default_size) | |||
| 155 | * between io_tlb_start and io_tlb_end. | 188 | * between io_tlb_start and io_tlb_end. |
| 156 | */ | 189 | */ |
| 157 | io_tlb_list = alloc_bootmem(io_tlb_nslabs * sizeof(int)); | 190 | io_tlb_list = alloc_bootmem(io_tlb_nslabs * sizeof(int)); |
| 158 | for (i = 0; i < io_tlb_nslabs; i++) | 191 | for (i = 0; i < io_tlb_nslabs; i++) { |
| 192 | if ( !(i % IO_TLB_SEGSIZE) ) | ||
| 193 | swiotlb_adjust_seg(io_tlb_start + (i << IO_TLB_SHIFT), | ||
| 194 | IO_TLB_SEGSIZE << IO_TLB_SHIFT); | ||
| 159 | io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); | 195 | io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE); |
| 196 | } | ||
| 160 | io_tlb_index = 0; | 197 | io_tlb_index = 0; |
| 161 | io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(char *)); | 198 | io_tlb_orig_addr = alloc_bootmem(io_tlb_nslabs * sizeof(io_tlb_addr_t)); |
| 162 | 199 | ||
| 163 | /* | 200 | /* |
| 164 | * Get the overflow emergency buffer | 201 | * Get the overflow emergency buffer |
| @@ -166,17 +203,21 @@ swiotlb_init_with_default_size(size_t default_size) | |||
| 166 | io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow); | 203 | io_tlb_overflow_buffer = alloc_bootmem_low(io_tlb_overflow); |
| 167 | if (!io_tlb_overflow_buffer) | 204 | if (!io_tlb_overflow_buffer) |
| 168 | panic("Cannot allocate SWIOTLB overflow buffer!\n"); | 205 | panic("Cannot allocate SWIOTLB overflow buffer!\n"); |
| 206 | swiotlb_adjust_seg(io_tlb_overflow_buffer, io_tlb_overflow); | ||
| 169 | 207 | ||
| 170 | printk(KERN_INFO "Placing software IO TLB between 0x%lx - 0x%lx\n", | 208 | swiotlb_print_info(bytes); |
| 171 | virt_to_bus(io_tlb_start), virt_to_bus(io_tlb_end)); | ||
| 172 | } | 209 | } |
| 210 | #ifndef __swiotlb_init_with_default_size | ||
| 211 | #define __swiotlb_init_with_default_size swiotlb_init_with_default_size | ||
| 212 | #endif | ||
| 173 | 213 | ||
| 174 | void __init | 214 | void __init |
| 175 | swiotlb_init(void) | 215 | swiotlb_init(void) |
| 176 | { | 216 | { |
| 177 | swiotlb_init_with_default_size(64 * (1<<20)); /* default to 64MB */ | 217 | __swiotlb_init_with_default_size(64 * (1<<20)); /* default to 64MB */ |
| 178 | } | 218 | } |
| 179 | 219 | ||
| 220 | #ifdef SWIOTLB_ARCH_NEED_LATE_INIT | ||
| 180 | /* | 221 | /* |
| 181 | * Systems with larger DMA zones (those that don't support ISA) can | 222 | * Systems with larger DMA zones (those that don't support ISA) can |
| 182 | * initialize the swiotlb later using the slab allocator if needed. | 223 | * initialize the swiotlb later using the slab allocator if needed. |
| @@ -234,12 +275,12 @@ swiotlb_late_init_with_default_size(size_t default_size) | |||
| 234 | 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); |
| 235 | io_tlb_index = 0; | 276 | io_tlb_index = 0; |
| 236 | 277 | ||
| 237 | io_tlb_orig_addr = (unsigned char **)__get_free_pages(GFP_KERNEL, | 278 | io_tlb_orig_addr = (io_tlb_addr_t *)__get_free_pages(GFP_KERNEL, |
| 238 | get_order(io_tlb_nslabs * sizeof(char *))); | 279 | get_order(io_tlb_nslabs * sizeof(io_tlb_addr_t))); |
| 239 | if (!io_tlb_orig_addr) | 280 | if (!io_tlb_orig_addr) |
| 240 | goto cleanup3; | 281 | goto cleanup3; |
| 241 | 282 | ||
| 242 | memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(char *)); | 283 | memset(io_tlb_orig_addr, 0, io_tlb_nslabs * sizeof(io_tlb_addr_t)); |
| 243 | 284 | ||
| 244 | /* | 285 | /* |
| 245 | * Get the overflow emergency buffer | 286 | * Get the overflow emergency buffer |
| @@ -249,19 +290,17 @@ swiotlb_late_init_with_default_size(size_t default_size) | |||
| 249 | if (!io_tlb_overflow_buffer) | 290 | if (!io_tlb_overflow_buffer) |
| 250 | goto cleanup4; | 291 | goto cleanup4; |
| 251 | 292 | ||
| 252 | printk(KERN_INFO "Placing %luMB software IO TLB between 0x%lx - " | 293 | swiotlb_print_info(bytes); |
| 253 | "0x%lx\n", bytes >> 20, | ||
| 254 | virt_to_bus(io_tlb_start), virt_to_bus(io_tlb_end)); | ||
| 255 | 294 | ||
| 256 | return 0; | 295 | return 0; |
| 257 | 296 | ||
| 258 | cleanup4: | 297 | cleanup4: |
| 259 | free_pages((unsigned long)io_tlb_orig_addr, get_order(io_tlb_nslabs * | 298 | free_pages((unsigned long)io_tlb_orig_addr, |
| 260 | sizeof(char *))); | 299 | get_order(io_tlb_nslabs * sizeof(io_tlb_addr_t))); |
| 261 | io_tlb_orig_addr = NULL; | 300 | io_tlb_orig_addr = NULL; |
| 262 | cleanup3: | 301 | cleanup3: |
| 263 | free_pages((unsigned long)io_tlb_list, get_order(io_tlb_nslabs * | 302 | free_pages((unsigned long)io_tlb_list, |
| 264 | sizeof(int))); | 303 | get_order(io_tlb_nslabs * sizeof(int))); |
| 265 | io_tlb_list = NULL; | 304 | io_tlb_list = NULL; |
| 266 | cleanup2: | 305 | cleanup2: |
| 267 | io_tlb_end = NULL; | 306 | io_tlb_end = NULL; |
| @@ -271,7 +310,9 @@ cleanup1: | |||
| 271 | io_tlb_nslabs = req_nslabs; | 310 | io_tlb_nslabs = req_nslabs; |
| 272 | return -ENOMEM; | 311 | return -ENOMEM; |
| 273 | } | 312 | } |
| 313 | #endif | ||
| 274 | 314 | ||
| 315 | #ifndef SWIOTLB_ARCH_HAS_NEEDS_MAPPING | ||
| 275 | static inline int | 316 | static inline int |
| 276 | address_needs_mapping(struct device *hwdev, dma_addr_t addr) | 317 | address_needs_mapping(struct device *hwdev, dma_addr_t addr) |
| 277 | { | 318 | { |
| @@ -282,11 +323,35 @@ address_needs_mapping(struct device *hwdev, dma_addr_t addr) | |||
| 282 | return (addr & ~mask) != 0; | 323 | return (addr & ~mask) != 0; |
| 283 | } | 324 | } |
| 284 | 325 | ||
| 326 | static inline int range_needs_mapping(const void *ptr, size_t size) | ||
| 327 | { | ||
| 328 | return swiotlb_force; | ||
| 329 | } | ||
| 330 | |||
| 331 | static inline int order_needs_mapping(unsigned int order) | ||
| 332 | { | ||
| 333 | return 0; | ||
| 334 | } | ||
| 335 | #endif | ||
| 336 | |||
| 337 | static void | ||
| 338 | __sync_single(io_tlb_addr_t buffer, char *dma_addr, size_t size, int dir) | ||
| 339 | { | ||
| 340 | #ifndef SWIOTLB_ARCH_HAS_SYNC_SINGLE | ||
| 341 | if (dir == DMA_TO_DEVICE) | ||
| 342 | memcpy(dma_addr, buffer, size); | ||
| 343 | else | ||
| 344 | memcpy(buffer, dma_addr, size); | ||
| 345 | #else | ||
| 346 | __swiotlb_arch_sync_single(buffer, dma_addr, size, dir); | ||
| 347 | #endif | ||
| 348 | } | ||
| 349 | |||
| 285 | /* | 350 | /* |
| 286 | * Allocates bounce buffer and returns its kernel virtual address. | 351 | * Allocates bounce buffer and returns its kernel virtual address. |
| 287 | */ | 352 | */ |
| 288 | static void * | 353 | static void * |
| 289 | map_single(struct device *hwdev, char *buffer, size_t size, int dir) | 354 | map_single(struct device *hwdev, io_tlb_addr_t buffer, size_t size, int dir) |
| 290 | { | 355 | { |
| 291 | unsigned long flags; | 356 | unsigned long flags; |
| 292 | char *dma_addr; | 357 | char *dma_addr; |
| @@ -359,7 +424,7 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir) | |||
| 359 | */ | 424 | */ |
| 360 | io_tlb_orig_addr[index] = buffer; | 425 | io_tlb_orig_addr[index] = buffer; |
| 361 | if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) | 426 | if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL) |
| 362 | memcpy(dma_addr, buffer, size); | 427 | __sync_single(buffer, dma_addr, size, DMA_TO_DEVICE); |
| 363 | 428 | ||
| 364 | return dma_addr; | 429 | return dma_addr; |
| 365 | } | 430 | } |
| @@ -373,17 +438,18 @@ unmap_single(struct device *hwdev, char *dma_addr, size_t size, int dir) | |||
| 373 | unsigned long flags; | 438 | unsigned long flags; |
| 374 | int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT; | 439 | int i, count, nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT; |
| 375 | int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; | 440 | int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; |
| 376 | char *buffer = io_tlb_orig_addr[index]; | 441 | io_tlb_addr_t buffer = io_tlb_orig_addr[index]; |
| 377 | 442 | ||
| 378 | /* | 443 | /* |
| 379 | * First, sync the memory before unmapping the entry | 444 | * First, sync the memory before unmapping the entry |
| 380 | */ | 445 | */ |
| 381 | if (buffer && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL))) | 446 | if (!swiotlb_orig_addr_null(buffer) |
| 447 | && ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL))) | ||
| 382 | /* | 448 | /* |
| 383 | * bounce... copy the data back into the original buffer * and | 449 | * bounce... copy the data back into the original buffer * and |
| 384 | * delete the bounce buffer. | 450 | * delete the bounce buffer. |
| 385 | */ | 451 | */ |
| 386 | memcpy(buffer, dma_addr, size); | 452 | __sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE); |
| 387 | 453 | ||
| 388 | /* | 454 | /* |
| 389 | * Return the buffer to the free list by setting the corresponding | 455 | * Return the buffer to the free list by setting the corresponding |
| @@ -416,18 +482,18 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size, | |||
| 416 | int dir, int target) | 482 | int dir, int target) |
| 417 | { | 483 | { |
| 418 | int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; | 484 | int index = (dma_addr - io_tlb_start) >> IO_TLB_SHIFT; |
| 419 | char *buffer = io_tlb_orig_addr[index]; | 485 | io_tlb_addr_t buffer = io_tlb_orig_addr[index]; |
| 420 | 486 | ||
| 421 | switch (target) { | 487 | switch (target) { |
| 422 | case SYNC_FOR_CPU: | 488 | case SYNC_FOR_CPU: |
| 423 | if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)) | 489 | if (likely(dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)) |
| 424 | memcpy(buffer, dma_addr, size); | 490 | __sync_single(buffer, dma_addr, size, DMA_FROM_DEVICE); |
| 425 | else | 491 | else |
| 426 | BUG_ON(dir != DMA_TO_DEVICE); | 492 | BUG_ON(dir != DMA_TO_DEVICE); |
| 427 | break; | 493 | break; |
| 428 | case SYNC_FOR_DEVICE: | 494 | case SYNC_FOR_DEVICE: |
| 429 | if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)) | 495 | if (likely(dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)) |
| 430 | memcpy(dma_addr, buffer, size); | 496 | __sync_single(buffer, dma_addr, size, DMA_TO_DEVICE); |
| 431 | else | 497 | else |
| 432 | BUG_ON(dir != DMA_FROM_DEVICE); | 498 | BUG_ON(dir != DMA_FROM_DEVICE); |
| 433 | break; | 499 | break; |
| @@ -436,6 +502,8 @@ sync_single(struct device *hwdev, char *dma_addr, size_t size, | |||
| 436 | } | 502 | } |
| 437 | } | 503 | } |
| 438 | 504 | ||
| 505 | #ifdef SWIOTLB_ARCH_NEED_ALLOC | ||
| 506 | |||
| 439 | void * | 507 | void * |
| 440 | swiotlb_alloc_coherent(struct device *hwdev, size_t size, | 508 | swiotlb_alloc_coherent(struct device *hwdev, size_t size, |
| 441 | dma_addr_t *dma_handle, gfp_t flags) | 509 | dma_addr_t *dma_handle, gfp_t flags) |
| @@ -451,7 +519,10 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size, | |||
| 451 | */ | 519 | */ |
| 452 | flags |= GFP_DMA; | 520 | flags |= GFP_DMA; |
| 453 | 521 | ||
| 454 | ret = (void *)__get_free_pages(flags, order); | 522 | if (!order_needs_mapping(order)) |
| 523 | ret = (void *)__get_free_pages(flags, order); | ||
| 524 | else | ||
| 525 | ret = NULL; | ||
| 455 | if (ret && address_needs_mapping(hwdev, virt_to_bus(ret))) { | 526 | if (ret && address_needs_mapping(hwdev, virt_to_bus(ret))) { |
| 456 | /* | 527 | /* |
| 457 | * The allocated memory isn't reachable by the device. | 528 | * The allocated memory isn't reachable by the device. |
| @@ -489,6 +560,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size, | |||
| 489 | *dma_handle = dev_addr; | 560 | *dma_handle = dev_addr; |
| 490 | return ret; | 561 | return ret; |
| 491 | } | 562 | } |
| 563 | EXPORT_SYMBOL(swiotlb_alloc_coherent); | ||
| 492 | 564 | ||
| 493 | void | 565 | void |
| 494 | swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr, | 566 | swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr, |
| @@ -501,6 +573,9 @@ swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr, | |||
| 501 | /* DMA_TO_DEVICE to avoid memcpy in unmap_single */ | 573 | /* DMA_TO_DEVICE to avoid memcpy in unmap_single */ |
| 502 | swiotlb_unmap_single (hwdev, dma_handle, size, DMA_TO_DEVICE); | 574 | swiotlb_unmap_single (hwdev, dma_handle, size, DMA_TO_DEVICE); |
| 503 | } | 575 | } |
| 576 | EXPORT_SYMBOL(swiotlb_free_coherent); | ||
| 577 | |||
| 578 | #endif | ||
| 504 | 579 | ||
| 505 | static void | 580 | static void |
| 506 | swiotlb_full(struct device *dev, size_t size, int dir, int do_panic) | 581 | swiotlb_full(struct device *dev, size_t size, int dir, int do_panic) |
| @@ -542,13 +617,14 @@ swiotlb_map_single(struct device *hwdev, void *ptr, size_t size, int dir) | |||
| 542 | * we can safely return the device addr and not worry about bounce | 617 | * we can safely return the device addr and not worry about bounce |
| 543 | * buffering it. | 618 | * buffering it. |
| 544 | */ | 619 | */ |
| 545 | if (!address_needs_mapping(hwdev, dev_addr) && !swiotlb_force) | 620 | if (!range_needs_mapping(ptr, size) |
| 621 | && !address_needs_mapping(hwdev, dev_addr)) | ||
| 546 | return dev_addr; | 622 | return dev_addr; |
| 547 | 623 | ||
| 548 | /* | 624 | /* |
| 549 | * Oh well, have to allocate and map a bounce buffer. | 625 | * Oh well, have to allocate and map a bounce buffer. |
| 550 | */ | 626 | */ |
| 551 | map = map_single(hwdev, ptr, size, dir); | 627 | map = map_single(hwdev, ptr_to_io_tlb_addr(ptr), size, dir); |
| 552 | if (!map) { | 628 | if (!map) { |
| 553 | swiotlb_full(hwdev, size, dir, 1); | 629 | swiotlb_full(hwdev, size, dir, 1); |
| 554 | map = io_tlb_overflow_buffer; | 630 | map = io_tlb_overflow_buffer; |
| @@ -676,17 +752,16 @@ int | |||
| 676 | swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems, | 752 | swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems, |
| 677 | int dir) | 753 | int dir) |
| 678 | { | 754 | { |
| 679 | void *addr; | ||
| 680 | dma_addr_t dev_addr; | 755 | dma_addr_t dev_addr; |
| 681 | int i; | 756 | int i; |
| 682 | 757 | ||
| 683 | BUG_ON(dir == DMA_NONE); | 758 | BUG_ON(dir == DMA_NONE); |
| 684 | 759 | ||
| 685 | for (i = 0; i < nelems; i++, sg++) { | 760 | for (i = 0; i < nelems; i++, sg++) { |
| 686 | addr = SG_ENT_VIRT_ADDRESS(sg); | 761 | dev_addr = SG_ENT_PHYS_ADDRESS(sg); |
| 687 | dev_addr = virt_to_bus(addr); | 762 | if (range_needs_mapping(SG_ENT_VIRT_ADDRESS(sg), sg->length) |
| 688 | if (swiotlb_force || address_needs_mapping(hwdev, dev_addr)) { | 763 | || address_needs_mapping(hwdev, dev_addr)) { |
| 689 | void *map = map_single(hwdev, addr, sg->length, dir); | 764 | void *map = map_single(hwdev, sg_to_io_tlb_addr(sg), sg->length, dir); |
| 690 | if (!map) { | 765 | if (!map) { |
| 691 | /* Don't panic here, we expect map_sg users | 766 | /* Don't panic here, we expect map_sg users |
| 692 | to do proper error handling. */ | 767 | to do proper error handling. */ |
| @@ -760,6 +835,44 @@ swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg, | |||
| 760 | swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_DEVICE); | 835 | swiotlb_sync_sg(hwdev, sg, nelems, dir, SYNC_FOR_DEVICE); |
| 761 | } | 836 | } |
| 762 | 837 | ||
| 838 | #ifdef SWIOTLB_ARCH_NEED_MAP_PAGE | ||
| 839 | |||
| 840 | dma_addr_t | ||
| 841 | swiotlb_map_page(struct device *hwdev, struct page *page, | ||
| 842 | unsigned long offset, size_t size, | ||
| 843 | enum dma_data_direction direction) | ||
| 844 | { | ||
| 845 | dma_addr_t dev_addr; | ||
| 846 | char *map; | ||
| 847 | |||
| 848 | dev_addr = page_to_bus(page) + offset; | ||
| 849 | if (address_needs_mapping(hwdev, dev_addr)) { | ||
| 850 | map = map_single(hwdev, page_to_io_tlb_addr(page, offset), size, direction); | ||
| 851 | if (!map) { | ||
| 852 | swiotlb_full(hwdev, size, direction, 1); | ||
| 853 | map = io_tlb_overflow_buffer; | ||
| 854 | } | ||
| 855 | dev_addr = virt_to_bus(map); | ||
| 856 | } | ||
| 857 | |||
| 858 | return dev_addr; | ||
| 859 | } | ||
| 860 | |||
| 861 | void | ||
| 862 | swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr, | ||
| 863 | size_t size, enum dma_data_direction direction) | ||
| 864 | { | ||
| 865 | char *dma_addr = bus_to_virt(dev_addr); | ||
| 866 | |||
| 867 | BUG_ON(direction == DMA_NONE); | ||
| 868 | if (dma_addr >= io_tlb_start && dma_addr < io_tlb_end) | ||
| 869 | unmap_single(hwdev, dma_addr, size, direction); | ||
| 870 | else if (direction == DMA_FROM_DEVICE) | ||
| 871 | dma_mark_clean(dma_addr, size); | ||
| 872 | } | ||
| 873 | |||
| 874 | #endif | ||
| 875 | |||
| 763 | int | 876 | int |
| 764 | swiotlb_dma_mapping_error(dma_addr_t dma_addr) | 877 | swiotlb_dma_mapping_error(dma_addr_t dma_addr) |
| 765 | { | 878 | { |
| @@ -772,10 +885,13 @@ swiotlb_dma_mapping_error(dma_addr_t dma_addr) | |||
| 772 | * during bus mastering, then you would pass 0x00ffffff as the mask to | 885 | * during bus mastering, then you would pass 0x00ffffff as the mask to |
| 773 | * this function. | 886 | * this function. |
| 774 | */ | 887 | */ |
| 888 | #ifndef __swiotlb_dma_supported | ||
| 889 | #define __swiotlb_dma_supported(hwdev, mask) (virt_to_bus(io_tlb_end - 1) <= (mask)) | ||
| 890 | #endif | ||
| 775 | int | 891 | int |
| 776 | swiotlb_dma_supported(struct device *hwdev, u64 mask) | 892 | swiotlb_dma_supported(struct device *hwdev, u64 mask) |
| 777 | { | 893 | { |
| 778 | return virt_to_bus(io_tlb_end - 1) <= mask; | 894 | return __swiotlb_dma_supported(hwdev, mask); |
| 779 | } | 895 | } |
| 780 | 896 | ||
| 781 | EXPORT_SYMBOL(swiotlb_init); | 897 | EXPORT_SYMBOL(swiotlb_init); |
| @@ -790,6 +906,4 @@ EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_device); | |||
| 790 | EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu); | 906 | EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu); |
| 791 | EXPORT_SYMBOL(swiotlb_sync_sg_for_device); | 907 | EXPORT_SYMBOL(swiotlb_sync_sg_for_device); |
| 792 | EXPORT_SYMBOL(swiotlb_dma_mapping_error); | 908 | EXPORT_SYMBOL(swiotlb_dma_mapping_error); |
| 793 | EXPORT_SYMBOL(swiotlb_alloc_coherent); | ||
| 794 | EXPORT_SYMBOL(swiotlb_free_coherent); | ||
| 795 | EXPORT_SYMBOL(swiotlb_dma_supported); | 909 | EXPORT_SYMBOL(swiotlb_dma_supported); |
