Messages in this thread Patch in this message | | | From | Filippo Sironi <> | Subject | [PATCH 3/5] iommu/amd: Hold the domain lock when calling __unmap_single | Date | Tue, 10 Sep 2019 19:49:23 +0200 |
| |
__unmap_single makes several calls to __domain_flush_pages, which traverses the device list that is protected by the domain lock. __attach_device and __detach_device).
Also, this is in line with the comment on top of __unmap_single, which says that the domain lock should be held when calling.
Signed-off-by: Filippo Sironi <sironi@amazon.de> --- drivers/iommu/amd_iommu.c | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 8e3664821b3c..d4f25767622e 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -2508,6 +2508,7 @@ static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, { struct protection_domain *domain; struct dma_ops_domain *dma_dom; + unsigned long flags; domain = get_domain(dev); if (IS_ERR(domain)) @@ -2515,7 +2516,9 @@ static void unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, dma_dom = to_dma_ops_domain(domain); + spin_lock_irqsave(&domain->lock, flags); __unmap_single(dma_dom, dma_addr, size, dir); + spin_unlock_irqrestore(&domain->lock, flags); } static int sg_num_pages(struct device *dev, @@ -2645,6 +2648,7 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist, struct dma_ops_domain *dma_dom; unsigned long startaddr; int npages; + unsigned long flags; domain = get_domain(dev); if (IS_ERR(domain)) @@ -2654,7 +2658,9 @@ static void unmap_sg(struct device *dev, struct scatterlist *sglist, dma_dom = to_dma_ops_domain(domain); npages = sg_num_pages(dev, sglist, nelems); + spin_lock_irqsave(&domain->lock, flags); __unmap_single(dma_dom, startaddr, npages << PAGE_SHIFT, dir); + spin_unlock_irqrestore(&domain->lock, flags); } /* @@ -2726,6 +2732,7 @@ static void free_coherent(struct device *dev, size_t size, struct protection_domain *domain; struct dma_ops_domain *dma_dom; struct page *page; + unsigned long flags; page = virt_to_page(virt_addr); size = PAGE_ALIGN(size); @@ -2736,7 +2743,9 @@ static void free_coherent(struct device *dev, size_t size, dma_dom = to_dma_ops_domain(domain); + spin_lock_irqsave(&domain->lock, flags); __unmap_single(dma_dom, dma_addr, size, DMA_BIDIRECTIONAL); + spin_unlock_irqrestore(&domain->lock, flags); free_mem: if (!dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT)) -- 2.7.4
| |