0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/device.h>
0010 #include <linux/iommu.h>
0011 #include <linux/init.h>
0012 #include <linux/slab.h>
0013
0014
0015
0016
0017
0018 static struct attribute *devices_attr[] = {
0019 NULL,
0020 };
0021
0022 static const struct attribute_group devices_attr_group = {
0023 .name = "devices",
0024 .attrs = devices_attr,
0025 };
0026
0027 static const struct attribute_group *dev_groups[] = {
0028 &devices_attr_group,
0029 NULL,
0030 };
0031
0032 static void release_device(struct device *dev)
0033 {
0034 kfree(dev);
0035 }
0036
0037 static struct class iommu_class = {
0038 .name = "iommu",
0039 .dev_release = release_device,
0040 .dev_groups = dev_groups,
0041 };
0042
0043 static int __init iommu_dev_init(void)
0044 {
0045 return class_register(&iommu_class);
0046 }
0047 postcore_initcall(iommu_dev_init);
0048
0049
0050
0051
0052
0053
0054 int iommu_device_sysfs_add(struct iommu_device *iommu,
0055 struct device *parent,
0056 const struct attribute_group **groups,
0057 const char *fmt, ...)
0058 {
0059 va_list vargs;
0060 int ret;
0061
0062 iommu->dev = kzalloc(sizeof(*iommu->dev), GFP_KERNEL);
0063 if (!iommu->dev)
0064 return -ENOMEM;
0065
0066 device_initialize(iommu->dev);
0067
0068 iommu->dev->class = &iommu_class;
0069 iommu->dev->parent = parent;
0070 iommu->dev->groups = groups;
0071
0072 va_start(vargs, fmt);
0073 ret = kobject_set_name_vargs(&iommu->dev->kobj, fmt, vargs);
0074 va_end(vargs);
0075 if (ret)
0076 goto error;
0077
0078 ret = device_add(iommu->dev);
0079 if (ret)
0080 goto error;
0081
0082 dev_set_drvdata(iommu->dev, iommu);
0083
0084 return 0;
0085
0086 error:
0087 put_device(iommu->dev);
0088 return ret;
0089 }
0090 EXPORT_SYMBOL_GPL(iommu_device_sysfs_add);
0091
0092 void iommu_device_sysfs_remove(struct iommu_device *iommu)
0093 {
0094 dev_set_drvdata(iommu->dev, NULL);
0095 device_unregister(iommu->dev);
0096 iommu->dev = NULL;
0097 }
0098 EXPORT_SYMBOL_GPL(iommu_device_sysfs_remove);
0099
0100
0101
0102
0103
0104
0105
0106 int iommu_device_link(struct iommu_device *iommu, struct device *link)
0107 {
0108 int ret;
0109
0110 if (!iommu || IS_ERR(iommu))
0111 return -ENODEV;
0112
0113 ret = sysfs_add_link_to_group(&iommu->dev->kobj, "devices",
0114 &link->kobj, dev_name(link));
0115 if (ret)
0116 return ret;
0117
0118 ret = sysfs_create_link_nowarn(&link->kobj, &iommu->dev->kobj, "iommu");
0119 if (ret)
0120 sysfs_remove_link_from_group(&iommu->dev->kobj, "devices",
0121 dev_name(link));
0122
0123 return ret;
0124 }
0125 EXPORT_SYMBOL_GPL(iommu_device_link);
0126
0127 void iommu_device_unlink(struct iommu_device *iommu, struct device *link)
0128 {
0129 if (!iommu || IS_ERR(iommu))
0130 return;
0131
0132 sysfs_remove_link(&link->kobj, "iommu");
0133 sysfs_remove_link_from_group(&iommu->dev->kobj, "devices", dev_name(link));
0134 }
0135 EXPORT_SYMBOL_GPL(iommu_device_unlink);