summaryrefslogtreecommitdiffstats
path: root/drivers/iommu/iova.c
diff options
context:
space:
mode:
authorJoerg Roedel2017-08-10 14:44:28 +0200
committerJoerg Roedel2017-08-15 18:23:50 +0200
commit42f87e71c3df12d8f29ec1bb7b47772ffaeaf1ee (patch)
treee87f5bea061b489bdc818faf1402f03ce853fec2 /drivers/iommu/iova.c
parentiommu/of: Fix of_iommu_configure() for disabled IOMMUs (diff)
downloadkernel-qcow2-linux-42f87e71c3df12d8f29ec1bb7b47772ffaeaf1ee.tar.gz
kernel-qcow2-linux-42f87e71c3df12d8f29ec1bb7b47772ffaeaf1ee.tar.xz
kernel-qcow2-linux-42f87e71c3df12d8f29ec1bb7b47772ffaeaf1ee.zip
iommu/iova: Add flush-queue data structures
This patch adds the basic data-structures to implement flush-queues in the generic IOVA code. It also adds the initialization and destroy routines for these data structures. The initialization routine is designed so that the use of this feature is optional for the users of IOVA code. Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/iova.c')
-rw-r--r--drivers/iommu/iova.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 246f14c83944..b9f6ce02a1e1 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -50,10 +50,48 @@ init_iova_domain(struct iova_domain *iovad, unsigned long granule,
iovad->granule = granule;
iovad->start_pfn = start_pfn;
iovad->dma_32bit_pfn = pfn_32bit + 1;
+ iovad->flush_cb = NULL;
+ iovad->fq = NULL;
init_iova_rcaches(iovad);
}
EXPORT_SYMBOL_GPL(init_iova_domain);
+static void free_iova_flush_queue(struct iova_domain *iovad)
+{
+ if (!iovad->fq)
+ return;
+
+ free_percpu(iovad->fq);
+
+ iovad->fq = NULL;
+ iovad->flush_cb = NULL;
+ iovad->entry_dtor = NULL;
+}
+
+int init_iova_flush_queue(struct iova_domain *iovad,
+ iova_flush_cb flush_cb, iova_entry_dtor entry_dtor)
+{
+ int cpu;
+
+ iovad->fq = alloc_percpu(struct iova_fq);
+ if (!iovad->fq)
+ return -ENOMEM;
+
+ iovad->flush_cb = flush_cb;
+ iovad->entry_dtor = entry_dtor;
+
+ for_each_possible_cpu(cpu) {
+ struct iova_fq *fq;
+
+ fq = per_cpu_ptr(iovad->fq, cpu);
+ fq->head = 0;
+ fq->tail = 0;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(init_iova_flush_queue);
+
static struct rb_node *
__get_cached_rbnode(struct iova_domain *iovad, unsigned long *limit_pfn)
{
@@ -433,6 +471,7 @@ void put_iova_domain(struct iova_domain *iovad)
struct rb_node *node;
unsigned long flags;
+ free_iova_flush_queue(iovad);
free_iova_rcaches(iovad);
spin_lock_irqsave(&iovad->iova_rbtree_lock, flags);
node = rb_first(&iovad->rbroot);