diff options
Diffstat (limited to 'drivers/iommu/iommu.c')
-rw-r--r-- | drivers/iommu/iommu.c | 60 |
1 files changed, 60 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); | ||