Commit ed18a462 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Marek Szyprowski
Browse files

iommu/dma: Factor out a iommu_dma_map_swiotlb helper



Split the iommu logic from iommu_dma_map_page into a separate helper.
This not only keeps the code neatly separated, but will also allow for
reuse in another caller.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Tested-by: default avatarJens Axboe <axboe@kernel.dk>
Reviewed-by: default avatarLuis Chamberlain <mcgrof@kernel.org>
Reviewed-by: default avatarLu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: default avatarLeon Romanovsky <leonro@nvidia.com>
Signed-off-by: default avatarMarek Szyprowski <m.szyprowski@samsung.com>
parent 393cf700
Loading
Loading
Loading
Loading
+41 −32
Original line number Diff line number Diff line
@@ -1138,44 +1138,29 @@ void iommu_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
			arch_sync_dma_for_device(sg_phys(sg), sg->length, dir);
}

dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
	      unsigned long offset, size_t size, enum dma_data_direction dir,
	      unsigned long attrs)
static phys_addr_t iommu_dma_map_swiotlb(struct device *dev, phys_addr_t phys,
		size_t size, enum dma_data_direction dir, unsigned long attrs)
{
	phys_addr_t phys = page_to_phys(page) + offset;
	bool coherent = dev_is_dma_coherent(dev);
	int prot = dma_info_to_prot(dir, coherent, attrs);
	struct iommu_domain *domain = iommu_get_dma_domain(dev);
	struct iommu_dma_cookie *cookie = domain->iova_cookie;
	struct iova_domain *iovad = &cookie->iovad;
	dma_addr_t iova, dma_mask = dma_get_mask(dev);
	struct iova_domain *iovad = &domain->iova_cookie->iovad;

	/*
	 * If both the physical buffer start address and size are
	 * page aligned, we don't need to use a bounce page.
	 */
	if (dev_use_swiotlb(dev, size, dir) &&
	    iova_offset(iovad, phys | size)) {
	if (!is_swiotlb_active(dev)) {
		dev_warn_once(dev, "DMA bounce buffers are inactive, unable to map unaligned transaction.\n");
			return DMA_MAPPING_ERROR;
		return (phys_addr_t)DMA_MAPPING_ERROR;
	}

	trace_swiotlb_bounced(dev, phys, size);

		phys = swiotlb_tbl_map_single(dev, phys, size,
					      iova_mask(iovad), dir, attrs);

		if (phys == DMA_MAPPING_ERROR)
			return DMA_MAPPING_ERROR;
	phys = swiotlb_tbl_map_single(dev, phys, size, iova_mask(iovad), dir,
			attrs);

	/*
		 * Untrusted devices should not see padding areas with random
		 * leftover kernel data, so zero the pre- and post-padding.
		 * swiotlb_tbl_map_single() has initialized the bounce buffer
		 * proper to the contents of the original memory buffer.
	 * Untrusted devices should not see padding areas with random leftover
	 * kernel data, so zero the pre- and post-padding.
	 * swiotlb_tbl_map_single() has initialized the bounce buffer proper to
	 * the contents of the original memory buffer.
	 */
		if (dev_is_untrusted(dev)) {
	if (phys != (phys_addr_t)DMA_MAPPING_ERROR && dev_is_untrusted(dev)) {
		size_t start, virt = (size_t)phys_to_virt(phys);

		/* Pre-padding */
@@ -1184,9 +1169,33 @@ dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,

		/* Post-padding */
		start = virt + size;
			memset((void *)start, 0,
			       iova_align(iovad, start) - start);
		memset((void *)start, 0, iova_align(iovad, start) - start);
	}

	return phys;
}

dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
	      unsigned long offset, size_t size, enum dma_data_direction dir,
	      unsigned long attrs)
{
	phys_addr_t phys = page_to_phys(page) + offset;
	bool coherent = dev_is_dma_coherent(dev);
	int prot = dma_info_to_prot(dir, coherent, attrs);
	struct iommu_domain *domain = iommu_get_dma_domain(dev);
	struct iommu_dma_cookie *cookie = domain->iova_cookie;
	struct iova_domain *iovad = &cookie->iovad;
	dma_addr_t iova, dma_mask = dma_get_mask(dev);

	/*
	 * If both the physical buffer start address and size are page aligned,
	 * we don't need to use a bounce page.
	 */
	if (dev_use_swiotlb(dev, size, dir) &&
	    iova_offset(iovad, phys | size)) {
		phys = iommu_dma_map_swiotlb(dev, phys, size, dir, attrs);
		if (phys == (phys_addr_t)DMA_MAPPING_ERROR)
			return DMA_MAPPING_ERROR;
	}

	if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))