Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * IOMMU sysfs class support
0004  *
0005  * Copyright (C) 2014 Red Hat, Inc.  All rights reserved.
0006  *     Author: Alex Williamson <alex.williamson@redhat.com>
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  * We provide a common class "devices" group which initially has no attributes.
0016  * As devices are added to the IOMMU, we'll add links to the group.
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  * Init the struct device for the IOMMU. IOMMU specific attributes can
0051  * be provided as an attribute group, allowing a unique namespace per
0052  * IOMMU type.
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  * IOMMU drivers can indicate a device is managed by a given IOMMU using
0102  * this interface.  A link to the device will be created in the "devices"
0103  * directory of the IOMMU device in sysfs and an "iommu" link will be
0104  * created under the linked device, pointing back at the IOMMU device.
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);