aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu/iommu.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/iommu/iommu.c')
-rw-r--r--drivers/iommu/iommu.c60
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
28static 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}
38static DEVICE_ATTR(iommu_group, S_IRUGO, show_iommu_group, NULL);
39
40static 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
50static 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
60static 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
73static struct notifier_block iommu_device_nb = {
74 .notifier_call = iommu_device_notifier,
75};
76
28static void iommu_bus_init(struct bus_type *bus, struct iommu_ops *ops) 77static 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}
188EXPORT_SYMBOL_GPL(iommu_unmap); 239EXPORT_SYMBOL_GPL(iommu_unmap);
240
241int 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}
248EXPORT_SYMBOL_GPL(iommu_device_group);