diff options
author | Joerg Roedel <jroedel@suse.de> | 2016-07-07 16:12:02 +0200 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2016-07-14 10:21:16 +0200 |
commit | 281e8ccbff172899a60579773e72ad63d58b3770 (patch) | |
tree | b0a03aa4ffe518a51d273bd76700288169d0d99c /drivers | |
parent | cda7005ba2cbd0744fea343dd5b2aa637eba5b9e (diff) |
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 <jroedel@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/iommu/amd_iommu.c | 17 |
1 files changed, 14 insertions, 3 deletions
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; |