xref: /openbmc/linux/drivers/iommu/iommu-sysfs.c (revision 9a108996)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2c61959ecSAlex Williamson /*
3c61959ecSAlex Williamson  * IOMMU sysfs class support
4c61959ecSAlex Williamson  *
5c61959ecSAlex Williamson  * Copyright (C) 2014 Red Hat, Inc.  All rights reserved.
6c61959ecSAlex Williamson  *     Author: Alex Williamson <alex.williamson@redhat.com>
7c61959ecSAlex Williamson  */
8c61959ecSAlex Williamson 
9c61959ecSAlex Williamson #include <linux/device.h>
10c61959ecSAlex Williamson #include <linux/iommu.h>
11c1af7b40SPaul Gortmaker #include <linux/init.h>
12ffd78f00SJoerg Roedel #include <linux/slab.h>
13c61959ecSAlex Williamson 
14c61959ecSAlex Williamson /*
15c61959ecSAlex Williamson  * We provide a common class "devices" group which initially has no attributes.
16c61959ecSAlex Williamson  * As devices are added to the IOMMU, we'll add links to the group.
17c61959ecSAlex Williamson  */
18c61959ecSAlex Williamson static struct attribute *devices_attr[] = {
19c61959ecSAlex Williamson 	NULL,
20c61959ecSAlex Williamson };
21c61959ecSAlex Williamson 
226954cf9bSJoerg Roedel static const struct attribute_group devices_attr_group = {
23c61959ecSAlex Williamson 	.name = "devices",
24c61959ecSAlex Williamson 	.attrs = devices_attr,
25c61959ecSAlex Williamson };
26c61959ecSAlex Williamson 
276954cf9bSJoerg Roedel static const struct attribute_group *dev_groups[] = {
286954cf9bSJoerg Roedel 	&devices_attr_group,
29c61959ecSAlex Williamson 	NULL,
30c61959ecSAlex Williamson };
31c61959ecSAlex Williamson 
release_device(struct device * dev)326954cf9bSJoerg Roedel static void release_device(struct device *dev)
33c61959ecSAlex Williamson {
34c61959ecSAlex Williamson 	kfree(dev);
35c61959ecSAlex Williamson }
36c61959ecSAlex Williamson 
37c61959ecSAlex Williamson static struct class iommu_class = {
38c61959ecSAlex Williamson 	.name = "iommu",
396954cf9bSJoerg Roedel 	.dev_release = release_device,
406954cf9bSJoerg Roedel 	.dev_groups = dev_groups,
41c61959ecSAlex Williamson };
42c61959ecSAlex Williamson 
iommu_dev_init(void)43c61959ecSAlex Williamson static int __init iommu_dev_init(void)
44c61959ecSAlex Williamson {
45c61959ecSAlex Williamson 	return class_register(&iommu_class);
46c61959ecSAlex Williamson }
47c61959ecSAlex Williamson postcore_initcall(iommu_dev_init);
48c61959ecSAlex Williamson 
49c61959ecSAlex Williamson /*
5039ab9555SJoerg Roedel  * Init the struct device for the IOMMU. IOMMU specific attributes can
5139ab9555SJoerg Roedel  * be provided as an attribute group, allowing a unique namespace per
5239ab9555SJoerg Roedel  * IOMMU type.
53c61959ecSAlex Williamson  */
iommu_device_sysfs_add(struct iommu_device * iommu,struct device * parent,const struct attribute_group ** groups,const char * fmt,...)5439ab9555SJoerg Roedel int iommu_device_sysfs_add(struct iommu_device *iommu,
5539ab9555SJoerg Roedel 			   struct device *parent,
56c61959ecSAlex Williamson 			   const struct attribute_group **groups,
57c61959ecSAlex Williamson 			   const char *fmt, ...)
58c61959ecSAlex Williamson {
59c61959ecSAlex Williamson 	va_list vargs;
60c61959ecSAlex Williamson 	int ret;
61c61959ecSAlex Williamson 
622926a2aaSJoerg Roedel 	iommu->dev = kzalloc(sizeof(*iommu->dev), GFP_KERNEL);
632926a2aaSJoerg Roedel 	if (!iommu->dev)
642926a2aaSJoerg Roedel 		return -ENOMEM;
65c61959ecSAlex Williamson 
662926a2aaSJoerg Roedel 	device_initialize(iommu->dev);
672926a2aaSJoerg Roedel 
682926a2aaSJoerg Roedel 	iommu->dev->class = &iommu_class;
692926a2aaSJoerg Roedel 	iommu->dev->parent = parent;
702926a2aaSJoerg Roedel 	iommu->dev->groups = groups;
71c61959ecSAlex Williamson 
72c61959ecSAlex Williamson 	va_start(vargs, fmt);
732926a2aaSJoerg Roedel 	ret = kobject_set_name_vargs(&iommu->dev->kobj, fmt, vargs);
74c61959ecSAlex Williamson 	va_end(vargs);
75c61959ecSAlex Williamson 	if (ret)
76c61959ecSAlex Williamson 		goto error;
77c61959ecSAlex Williamson 
782926a2aaSJoerg Roedel 	ret = device_add(iommu->dev);
79c61959ecSAlex Williamson 	if (ret)
80c61959ecSAlex Williamson 		goto error;
81c61959ecSAlex Williamson 
822926a2aaSJoerg Roedel 	dev_set_drvdata(iommu->dev, iommu);
832926a2aaSJoerg Roedel 
8439ab9555SJoerg Roedel 	return 0;
85c61959ecSAlex Williamson 
86c61959ecSAlex Williamson error:
872926a2aaSJoerg Roedel 	put_device(iommu->dev);
8839ab9555SJoerg Roedel 	return ret;
89c61959ecSAlex Williamson }
90a7ba5c3dSWill Deacon EXPORT_SYMBOL_GPL(iommu_device_sysfs_add);
91c61959ecSAlex Williamson 
iommu_device_sysfs_remove(struct iommu_device * iommu)9239ab9555SJoerg Roedel void iommu_device_sysfs_remove(struct iommu_device *iommu)
93c61959ecSAlex Williamson {
942926a2aaSJoerg Roedel 	dev_set_drvdata(iommu->dev, NULL);
952926a2aaSJoerg Roedel 	device_unregister(iommu->dev);
962926a2aaSJoerg Roedel 	iommu->dev = NULL;
97c61959ecSAlex Williamson }
98a7ba5c3dSWill Deacon EXPORT_SYMBOL_GPL(iommu_device_sysfs_remove);
99a7ba5c3dSWill Deacon 
100c61959ecSAlex Williamson /*
101c61959ecSAlex Williamson  * IOMMU drivers can indicate a device is managed by a given IOMMU using
102c61959ecSAlex Williamson  * this interface.  A link to the device will be created in the "devices"
103c61959ecSAlex Williamson  * directory of the IOMMU device in sysfs and an "iommu" link will be
104c61959ecSAlex Williamson  * created under the linked device, pointing back at the IOMMU device.
105c61959ecSAlex Williamson  */
iommu_device_link(struct iommu_device * iommu,struct device * link)106e3d10af1SJoerg Roedel int iommu_device_link(struct iommu_device *iommu, struct device *link)
107c61959ecSAlex Williamson {
108c61959ecSAlex Williamson 	int ret;
109c61959ecSAlex Williamson 
1102926a2aaSJoerg Roedel 	ret = sysfs_add_link_to_group(&iommu->dev->kobj, "devices",
111c61959ecSAlex Williamson 				      &link->kobj, dev_name(link));
112c61959ecSAlex Williamson 	if (ret)
113c61959ecSAlex Williamson 		return ret;
114c61959ecSAlex Williamson 
1152926a2aaSJoerg Roedel 	ret = sysfs_create_link_nowarn(&link->kobj, &iommu->dev->kobj, "iommu");
116c61959ecSAlex Williamson 	if (ret)
1172926a2aaSJoerg Roedel 		sysfs_remove_link_from_group(&iommu->dev->kobj, "devices",
118c61959ecSAlex Williamson 					     dev_name(link));
119c61959ecSAlex Williamson 
120c61959ecSAlex Williamson 	return ret;
121c61959ecSAlex Williamson }
122c61959ecSAlex Williamson 
iommu_device_unlink(struct iommu_device * iommu,struct device * link)123e3d10af1SJoerg Roedel void iommu_device_unlink(struct iommu_device *iommu, struct device *link)
124c61959ecSAlex Williamson {
125c61959ecSAlex Williamson 	sysfs_remove_link(&link->kobj, "iommu");
1262926a2aaSJoerg Roedel 	sysfs_remove_link_from_group(&iommu->dev->kobj, "devices", dev_name(link));
127c61959ecSAlex Williamson }
128