diff options
-rw-r--r-- | drivers/iommu/iommu.c | 60 | ||||
-rw-r--r-- | include/linux/iommu.h | 7 |
2 files changed, 67 insertions, 0 deletions
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 2fb2963df553..9c35be4b333f 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c | |||
@@ -25,8 +25,59 @@ | |||
25 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
26 | #include <linux/iommu.h> | 26 | #include <linux/iommu.h> |
27 | 27 | ||
28 | static ssize_t show_iommu_group(struct device *dev, | ||
29 | struct device_attribute *attr, char *buf) | ||
30 | { | ||
31 | unsigned int groupid; | ||
32 | |||
33 | if (iommu_device_group(dev, &groupid)) | ||
34 | return 0; | ||
35 | |||
36 | return sprintf(buf, "%u", groupid); | ||
37 | } | ||
38 | static DEVICE_ATTR(iommu_group, S_IRUGO, show_iommu_group, NULL); | ||
39 | |||
40 | static int add_iommu_group(struct device *dev, void *data) | ||
41 | { | ||
42 | unsigned int groupid; | ||
43 | |||
44 | if (iommu_device_group(dev, &groupid) == 0) | ||
45 | return device_create_file(dev, &dev_attr_iommu_group); | ||
46 | |||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | static int remove_iommu_group(struct device *dev) | ||
51 | { | ||
52 | unsigned int groupid; | ||
53 | |||
54 | if (iommu_device_group(dev, &groupid) == 0) | ||
55 | device_remove_file(dev, &dev_attr_iommu_group); | ||
56 | |||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static int iommu_device_notifier(struct notifier_block *nb, | ||
61 | unsigned long action, void *data) | ||
62 | { | ||
63 | struct device *dev = data; | ||
64 | |||
65 | if (action == BUS_NOTIFY_ADD_DEVICE) | ||
66 | return add_iommu_group(dev, NULL); | ||
67 | else if (action == BUS_NOTIFY_DEL_DEVICE) | ||
68 | return remove_iommu_group(dev); | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static struct notifier_block iommu_device_nb = { | ||
74 | .notifier_call = iommu_device_notifier, | ||
75 | }; | ||
76 | |||
28 | static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops) | 77 | static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops) |
29 | { | 78 | { |
79 | bus_register_notifier(bus, &iommu_device_nb); | ||
80 | bus_for_each_dev(bus, NULL, NULL, add_iommu_group); | ||
30 | } | 81 | } |
31 | 82 | ||
32 | /** | 83 | /** |
@@ -186,3 +237,12 @@ int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order) | |||
186 | return domain->ops->unmap(domain, iova, gfp_order); | 237 | return domain->ops->unmap(domain, iova, gfp_order); |
187 | } | 238 | } |
188 | EXPORT_SYMBOL_GPL(iommu_unmap); | 239 | EXPORT_SYMBOL_GPL(iommu_unmap); |
240 | |||
241 | int iommu_device_group(struct device *dev, unsigned int *groupid) | ||
242 | { | ||
243 | if (iommu_present(dev->bus) && dev->bus->iommu_ops->device_group) | ||
244 | return dev->bus->iommu_ops->device_group(dev, groupid); | ||
245 | |||
246 | return -ENODEV; | ||
247 | } | ||
248 | EXPORT_SYMBOL_GPL(iommu_device_group); | ||
diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 432acc4c054d..93617e7779a1 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h | |||
@@ -61,6 +61,7 @@ struct iommu_ops { | |||
61 | unsigned long iova); | 61 | unsigned long iova); |
62 | int (*domain_has_cap)(struct iommu_domain *domain, | 62 | int (*domain_has_cap)(struct iommu_domain *domain, |
63 | unsigned long cap); | 63 | unsigned long cap); |
64 | int (*device_group)(struct device *dev, unsigned int *groupid); | ||
64 | }; | 65 | }; |
65 | 66 | ||
66 | extern int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops); | 67 | extern int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops); |
@@ -81,6 +82,7 @@ extern int iommu_domain_has_cap(struct iommu_domain *domain, | |||
81 | unsigned long cap); | 82 | unsigned long cap); |
82 | extern void iommu_set_fault_handler(struct iommu_domain *domain, | 83 | extern void iommu_set_fault_handler(struct iommu_domain *domain, |
83 | iommu_fault_handler_t handler); | 84 | iommu_fault_handler_t handler); |
85 | extern int iommu_device_group(struct device *dev, unsigned int *groupid); | ||
84 | 86 | ||
85 | /** | 87 | /** |
86 | * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework | 88 | * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework |
@@ -179,6 +181,11 @@ static inline void iommu_set_fault_handler(struct iommu_domain *domain, | |||
179 | { | 181 | { |
180 | } | 182 | } |
181 | 183 | ||
184 | static inline int iommu_device_group(struct device *dev, unsigned int *groupid); | ||
185 | { | ||
186 | return -ENODEV; | ||
187 | } | ||
188 | |||
182 | #endif /* CONFIG_IOMMU_API */ | 189 | #endif /* CONFIG_IOMMU_API */ |
183 | 190 | ||
184 | #endif /* __LINUX_IOMMU_H */ | 191 | #endif /* __LINUX_IOMMU_H */ |