aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2018-01-09 16:15:30 -0500
committerChristoph Hellwig <hch@lst.de>2018-01-15 03:35:49 -0500
commit0176adb004065d6815a8e67946752df4cd947c5b (patch)
treee2e9a646e644709c854f4f9fdd3c1827bb796931
parenta25381aa3ae60a2e028c95f1318649b13cbbce30 (diff)
swiotlb: refactor coherent buffer allocation
Factor out a new swiotlb_alloc_buffer helper that allocates DMA coherent memory from the swiotlb bounce buffer. This allows to simplify the swiotlb_alloc implemenation that uses dma_direct_alloc to try to allocate a reachable buffer first. Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: Christian König <christian.koenig@amd.com>
-rw-r--r--lib/swiotlb.c122
1 files changed, 65 insertions, 57 deletions
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index 1a147f1354a1..0039b7c5e690 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -709,75 +709,79 @@ void swiotlb_tbl_sync_single(struct device *hwdev, phys_addr_t tlb_addr,
709} 709}
710EXPORT_SYMBOL_GPL(swiotlb_tbl_sync_single); 710EXPORT_SYMBOL_GPL(swiotlb_tbl_sync_single);
711 711
712void * 712static inline bool dma_coherent_ok(struct device *dev, dma_addr_t addr,
713swiotlb_alloc_coherent(struct device *hwdev, size_t size, 713 size_t size)
714 dma_addr_t *dma_handle, gfp_t flags)
715{ 714{
716 bool warn = !(flags & __GFP_NOWARN); 715 u64 mask = DMA_BIT_MASK(32);
717 dma_addr_t dev_addr;
718 void *ret;
719 int order = get_order(size);
720 u64 dma_mask = DMA_BIT_MASK(32);
721 716
722 if (hwdev && hwdev->coherent_dma_mask) 717 if (dev && dev->coherent_dma_mask)
723 dma_mask = hwdev->coherent_dma_mask; 718 mask = dev->coherent_dma_mask;
719 return addr + size - 1 <= mask;
720}
724 721
725 ret = (void *)__get_free_pages(flags, order); 722static void *
726 if (ret) { 723swiotlb_alloc_buffer(struct device *dev, size_t size, dma_addr_t *dma_handle,
727 dev_addr = swiotlb_virt_to_bus(hwdev, ret); 724 unsigned long attrs)
728 if (dev_addr + size - 1 > dma_mask) { 725{
729 /* 726 phys_addr_t phys_addr;
730 * The allocated memory isn't reachable by the device.
731 */
732 free_pages((unsigned long) ret, order);
733 ret = NULL;
734 }
735 }
736 if (!ret) {
737 /*
738 * We are either out of memory or the device can't DMA to
739 * GFP_DMA memory; fall back on map_single(), which
740 * will grab memory from the lowest available address range.
741 */
742 phys_addr_t paddr = map_single(hwdev, 0, size, DMA_FROM_DEVICE,
743 warn ? 0 : DMA_ATTR_NO_WARN);
744 if (paddr == SWIOTLB_MAP_ERROR)
745 goto err_warn;
746 727
747 ret = phys_to_virt(paddr); 728 if (swiotlb_force == SWIOTLB_NO_FORCE)
748 dev_addr = swiotlb_phys_to_dma(hwdev, paddr); 729 goto out_warn;
749 730
750 /* Confirm address can be DMA'd by device */ 731 phys_addr = swiotlb_tbl_map_single(dev,
751 if (dev_addr + size - 1 > dma_mask) { 732 swiotlb_phys_to_dma(dev, io_tlb_start),
752 printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n", 733 0, size, DMA_FROM_DEVICE, 0);
753 (unsigned long long)dma_mask, 734 if (phys_addr == SWIOTLB_MAP_ERROR)
754 (unsigned long long)dev_addr); 735 goto out_warn;
755 736
756 /* 737 *dma_handle = swiotlb_phys_to_dma(dev, phys_addr);
757 * DMA_TO_DEVICE to avoid memcpy in unmap_single. 738 if (dma_coherent_ok(dev, *dma_handle, size))
758 * The DMA_ATTR_SKIP_CPU_SYNC is optional. 739 goto out_unmap;
759 */
760 swiotlb_tbl_unmap_single(hwdev, paddr,
761 size, DMA_TO_DEVICE,
762 DMA_ATTR_SKIP_CPU_SYNC);
763 goto err_warn;
764 }
765 }
766 740
767 *dma_handle = dev_addr; 741 memset(phys_to_virt(phys_addr), 0, size);
768 memset(ret, 0, size); 742 return phys_to_virt(phys_addr);
769 743
770 return ret; 744out_unmap:
745 dev_warn(dev, "hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n",
746 (unsigned long long)(dev ? dev->coherent_dma_mask : 0),
747 (unsigned long long)*dma_handle);
771 748
772err_warn: 749 /*
773 if (warn && printk_ratelimit()) { 750 * DMA_TO_DEVICE to avoid memcpy in unmap_single.
774 pr_warn("swiotlb: coherent allocation failed for device %s size=%zu\n", 751 * DMA_ATTR_SKIP_CPU_SYNC is optional.
775 dev_name(hwdev), size); 752 */
753 swiotlb_tbl_unmap_single(dev, phys_addr, size, DMA_TO_DEVICE,
754 DMA_ATTR_SKIP_CPU_SYNC);
755out_warn:
756 if ((attrs & DMA_ATTR_NO_WARN) && printk_ratelimit()) {
757 dev_warn(dev,
758 "swiotlb: coherent allocation failed, size=%zu\n",
759 size);
776 dump_stack(); 760 dump_stack();
777 } 761 }
778
779 return NULL; 762 return NULL;
780} 763}
764
765void *
766swiotlb_alloc_coherent(struct device *hwdev, size_t size,
767 dma_addr_t *dma_handle, gfp_t flags)
768{
769 int order = get_order(size);
770 unsigned long attrs = (flags & __GFP_NOWARN) ? DMA_ATTR_NO_WARN : 0;
771 void *ret;
772
773 ret = (void *)__get_free_pages(flags, order);
774 if (ret) {
775 *dma_handle = swiotlb_virt_to_bus(hwdev, ret);
776 if (dma_coherent_ok(hwdev, *dma_handle, size)) {
777 memset(ret, 0, size);
778 return ret;
779 }
780 free_pages((unsigned long)ret, order);
781 }
782
783 return swiotlb_alloc_buffer(hwdev, size, dma_handle, attrs);
784}
781EXPORT_SYMBOL(swiotlb_alloc_coherent); 785EXPORT_SYMBOL(swiotlb_alloc_coherent);
782 786
783static bool swiotlb_free_buffer(struct device *dev, size_t size, 787static bool swiotlb_free_buffer(struct device *dev, size_t size,
@@ -1103,6 +1107,10 @@ void *swiotlb_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
1103{ 1107{
1104 void *vaddr; 1108 void *vaddr;
1105 1109
1110 /* temporary workaround: */
1111 if (gfp & __GFP_NOWARN)
1112 attrs |= DMA_ATTR_NO_WARN;
1113
1106 /* 1114 /*
1107 * Don't print a warning when the first allocation attempt fails. 1115 * Don't print a warning when the first allocation attempt fails.
1108 * swiotlb_alloc_coherent() will print a warning when the DMA memory 1116 * swiotlb_alloc_coherent() will print a warning when the DMA memory
@@ -1112,7 +1120,7 @@ void *swiotlb_alloc(struct device *dev, size_t size, dma_addr_t *dma_handle,
1112 1120
1113 vaddr = dma_direct_alloc(dev, size, dma_handle, gfp, attrs); 1121 vaddr = dma_direct_alloc(dev, size, dma_handle, gfp, attrs);
1114 if (!vaddr) 1122 if (!vaddr)
1115 vaddr = swiotlb_alloc_coherent(dev, size, dma_handle, gfp); 1123 vaddr = swiotlb_alloc_buffer(dev, size, dma_handle, attrs);
1116 return vaddr; 1124 return vaddr;
1117} 1125}
1118 1126