aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/dmar.h
diff options
context:
space:
mode:
authorJiang Liu <jiang.liu@linux.intel.com>2014-02-19 01:07:34 -0500
committerJoerg Roedel <joro@8bytes.org>2014-03-04 11:51:05 -0500
commit0e242612d9cdb46e878ed1f126c78fe68492af00 (patch)
treeab7c73c8ebb07c94ac42d93de529f9905569ab09 /include/linux/dmar.h
parent3a5670e8ac932c10a3e50d9dc0ab1da4cc3041d7 (diff)
iommu/vt-d: Use RCU to protect global resources in interrupt context
Global DMA and interrupt remapping resources may be accessed in interrupt context, so use RCU instead of rwsem to protect them in such cases. Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com> Signed-off-by: Joerg Roedel <joro@8bytes.org>
Diffstat (limited to 'include/linux/dmar.h')
-rw-r--r--include/linux/dmar.h23
1 files changed, 17 insertions, 6 deletions
diff --git a/include/linux/dmar.h b/include/linux/dmar.h
index 8f06a0135a84..bedebab934b4 100644
--- a/include/linux/dmar.h
+++ b/include/linux/dmar.h
@@ -26,6 +26,7 @@
26#include <linux/msi.h> 26#include <linux/msi.h>
27#include <linux/irqreturn.h> 27#include <linux/irqreturn.h>
28#include <linux/rwsem.h> 28#include <linux/rwsem.h>
29#include <linux/rcupdate.h>
29 30
30struct acpi_dmar_header; 31struct acpi_dmar_header;
31 32
@@ -41,7 +42,7 @@ struct dmar_drhd_unit {
41 struct list_head list; /* list of drhd units */ 42 struct list_head list; /* list of drhd units */
42 struct acpi_dmar_header *hdr; /* ACPI header */ 43 struct acpi_dmar_header *hdr; /* ACPI header */
43 u64 reg_base_addr; /* register base address*/ 44 u64 reg_base_addr; /* register base address*/
44 struct pci_dev **devices; /* target device array */ 45 struct pci_dev __rcu **devices;/* target device array */
45 int devices_cnt; /* target device count */ 46 int devices_cnt; /* target device count */
46 u16 segment; /* PCI domain */ 47 u16 segment; /* PCI domain */
47 u8 ignored:1; /* ignore drhd */ 48 u8 ignored:1; /* ignore drhd */
@@ -53,22 +54,31 @@ extern struct rw_semaphore dmar_global_lock;
53extern struct list_head dmar_drhd_units; 54extern struct list_head dmar_drhd_units;
54 55
55#define for_each_drhd_unit(drhd) \ 56#define for_each_drhd_unit(drhd) \
56 list_for_each_entry(drhd, &dmar_drhd_units, list) 57 list_for_each_entry_rcu(drhd, &dmar_drhd_units, list)
57 58
58#define for_each_active_drhd_unit(drhd) \ 59#define for_each_active_drhd_unit(drhd) \
59 list_for_each_entry(drhd, &dmar_drhd_units, list) \ 60 list_for_each_entry_rcu(drhd, &dmar_drhd_units, list) \
60 if (drhd->ignored) {} else 61 if (drhd->ignored) {} else
61 62
62#define for_each_active_iommu(i, drhd) \ 63#define for_each_active_iommu(i, drhd) \
63 list_for_each_entry(drhd, &dmar_drhd_units, list) \ 64 list_for_each_entry_rcu(drhd, &dmar_drhd_units, list) \
64 if (i=drhd->iommu, drhd->ignored) {} else 65 if (i=drhd->iommu, drhd->ignored) {} else
65 66
66#define for_each_iommu(i, drhd) \ 67#define for_each_iommu(i, drhd) \
67 list_for_each_entry(drhd, &dmar_drhd_units, list) \ 68 list_for_each_entry_rcu(drhd, &dmar_drhd_units, list) \
68 if (i=drhd->iommu, 0) {} else 69 if (i=drhd->iommu, 0) {} else
69 70
71static inline bool dmar_rcu_check(void)
72{
73 return rwsem_is_locked(&dmar_global_lock) ||
74 system_state == SYSTEM_BOOTING;
75}
76
77#define dmar_rcu_dereference(p) rcu_dereference_check((p), dmar_rcu_check())
78
70#define for_each_dev_scope(a, c, p, d) \ 79#define for_each_dev_scope(a, c, p, d) \
71 for ((p) = 0; ((d) = (p) < (c) ? (a)[(p)] : NULL, (p) < (c)); (p)++) 80 for ((p) = 0; ((d) = (p) < (c) ? dmar_rcu_dereference((a)[(p)]) : \
81 NULL, (p) < (c)); (p)++)
72 82
73#define for_each_active_dev_scope(a, c, p, d) \ 83#define for_each_active_dev_scope(a, c, p, d) \
74 for_each_dev_scope((a), (c), (p), (d)) if (!(d)) { continue; } else 84 for_each_dev_scope((a), (c), (p), (d)) if (!(d)) { continue; } else
@@ -78,6 +88,7 @@ extern int dmar_dev_scope_init(void);
78extern int dmar_parse_dev_scope(void *start, void *end, int *cnt, 88extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,
79 struct pci_dev ***devices, u16 segment); 89 struct pci_dev ***devices, u16 segment);
80extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt); 90extern void *dmar_alloc_dev_scope(void *start, void *end, int *cnt);
91extern void dmar_free_dev_scope(struct pci_dev __rcu ***devices, int *cnt);
81extern void dmar_free_dev_scope(struct pci_dev ***devices, int *cnt); 92extern void dmar_free_dev_scope(struct pci_dev ***devices, int *cnt);
82 93
83/* Intel IOMMU detection */ 94/* Intel IOMMU detection */