From: Joerg Roedel Date: Thu, 7 Jul 2016 14:12:02 +0000 (+0200) Subject: iommu/amd: Flush iova queue before releasing dma_ops_domain X-Git-Tag: v5.15~13141^2^2~3 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=281e8ccbff172899a60579773e72ad63d58b3770;p=platform%2Fkernel%2Flinux-starfive.git iommu/amd: Flush iova queue before releasing dma_ops_domain Before a dma_ops_domain can be freed, we need to make sure it is not longer referenced by the flush queue. So empty the queue before a dma_ops_domain can be freed. Signed-off-by: Joerg Roedel --- diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 5c72d12..d13a186 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -2154,12 +2154,10 @@ static void __queue_flush(struct flush_queue *queue) queue->next = 0; } -void queue_flush_timeout(unsigned long unsused) +static void queue_flush_all(void) { int cpu; - atomic_set(&queue_timer_on, 0); - for_each_possible_cpu(cpu) { struct flush_queue *queue; unsigned long flags; @@ -2172,6 +2170,12 @@ void queue_flush_timeout(unsigned long unsused) } } +static void queue_flush_timeout(unsigned long unsused) +{ + atomic_set(&queue_timer_on, 0); + queue_flush_all(); +} + static void queue_add(struct dma_ops_domain *dma_dom, unsigned long address, unsigned long pages) { @@ -2877,6 +2881,13 @@ static void amd_iommu_domain_free(struct iommu_domain *dom) switch (dom->type) { case IOMMU_DOMAIN_DMA: + /* + * First make sure the domain is no longer referenced from the + * flush queue + */ + queue_flush_all(); + + /* Now release the domain */ dma_dom = domain->priv; dma_ops_domain_free(dma_dom); break;