diff options
author | Christoph Hellwig <hch@lst.de> | 2018-01-09 16:15:30 -0500 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2018-01-15 03:35:49 -0500 |
commit | 0176adb004065d6815a8e67946752df4cd947c5b (patch) | |
tree | e2e9a646e644709c854f4f9fdd3c1827bb796931 | |
parent | a25381aa3ae60a2e028c95f1318649b13cbbce30 (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.c | 122 |
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 | } |
710 | EXPORT_SYMBOL_GPL(swiotlb_tbl_sync_single); | 710 | EXPORT_SYMBOL_GPL(swiotlb_tbl_sync_single); |
711 | 711 | ||
712 | void * | 712 | static inline bool dma_coherent_ok(struct device *dev, dma_addr_t addr, |
713 | swiotlb_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); | 722 | static void * |
726 | if (ret) { | 723 | swiotlb_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; | 744 | out_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 | ||
772 | err_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); | ||
755 | out_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 | |||
765 | void * | ||
766 | swiotlb_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 | } | ||
781 | EXPORT_SYMBOL(swiotlb_alloc_coherent); | 785 | EXPORT_SYMBOL(swiotlb_alloc_coherent); |
782 | 786 | ||
783 | static bool swiotlb_free_buffer(struct device *dev, size_t size, | 787 | static 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 | ||