Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * IOMMU sysfs class support
4 : : *
5 : : * Copyright (C) 2014 Red Hat, Inc. All rights reserved.
6 : : * Author: Alex Williamson <alex.williamson@redhat.com>
7 : : */
8 : :
9 : : #include <linux/device.h>
10 : : #include <linux/iommu.h>
11 : : #include <linux/init.h>
12 : : #include <linux/slab.h>
13 : :
14 : : /*
15 : : * We provide a common class "devices" group which initially has no attributes.
16 : : * As devices are added to the IOMMU, we'll add links to the group.
17 : : */
18 : : static struct attribute *devices_attr[] = {
19 : : NULL,
20 : : };
21 : :
22 : : static const struct attribute_group devices_attr_group = {
23 : : .name = "devices",
24 : : .attrs = devices_attr,
25 : : };
26 : :
27 : : static const struct attribute_group *dev_groups[] = {
28 : : &devices_attr_group,
29 : : NULL,
30 : : };
31 : :
32 : 0 : static void release_device(struct device *dev)
33 : : {
34 : 0 : kfree(dev);
35 : 0 : }
36 : :
37 : : static struct class iommu_class = {
38 : : .name = "iommu",
39 : : .dev_release = release_device,
40 : : .dev_groups = dev_groups,
41 : : };
42 : :
43 : 13 : static int __init iommu_dev_init(void)
44 : : {
45 : 13 : return class_register(&iommu_class);
46 : : }
47 : : postcore_initcall(iommu_dev_init);
48 : :
49 : : /*
50 : : * Init the struct device for the IOMMU. IOMMU specific attributes can
51 : : * be provided as an attribute group, allowing a unique namespace per
52 : : * IOMMU type.
53 : : */
54 : 0 : int iommu_device_sysfs_add(struct iommu_device *iommu,
55 : : struct device *parent,
56 : : const struct attribute_group **groups,
57 : : const char *fmt, ...)
58 : : {
59 : 0 : va_list vargs;
60 : 0 : int ret;
61 : :
62 : 0 : iommu->dev = kzalloc(sizeof(*iommu->dev), GFP_KERNEL);
63 [ # # ]: 0 : if (!iommu->dev)
64 : : return -ENOMEM;
65 : :
66 : 0 : device_initialize(iommu->dev);
67 : :
68 : 0 : iommu->dev->class = &iommu_class;
69 : 0 : iommu->dev->parent = parent;
70 : 0 : iommu->dev->groups = groups;
71 : :
72 : 0 : va_start(vargs, fmt);
73 : 0 : ret = kobject_set_name_vargs(&iommu->dev->kobj, fmt, vargs);
74 : 0 : va_end(vargs);
75 [ # # ]: 0 : if (ret)
76 : 0 : goto error;
77 : :
78 : 0 : ret = device_add(iommu->dev);
79 [ # # ]: 0 : if (ret)
80 : 0 : goto error;
81 : :
82 : 0 : dev_set_drvdata(iommu->dev, iommu);
83 : :
84 : 0 : return 0;
85 : :
86 : 0 : error:
87 : 0 : put_device(iommu->dev);
88 : 0 : return ret;
89 : : }
90 : : EXPORT_SYMBOL_GPL(iommu_device_sysfs_add);
91 : :
92 : 0 : void iommu_device_sysfs_remove(struct iommu_device *iommu)
93 : : {
94 : 0 : dev_set_drvdata(iommu->dev, NULL);
95 : 0 : device_unregister(iommu->dev);
96 : 0 : iommu->dev = NULL;
97 : 0 : }
98 : : EXPORT_SYMBOL_GPL(iommu_device_sysfs_remove);
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 : : */
106 : 0 : int iommu_device_link(struct iommu_device *iommu, struct device *link)
107 : : {
108 : 0 : int ret;
109 : :
110 [ # # # # ]: 0 : if (!iommu || IS_ERR(iommu))
111 : : return -ENODEV;
112 : :
113 [ # # ]: 0 : ret = sysfs_add_link_to_group(&iommu->dev->kobj, "devices",
114 : : &link->kobj, dev_name(link));
115 [ # # ]: 0 : if (ret)
116 : : return ret;
117 : :
118 : 0 : ret = sysfs_create_link_nowarn(&link->kobj, &iommu->dev->kobj, "iommu");
119 [ # # ]: 0 : if (ret)
120 [ # # ]: 0 : sysfs_remove_link_from_group(&iommu->dev->kobj, "devices",
121 : : dev_name(link));
122 : :
123 : : return ret;
124 : : }
125 : : EXPORT_SYMBOL_GPL(iommu_device_link);
126 : :
127 : 0 : void iommu_device_unlink(struct iommu_device *iommu, struct device *link)
128 : : {
129 [ # # # # ]: 0 : if (!iommu || IS_ERR(iommu))
130 : : return;
131 : :
132 : 0 : sysfs_remove_link(&link->kobj, "iommu");
133 [ # # ]: 0 : sysfs_remove_link_from_group(&iommu->dev->kobj, "devices", dev_name(link));
134 : : }
135 : : EXPORT_SYMBOL_GPL(iommu_device_unlink);
|