summaryrefslogtreecommitdiff
path: root/include/linux/iommu-common.h
diff options
context:
space:
mode:
authorSowmini Varadhan <sowmini.varadhan@oracle.com>2015-03-12 20:02:35 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-16 12:44:55 -0700
commit10b88a4b17d31a7409494b179dcb76e7ab2fcaea (patch)
tree1322d01102b150a8c04d2815fee1935efc951b76 /include/linux/iommu-common.h
parent497a5df7bf6ffd136ae21c49d1a01292930d7ca2 (diff)
sparc: Break up monolithic iommu table/lock into finer graularity pools and lock
Investigation of multithreaded iperf experiments on an ethernet interface show the iommu->lock as the hottest lock identified by lockstat, with something of the order of 21M contentions out of 27M acquisitions, and an average wait time of 26 us for the lock. This is not efficient. A more scalable design is to follow the ppc model, where the iommu_table has multiple pools, each stretching over a segment of the map, and with a separate lock for each pool. This model allows for better parallelization of the iommu map search. This patch adds the iommu range alloc/free function infrastructure. Signed-off-by: Sowmini Varadhan <sowmini.varadhan@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/linux/iommu-common.h')
-rw-r--r--include/linux/iommu-common.h55
1 files changed, 55 insertions, 0 deletions
diff --git a/include/linux/iommu-common.h b/include/linux/iommu-common.h
new file mode 100644
index 000000000000..6be5c863f329
--- /dev/null
+++ b/include/linux/iommu-common.h
@@ -0,0 +1,55 @@
+#ifndef _LINUX_IOMMU_COMMON_H
+#define _LINUX_IOMMU_COMMON_H
+
+#include <linux/spinlock_types.h>
+#include <linux/device.h>
+#include <asm/page.h>
+
+#define IOMMU_POOL_HASHBITS 4
+#define IOMMU_NR_POOLS (1 << IOMMU_POOL_HASHBITS)
+
+struct iommu_pool {
+ unsigned long start;
+ unsigned long end;
+ unsigned long hint;
+ spinlock_t lock;
+};
+
+struct iommu_table;
+
+struct iommu_tbl_ops {
+ unsigned long (*cookie_to_index)(u64, void *);
+ void (*demap)(void *, unsigned long, unsigned long);
+ void (*reset)(struct iommu_table *);
+};
+
+struct iommu_table {
+ unsigned long page_table_map_base;
+ unsigned long page_table_shift;
+ unsigned long nr_pools;
+ const struct iommu_tbl_ops *iommu_tbl_ops;
+ unsigned long poolsize;
+ struct iommu_pool arena_pool[IOMMU_NR_POOLS];
+ u32 flags;
+#define IOMMU_HAS_LARGE_POOL 0x00000001
+ struct iommu_pool large_pool;
+ unsigned long *map;
+};
+
+extern void iommu_tbl_pool_init(struct iommu_table *iommu,
+ unsigned long num_entries,
+ u32 page_table_shift,
+ const struct iommu_tbl_ops *iommu_tbl_ops,
+ bool large_pool, u32 npools);
+
+extern unsigned long iommu_tbl_range_alloc(struct device *dev,
+ struct iommu_table *iommu,
+ unsigned long npages,
+ unsigned long *handle,
+ unsigned int pool_hash);
+
+extern void iommu_tbl_range_free(struct iommu_table *iommu,
+ u64 dma_addr, unsigned long npages,
+ bool do_demap, void *demap_arg);
+
+#endif