FROMGIT: 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: Christoph Hellwig <hch@lst.de>
Tested-by: Jens Axboe <axboe@kernel.dk>
Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
(cherry picked from commit ed18a46262be4397cdc24382fb331c68846fef6e
https://git.kernel.org/pub/scm/linux/kernel/git/mszyprowski/linux.git)
Bug: 416098329
[Daniel: Adopted to commit ed5035757c ("BACKPORT: FROMLIST: PCI: Rename
pci_dev->untrusted to pci_dev->requires_dma_protection")]
Signed-off-by: Daniel Mentz <danielmentz@google.com>
Change-Id: I0ece9ce844ebcbab5ee6c6c6b0e99dea6255a77b
This commit is contained in:
committed by
Carlos Llamas
parent
0f2253b2b1
commit
59a15e3bf1
+41
-32
@@ -1171,6 +1171,43 @@ void iommu_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sgl,
|
|||||||
arch_sync_dma_for_device(sg_phys(sg), sg->length, dir);
|
arch_sync_dma_for_device(sg_phys(sg), sg->length, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
struct iommu_domain *domain = iommu_get_dma_domain(dev);
|
||||||
|
struct iova_domain *iovad = &domain->iova_cookie->iovad;
|
||||||
|
|
||||||
|
if (!is_swiotlb_active(dev)) {
|
||||||
|
dev_warn_once(dev, "DMA bounce buffers are inactive, unable to map unaligned transaction.\n");
|
||||||
|
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);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Zero the pre- and post-padding to prevent exposing kernel data to devices
|
||||||
|
* requiring DMA protection.
|
||||||
|
* swiotlb_tbl_map_single() has initialized the bounce buffer proper to
|
||||||
|
* the contents of the original memory buffer.
|
||||||
|
*/
|
||||||
|
if (phys != (phys_addr_t)DMA_MAPPING_ERROR && dev_requires_dma_protection(dev)) {
|
||||||
|
size_t start, virt = (size_t)phys_to_virt(phys);
|
||||||
|
|
||||||
|
/* Pre-padding */
|
||||||
|
start = iova_align_down(iovad, virt);
|
||||||
|
memset((void *)start, 0, virt - start);
|
||||||
|
|
||||||
|
/* Post-padding */
|
||||||
|
start = virt + size;
|
||||||
|
memset((void *)start, 0, iova_align(iovad, start) - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
return phys;
|
||||||
|
}
|
||||||
|
|
||||||
dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
|
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 offset, size_t size, enum dma_data_direction dir,
|
||||||
unsigned long attrs)
|
unsigned long attrs)
|
||||||
@@ -1184,42 +1221,14 @@ dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
|
|||||||
dma_addr_t iova, dma_mask = dma_get_mask(dev);
|
dma_addr_t iova, dma_mask = dma_get_mask(dev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If both the physical buffer start address and size are
|
* If both the physical buffer start address and size are page aligned,
|
||||||
* page aligned, we don't need to use a bounce page.
|
* we don't need to use a bounce page.
|
||||||
*/
|
*/
|
||||||
if (dev_use_swiotlb(dev, size, dir) &&
|
if (dev_use_swiotlb(dev, size, dir) &&
|
||||||
iova_offset(iovad, phys | size)) {
|
iova_offset(iovad, phys | size)) {
|
||||||
if (!is_swiotlb_active(dev)) {
|
phys = iommu_dma_map_swiotlb(dev, phys, size, dir, attrs);
|
||||||
dev_warn_once(dev, "DMA bounce buffers are inactive, unable to map unaligned transaction.\n");
|
if (phys == (phys_addr_t)DMA_MAPPING_ERROR)
|
||||||
return DMA_MAPPING_ERROR;
|
return 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;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Zero the pre- and post-padding to prevent exposing kernel data to devices
|
|
||||||
* requiring DMA protection.
|
|
||||||
* swiotlb_tbl_map_single() has initialized the bounce buffer
|
|
||||||
* proper to the contents of the original memory buffer.
|
|
||||||
*/
|
|
||||||
if (dev_requires_dma_protection(dev)) {
|
|
||||||
size_t start, virt = (size_t)phys_to_virt(phys);
|
|
||||||
|
|
||||||
/* Pre-padding */
|
|
||||||
start = iova_align_down(iovad, virt);
|
|
||||||
memset((void *)start, 0, virt - start);
|
|
||||||
|
|
||||||
/* Post-padding */
|
|
||||||
start = virt + size;
|
|
||||||
memset((void *)start, 0,
|
|
||||||
iova_align(iovad, start) - start);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
|
if (!coherent && !(attrs & DMA_ATTR_SKIP_CPU_SYNC))
|
||||||
|
|||||||
Reference in New Issue
Block a user