aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Williamson <alex.williamson@redhat.com>2014-06-12 18:12:24 -0400
committerJoerg Roedel <jroedel@suse.de>2014-07-04 06:35:59 -0400
commitc61959ecbbc6bf9034e65c8e8ef03fa9d1066f05 (patch)
tree8c5b068f79d1a873d55d6f00e1888f559e6d1ea4
parentfd2852d5da67ca890b10468e33c68544e8da1ece (diff)
iommu: Add sysfs support for IOMMUs
IOMMUs currently have no common representation to userspace, most seem to have no representation at all aside from a few printks on bootup. There are however features of IOMMUs that are useful to know about. For instance the IOMMU might support superpages, making use of processor large/huge pages more important in a device assignment scenario. It's also useful to create cross links between devices and IOMMU hardware units, so that users might be able to load balance their devices to avoid thrashing a single hardware unit. This patch adds a device create and destroy interface as well as device linking, making it very lightweight for an IOMMU driver to add basic support. IOMMU drivers can provide additional attributes automatically by using an attribute_group. The attributes exposed are expected to be relatively device specific, the means to retrieve them certainly are, so there are currently no common attributes for the new class created here. Signed-off-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--Documentation/ABI/testing/sysfs-class-iommu17
-rw-r--r--drivers/iommu/Makefile1
-rw-r--r--drivers/iommu/iommu-sysfs.c133
-rw-r--r--include/linux/iommu.h26
4 files changed, 177 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-iommu b/Documentation/ABI/testing/sysfs-class-iommu
new file mode 100644
index 000000000000..6d0a1b4be82d
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-class-iommu
@@ -0,0 +1,17 @@
1What: /sys/class/iommu/<iommu>/devices/
2Date: June 2014
3KernelVersion: 3.17
4Contact: Alex Williamson <alex.williamson@redhat.com>
5Description:
6 IOMMU drivers are able to link devices managed by a
7 given IOMMU here to allow association of IOMMU to
8 device.
9
10What: /sys/devices/.../iommu
11Date: June 2014
12KernelVersion: 3.17
13Contact: Alex Williamson <alex.williamson@redhat.com>
14Description:
15 IOMMU drivers are able to link the IOMMU for a
16 given device here to allow association of device to
17 IOMMU.
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 8893bad048e0..7788ebd1f6e2 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -1,5 +1,6 @@
1obj-$(CONFIG_IOMMU_API) += iommu.o 1obj-$(CONFIG_IOMMU_API) += iommu.o
2obj-$(CONFIG_IOMMU_API) += iommu-traces.o 2obj-$(CONFIG_IOMMU_API) += iommu-traces.o
3obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o
3obj-$(CONFIG_OF_IOMMU) += of_iommu.o 4obj-$(CONFIG_OF_IOMMU) += of_iommu.o
4obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o 5obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o msm_iommu_dev.o
5obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o 6obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
diff --git a/drivers/iommu/iommu-sysfs.c b/drivers/iommu/iommu-sysfs.c
new file mode 100644
index 000000000000..d6939234a009
--- /dev/null
+++ b/drivers/iommu/iommu-sysfs.c
@@ -0,0 +1,133 @@
1/*
2 * IOMMU sysfs class support
3 *
4 * Copyright (C) 2014 Red Hat, Inc. All rights reserved.
5 * Author: Alex Williamson <alex.williamson@redhat.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/device.h>
13#include <linux/iommu.h>
14#include <linux/module.h>
15
16/*
17 * We provide a common class "devices" group which initially has no attributes.
18 * As devices are added to the IOMMU, we'll add links to the group.
19 */
20static struct attribute *devices_attr[] = {
21 NULL,
22};
23
24static const struct attribute_group iommu_devices_attr_group = {
25 .name = "devices",
26 .attrs = devices_attr,
27};
28
29static const struct attribute_group *iommu_dev_groups[] = {
30 &iommu_devices_attr_group,
31 NULL,
32};
33
34static void iommu_release_device(struct device *dev)
35{
36 kfree(dev);
37}
38
39static struct class iommu_class = {
40 .name = "iommu",
41 .dev_release = iommu_release_device,
42 .dev_groups = iommu_dev_groups,
43};
44
45static int __init iommu_dev_init(void)
46{
47 return class_register(&iommu_class);
48}
49postcore_initcall(iommu_dev_init);
50
51/*
52 * Create an IOMMU device and return a pointer to it. IOMMU specific
53 * attributes can be provided as an attribute group, allowing a unique
54 * namespace per IOMMU type.
55 */
56struct device *iommu_device_create(struct device *parent, void *drvdata,
57 const struct attribute_group **groups,
58 const char *fmt, ...)
59{
60 struct device *dev;
61 va_list vargs;
62 int ret;
63
64 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
65 if (!dev)
66 return ERR_PTR(-ENOMEM);
67
68 device_initialize(dev);
69
70 dev->class = &iommu_class;
71 dev->parent = parent;
72 dev->groups = groups;
73 dev_set_drvdata(dev, drvdata);
74
75 va_start(vargs, fmt);
76 ret = kobject_set_name_vargs(&dev->kobj, fmt, vargs);
77 va_end(vargs);
78 if (ret)
79 goto error;
80
81 ret = device_add(dev);
82 if (ret)
83 goto error;
84
85 return dev;
86
87error:
88 put_device(dev);
89 return ERR_PTR(ret);
90}
91
92void iommu_device_destroy(struct device *dev)
93{
94 if (!dev || IS_ERR(dev))
95 return;
96
97 device_unregister(dev);
98}
99
100/*
101 * IOMMU drivers can indicate a device is managed by a given IOMMU using
102 * this interface. A link to the device will be created in the "devices"
103 * directory of the IOMMU device in sysfs and an "iommu" link will be
104 * created under the linked device, pointing back at the IOMMU device.
105 */
106int iommu_device_link(struct device *dev, struct device *link)
107{
108 int ret;
109
110 if (!dev || IS_ERR(dev))
111 return -ENODEV;
112
113 ret = sysfs_add_link_to_group(&dev->kobj, "devices",
114 &link->kobj, dev_name(link));
115 if (ret)
116 return ret;
117
118 ret = sysfs_create_link_nowarn(&link->kobj, &dev->kobj, "iommu");
119 if (ret)
120 sysfs_remove_link_from_group(&dev->kobj, "devices",
121 dev_name(link));
122
123 return ret;
124}
125
126void iommu_device_unlink(struct device *dev, struct device *link)
127{
128 if (!dev || IS_ERR(dev))
129 return;
130
131 sysfs_remove_link(&link->kobj, "iommu");
132 sysfs_remove_link_from_group(&dev->kobj, "devices", dev_name(link));
133}
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index a2e5843b0a22..7fd16e3d1f25 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -187,6 +187,12 @@ extern int iommu_domain_get_attr(struct iommu_domain *domain, enum iommu_attr,
187 void *data); 187 void *data);
188extern int iommu_domain_set_attr(struct iommu_domain *domain, enum iommu_attr, 188extern int iommu_domain_set_attr(struct iommu_domain *domain, enum iommu_attr,
189 void *data); 189 void *data);
190struct device *iommu_device_create(struct device *parent, void *drvdata,
191 const struct attribute_group **groups,
192 const char *fmt, ...);
193void iommu_device_destroy(struct device *dev);
194int iommu_device_link(struct device *dev, struct device *link);
195void iommu_device_unlink(struct device *dev, struct device *link);
190 196
191/* Window handling function prototypes */ 197/* Window handling function prototypes */
192extern int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr, 198extern int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr,
@@ -397,6 +403,26 @@ static inline int iommu_domain_set_attr(struct iommu_domain *domain,
397 return -EINVAL; 403 return -EINVAL;
398} 404}
399 405
406struct device *iommu_device_create(struct device *parent, void *drvdata,
407 const struct attribute_group **groups,
408 const char *fmt, ...)
409{
410 return ERR_PTR(-ENODEV);
411}
412
413void iommu_device_destroy(struct device *dev)
414{
415}
416
417int iommu_device_link(struct device *dev, struct device *link)
418{
419 return -EINVAL;
420}
421
422void iommu_device_unlink(struct device *dev, struct device *link)
423{
424}
425
400#endif /* CONFIG_IOMMU_API */ 426#endif /* CONFIG_IOMMU_API */
401 427
402#endif /* __LINUX_IOMMU_H */ 428#endif /* __LINUX_IOMMU_H */