From 281e8ccbff172899a60579773e72ad63d58b3770 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 7 Jul 2016 16:12:02 +0200 Subject: 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 --- drivers/iommu/amd_iommu.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'drivers/iommu/amd_iommu.c') diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 5c72d124403c..d13a18633dce 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; -- cgit v1.2.3