aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2007-02-05 21:53:04 -0500
committerTony Luck <tony.luck@intel.com>2007-02-05 21:53:04 -0500
commit51099005ab8e09d68a13fea8d55bc739c1040ca6 (patch)
tree865519c98fada85e5ae2ba4f617dea27e63aee56
parent563aaf064f3776623ff5e7aef511ac2eb7e5f0bb (diff)
[IA64] swiotlb abstraction (e.g. for Xen)
Add abstraction so that the file can be used by environments other than IA64 and EM64T, namely for Xen. Signed-off-by: Jan Beulich <jbeulich@novell.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Tony Luck <tony.luck@intel.com>
-rw-r--r--include/asm-ia64/swiotlb.h9
-rw-r--r--include/asm-x86_64/swiotlb.h1
-rw-r--r--lib/swiotlb.c184
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);
44extern int swiotlb_force; 44extern int swiotlb_force;
45 45
46#ifdef CONFIG_SWIOTLB 46#ifdef CONFIG_SWIOTLB
47#define SWIOTLB_ARCH_NEED_ALLOC
47extern int swiotlb; 48extern 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 */
104static unsigned char **io_tlb_orig_addr; 107#ifndef SWIOTLB_ARCH_HAS_IO_TLB_ADDR_T
108typedef 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
114static 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 */
109static DEFINE_SPINLOCK(io_tlb_lock); 119static DEFINE_SPINLOCK(io_tlb_lock);
110 120
121#ifdef SWIOTLB_EXTRA_VARIABLES
122SWIOTLB_EXTRA_VARIABLES;
123#endif
124
125#ifndef SWIOTLB_ARCH_HAS_SETUP_IO_TLB_NPAGES
111static int __init 126static int __init
112setup_io_tlb_npages(char *str) 127setup_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
174void __init 214void __init
175swiotlb_init(void) 215swiotlb_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
258cleanup4: 297cleanup4:
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;
262cleanup3: 301cleanup3:
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;
266cleanup2: 305cleanup2:
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
275static inline int 316static inline int
276address_needs_mapping(struct device *hwdev, dma_addr_t addr) 317address_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
326static inline int range_needs_mapping(const void *ptr, size_t size)
327{
328 return swiotlb_force;
329}
330
331static inline int order_needs_mapping(unsigned int order)
332{
333 return 0;
334}
335#endif
336
337static 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 */
288static void * 353static void *
289map_single(struct device *hwdev, char *buffer, size_t size, int dir) 354map_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
439void * 507void *
440swiotlb_alloc_coherent(struct device *hwdev, size_t size, 508swiotlb_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}
563EXPORT_SYMBOL(swiotlb_alloc_coherent);
492 564
493void 565void
494swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr, 566swiotlb_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}
576EXPORT_SYMBOL(swiotlb_free_coherent);
577
578#endif
504 579
505static void 580static void
506swiotlb_full(struct device *dev, size_t size, int dir, int do_panic) 581swiotlb_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
676swiotlb_map_sg(struct device *hwdev, struct scatterlist *sg, int nelems, 752swiotlb_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
840dma_addr_t
841swiotlb_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
861void
862swiotlb_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
763int 876int
764swiotlb_dma_mapping_error(dma_addr_t dma_addr) 877swiotlb_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
775int 891int
776swiotlb_dma_supported(struct device *hwdev, u64 mask) 892swiotlb_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
781EXPORT_SYMBOL(swiotlb_init); 897EXPORT_SYMBOL(swiotlb_init);
@@ -790,6 +906,4 @@ EXPORT_SYMBOL_GPL(swiotlb_sync_single_range_for_device);
790EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu); 906EXPORT_SYMBOL(swiotlb_sync_sg_for_cpu);
791EXPORT_SYMBOL(swiotlb_sync_sg_for_device); 907EXPORT_SYMBOL(swiotlb_sync_sg_for_device);
792EXPORT_SYMBOL(swiotlb_dma_mapping_error); 908EXPORT_SYMBOL(swiotlb_dma_mapping_error);
793EXPORT_SYMBOL(swiotlb_alloc_coherent);
794EXPORT_SYMBOL(swiotlb_free_coherent);
795EXPORT_SYMBOL(swiotlb_dma_supported); 909EXPORT_SYMBOL(swiotlb_dma_supported);