aboutsummaryrefslogtreecommitdiffstats
path: root/lib/swiotlb.c
diff options
context:
space:
mode:
authorIan Campbell <ian.campbell@citrix.com>2008-12-16 15:17:30 -0500
committerIngo Molnar <mingo@elte.hu>2008-12-17 12:58:09 -0500
commite08e1f7adba522378e8d2ae941bf25443866136d (patch)
tree4410e414d856dc03d77a0c654d6b9672f6e69f36 /lib/swiotlb.c
parenta5ddde4a558b3bd1e3dc50e274a0db2ea7a8fd06 (diff)
swiotlb: allow architectures to override phys<->bus<->phys conversions
Impact: generalize phys<->bus<->phys conversions in the swiotlb code Architectures may need to override these conversions. Implement a __weak hook point containing the default implementation. Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'lib/swiotlb.c')
-rw-r--r--lib/swiotlb.c52
1 files changed, 36 insertions, 16 deletions
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 1272b23e4769..3494263cdd9a 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -125,6 +125,26 @@ void * __weak swiotlb_alloc(unsigned order, unsigned long nslabs)
125 return (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN, order); 125 return (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN, order);
126} 126}
127 127
128dma_addr_t __weak swiotlb_phys_to_bus(phys_addr_t paddr)
129{
130 return paddr;
131}
132
133phys_addr_t __weak swiotlb_bus_to_phys(dma_addr_t baddr)
134{
135 return baddr;
136}
137
138static dma_addr_t swiotlb_virt_to_bus(volatile void *address)
139{
140 return swiotlb_phys_to_bus(virt_to_phys(address));
141}
142
143static void *swiotlb_bus_to_virt(dma_addr_t address)
144{
145 return phys_to_virt(swiotlb_bus_to_phys(address));
146}
147
128/* 148/*
129 * Statically reserve bounce buffer space and initialize bounce buffer data 149 * Statically reserve bounce buffer space and initialize bounce buffer data
130 * structures for the software IO TLB used to implement the DMA API. 150 * structures for the software IO TLB used to implement the DMA API.
@@ -168,7 +188,7 @@ swiotlb_init_with_default_size(size_t default_size)
168 panic("Cannot allocate SWIOTLB overflow buffer!\n"); 188 panic("Cannot allocate SWIOTLB overflow buffer!\n");
169 189
170 printk(KERN_INFO "Placing software IO TLB between 0x%lx - 0x%lx\n", 190 printk(KERN_INFO "Placing software IO TLB between 0x%lx - 0x%lx\n",
171 virt_to_bus(io_tlb_start), virt_to_bus(io_tlb_end)); 191 swiotlb_virt_to_bus(io_tlb_start), swiotlb_virt_to_bus(io_tlb_end));
172} 192}
173 193
174void __init 194void __init
@@ -250,7 +270,7 @@ swiotlb_late_init_with_default_size(size_t default_size)
250 270
251 printk(KERN_INFO "Placing %luMB software IO TLB between 0x%lx - " 271 printk(KERN_INFO "Placing %luMB software IO TLB between 0x%lx - "
252 "0x%lx\n", bytes >> 20, 272 "0x%lx\n", bytes >> 20,
253 virt_to_bus(io_tlb_start), virt_to_bus(io_tlb_end)); 273 swiotlb_virt_to_bus(io_tlb_start), swiotlb_virt_to_bus(io_tlb_end));
254 274
255 return 0; 275 return 0;
256 276
@@ -298,7 +318,7 @@ map_single(struct device *hwdev, char *buffer, size_t size, int dir)
298 unsigned long max_slots; 318 unsigned long max_slots;
299 319
300 mask = dma_get_seg_boundary(hwdev); 320 mask = dma_get_seg_boundary(hwdev);
301 start_dma_addr = virt_to_bus(io_tlb_start) & mask; 321 start_dma_addr = swiotlb_virt_to_bus(io_tlb_start) & mask;
302 322
303 offset_slots = ALIGN(start_dma_addr, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT; 323 offset_slots = ALIGN(start_dma_addr, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
304 324
@@ -475,7 +495,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
475 dma_mask = hwdev->coherent_dma_mask; 495 dma_mask = hwdev->coherent_dma_mask;
476 496
477 ret = (void *)__get_free_pages(flags, order); 497 ret = (void *)__get_free_pages(flags, order);
478 if (ret && !is_buffer_dma_capable(dma_mask, virt_to_bus(ret), size)) { 498 if (ret && !is_buffer_dma_capable(dma_mask, swiotlb_virt_to_bus(ret), size)) {
479 /* 499 /*
480 * The allocated memory isn't reachable by the device. 500 * The allocated memory isn't reachable by the device.
481 * Fall back on swiotlb_map_single(). 501 * Fall back on swiotlb_map_single().
@@ -496,7 +516,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
496 } 516 }
497 517
498 memset(ret, 0, size); 518 memset(ret, 0, size);
499 dev_addr = virt_to_bus(ret); 519 dev_addr = swiotlb_virt_to_bus(ret);
500 520
501 /* Confirm address can be DMA'd by device */ 521 /* Confirm address can be DMA'd by device */
502 if (!is_buffer_dma_capable(dma_mask, dev_addr, size)) { 522 if (!is_buffer_dma_capable(dma_mask, dev_addr, size)) {
@@ -556,7 +576,7 @@ dma_addr_t
556swiotlb_map_single_attrs(struct device *hwdev, void *ptr, size_t size, 576swiotlb_map_single_attrs(struct device *hwdev, void *ptr, size_t size,
557 int dir, struct dma_attrs *attrs) 577 int dir, struct dma_attrs *attrs)
558{ 578{
559 dma_addr_t dev_addr = virt_to_bus(ptr); 579 dma_addr_t dev_addr = swiotlb_virt_to_bus(ptr);
560 void *map; 580 void *map;
561 581
562 BUG_ON(dir == DMA_NONE); 582 BUG_ON(dir == DMA_NONE);
@@ -577,7 +597,7 @@ swiotlb_map_single_attrs(struct device *hwdev, void *ptr, size_t size,
577 map = io_tlb_overflow_buffer; 597 map = io_tlb_overflow_buffer;
578 } 598 }
579 599
580 dev_addr = virt_to_bus(map); 600 dev_addr = swiotlb_virt_to_bus(map);
581 601
582 /* 602 /*
583 * Ensure that the address returned is DMA'ble 603 * Ensure that the address returned is DMA'ble
@@ -607,7 +627,7 @@ void
607swiotlb_unmap_single_attrs(struct device *hwdev, dma_addr_t dev_addr, 627swiotlb_unmap_single_attrs(struct device *hwdev, dma_addr_t dev_addr,
608 size_t size, int dir, struct dma_attrs *attrs) 628 size_t size, int dir, struct dma_attrs *attrs)
609{ 629{
610 char *dma_addr = bus_to_virt(dev_addr); 630 char *dma_addr = swiotlb_bus_to_virt(dev_addr);
611 631
612 BUG_ON(dir == DMA_NONE); 632 BUG_ON(dir == DMA_NONE);
613 if (is_swiotlb_buffer(dma_addr)) 633 if (is_swiotlb_buffer(dma_addr))
@@ -637,7 +657,7 @@ static void
637swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr, 657swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
638 size_t size, int dir, int target) 658 size_t size, int dir, int target)
639{ 659{
640 char *dma_addr = bus_to_virt(dev_addr); 660 char *dma_addr = swiotlb_bus_to_virt(dev_addr);
641 661
642 BUG_ON(dir == DMA_NONE); 662 BUG_ON(dir == DMA_NONE);
643 if (is_swiotlb_buffer(dma_addr)) 663 if (is_swiotlb_buffer(dma_addr))
@@ -668,7 +688,7 @@ swiotlb_sync_single_range(struct device *hwdev, dma_addr_t dev_addr,
668 unsigned long offset, size_t size, 688 unsigned long offset, size_t size,
669 int dir, int target) 689 int dir, int target)
670{ 690{
671 char *dma_addr = bus_to_virt(dev_addr) + offset; 691 char *dma_addr = swiotlb_bus_to_virt(dev_addr) + offset;
672 692
673 BUG_ON(dir == DMA_NONE); 693 BUG_ON(dir == DMA_NONE);
674 if (is_swiotlb_buffer(dma_addr)) 694 if (is_swiotlb_buffer(dma_addr))
@@ -724,7 +744,7 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
724 744
725 for_each_sg(sgl, sg, nelems, i) { 745 for_each_sg(sgl, sg, nelems, i) {
726 addr = SG_ENT_VIRT_ADDRESS(sg); 746 addr = SG_ENT_VIRT_ADDRESS(sg);
727 dev_addr = virt_to_bus(addr); 747 dev_addr = swiotlb_virt_to_bus(addr);
728 if (swiotlb_force || 748 if (swiotlb_force ||
729 address_needs_mapping(hwdev, dev_addr, sg->length)) { 749 address_needs_mapping(hwdev, dev_addr, sg->length)) {
730 void *map = map_single(hwdev, addr, sg->length, dir); 750 void *map = map_single(hwdev, addr, sg->length, dir);
@@ -737,7 +757,7 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
737 sgl[0].dma_length = 0; 757 sgl[0].dma_length = 0;
738 return 0; 758 return 0;
739 } 759 }
740 sg->dma_address = virt_to_bus(map); 760 sg->dma_address = swiotlb_virt_to_bus(map);
741 } else 761 } else
742 sg->dma_address = dev_addr; 762 sg->dma_address = dev_addr;
743 sg->dma_length = sg->length; 763 sg->dma_length = sg->length;
@@ -768,7 +788,7 @@ swiotlb_unmap_sg_attrs(struct device *hwdev, struct scatterlist *sgl,
768 788
769 for_each_sg(sgl, sg, nelems, i) { 789 for_each_sg(sgl, sg, nelems, i) {
770 if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) 790 if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
771 unmap_single(hwdev, bus_to_virt(sg->dma_address), 791 unmap_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
772 sg->dma_length, dir); 792 sg->dma_length, dir);
773 else if (dir == DMA_FROM_DEVICE) 793 else if (dir == DMA_FROM_DEVICE)
774 dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length); 794 dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
@@ -801,7 +821,7 @@ swiotlb_sync_sg(struct device *hwdev, struct scatterlist *sgl,
801 821
802 for_each_sg(sgl, sg, nelems, i) { 822 for_each_sg(sgl, sg, nelems, i) {
803 if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg)) 823 if (sg->dma_address != SG_ENT_PHYS_ADDRESS(sg))
804 sync_single(hwdev, bus_to_virt(sg->dma_address), 824 sync_single(hwdev, swiotlb_bus_to_virt(sg->dma_address),
805 sg->dma_length, dir, target); 825 sg->dma_length, dir, target);
806 else if (dir == DMA_FROM_DEVICE) 826 else if (dir == DMA_FROM_DEVICE)
807 dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length); 827 dma_mark_clean(SG_ENT_VIRT_ADDRESS(sg), sg->dma_length);
@@ -825,7 +845,7 @@ swiotlb_sync_sg_for_device(struct device *hwdev, struct scatterlist *sg,
825int 845int
826swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr) 846swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr)
827{ 847{
828 return (dma_addr == virt_to_bus(io_tlb_overflow_buffer)); 848 return (dma_addr == swiotlb_virt_to_bus(io_tlb_overflow_buffer));
829} 849}
830 850
831/* 851/*
@@ -837,7 +857,7 @@ swiotlb_dma_mapping_error(struct device *hwdev, dma_addr_t dma_addr)
837int 857int
838swiotlb_dma_supported(struct device *hwdev, u64 mask) 858swiotlb_dma_supported(struct device *hwdev, u64 mask)
839{ 859{
840 return virt_to_bus(io_tlb_end - 1) <= mask; 860 return swiotlb_virt_to_bus(io_tlb_end - 1) <= mask;
841} 861}
842 862
843EXPORT_SYMBOL(swiotlb_map_single); 863EXPORT_SYMBOL(swiotlb_map_single);