2019-06-04 11:11:33 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2014-06-13 02:12:24 +04:00
/*
* IOMMU sysfs class support
*
* Copyright ( C ) 2014 Red Hat , Inc . All rights reserved .
* Author : Alex Williamson < alex . williamson @ redhat . com >
*/
# include <linux/device.h>
# include <linux/iommu.h>
2018-12-01 22:19:09 +03:00
# include <linux/init.h>
2014-07-07 14:01:21 +04:00
# include <linux/slab.h>
2014-06-13 02:12:24 +04:00
/*
* We provide a common class " devices " group which initially has no attributes .
* As devices are added to the IOMMU , we ' ll add links to the group .
*/
static struct attribute * devices_attr [ ] = {
NULL ,
} ;
2018-12-05 15:57:43 +03:00
static const struct attribute_group devices_attr_group = {
2014-06-13 02:12:24 +04:00
. name = " devices " ,
. attrs = devices_attr ,
} ;
2018-12-05 15:57:43 +03:00
static const struct attribute_group * dev_groups [ ] = {
& devices_attr_group ,
2014-06-13 02:12:24 +04:00
NULL ,
} ;
2018-12-05 15:57:43 +03:00
static void release_device ( struct device * dev )
2014-06-13 02:12:24 +04:00
{
kfree ( dev ) ;
}
static struct class iommu_class = {
. name = " iommu " ,
2018-12-05 15:57:43 +03:00
. dev_release = release_device ,
. dev_groups = dev_groups ,
2014-06-13 02:12:24 +04:00
} ;
static int __init iommu_dev_init ( void )
{
return class_register ( & iommu_class ) ;
}
postcore_initcall ( iommu_dev_init ) ;
/*
2017-02-01 18:56:46 +03:00
* Init the struct device for the IOMMU . IOMMU specific attributes can
* be provided as an attribute group , allowing a unique namespace per
* IOMMU type .
2014-06-13 02:12:24 +04:00
*/
2017-02-01 18:56:46 +03:00
int iommu_device_sysfs_add ( struct iommu_device * iommu ,
struct device * parent ,
const struct attribute_group * * groups ,
const char * fmt , . . . )
2014-06-13 02:12:24 +04:00
{
va_list vargs ;
int ret ;
2017-08-14 18:19:26 +03:00
iommu - > dev = kzalloc ( sizeof ( * iommu - > dev ) , GFP_KERNEL ) ;
if ( ! iommu - > dev )
return - ENOMEM ;
2014-06-13 02:12:24 +04:00
2017-08-14 18:19:26 +03:00
device_initialize ( iommu - > dev ) ;
iommu - > dev - > class = & iommu_class ;
iommu - > dev - > parent = parent ;
iommu - > dev - > groups = groups ;
2014-06-13 02:12:24 +04:00
va_start ( vargs , fmt ) ;
2017-08-14 18:19:26 +03:00
ret = kobject_set_name_vargs ( & iommu - > dev - > kobj , fmt , vargs ) ;
2014-06-13 02:12:24 +04:00
va_end ( vargs ) ;
if ( ret )
goto error ;
2017-08-14 18:19:26 +03:00
ret = device_add ( iommu - > dev ) ;
2014-06-13 02:12:24 +04:00
if ( ret )
goto error ;
2017-08-14 18:19:26 +03:00
dev_set_drvdata ( iommu - > dev , iommu ) ;
2017-02-01 18:56:46 +03:00
return 0 ;
2014-06-13 02:12:24 +04:00
error :
2017-08-14 18:19:26 +03:00
put_device ( iommu - > dev ) ;
2017-02-01 18:56:46 +03:00
return ret ;
2014-06-13 02:12:24 +04:00
}
2019-12-19 15:03:37 +03:00
EXPORT_SYMBOL_GPL ( iommu_device_sysfs_add ) ;
2014-06-13 02:12:24 +04:00
2017-02-01 18:56:46 +03:00
void iommu_device_sysfs_remove ( struct iommu_device * iommu )
2014-06-13 02:12:24 +04:00
{
2017-08-14 18:19:26 +03:00
dev_set_drvdata ( iommu - > dev , NULL ) ;
device_unregister ( iommu - > dev ) ;
iommu - > dev = NULL ;
2014-06-13 02:12:24 +04:00
}
2019-12-19 15:03:37 +03:00
EXPORT_SYMBOL_GPL ( iommu_device_sysfs_remove ) ;
2014-06-13 02:12:24 +04:00
/*
* IOMMU drivers can indicate a device is managed by a given IOMMU using
* this interface . A link to the device will be created in the " devices "
* directory of the IOMMU device in sysfs and an " iommu " link will be
* created under the linked device , pointing back at the IOMMU device .
*/
2017-02-01 19:23:22 +03:00
int iommu_device_link ( struct iommu_device * iommu , struct device * link )
2014-06-13 02:12:24 +04:00
{
int ret ;
2017-02-01 19:23:22 +03:00
if ( ! iommu | | IS_ERR ( iommu ) )
2014-06-13 02:12:24 +04:00
return - ENODEV ;
2017-08-14 18:19:26 +03:00
ret = sysfs_add_link_to_group ( & iommu - > dev - > kobj , " devices " ,
2014-06-13 02:12:24 +04:00
& link - > kobj , dev_name ( link ) ) ;
if ( ret )
return ret ;
2017-08-14 18:19:26 +03:00
ret = sysfs_create_link_nowarn ( & link - > kobj , & iommu - > dev - > kobj , " iommu " ) ;
2014-06-13 02:12:24 +04:00
if ( ret )
2017-08-14 18:19:26 +03:00
sysfs_remove_link_from_group ( & iommu - > dev - > kobj , " devices " ,
2014-06-13 02:12:24 +04:00
dev_name ( link ) ) ;
return ret ;
}
2019-12-19 15:03:37 +03:00
EXPORT_SYMBOL_GPL ( iommu_device_link ) ;
2014-06-13 02:12:24 +04:00
2017-02-01 19:23:22 +03:00
void iommu_device_unlink ( struct iommu_device * iommu , struct device * link )
2014-06-13 02:12:24 +04:00
{
2017-02-01 19:23:22 +03:00
if ( ! iommu | | IS_ERR ( iommu ) )
2014-06-13 02:12:24 +04:00
return ;
sysfs_remove_link ( & link - > kobj , " iommu " ) ;
2017-08-14 18:19:26 +03:00
sysfs_remove_link_from_group ( & iommu - > dev - > kobj , " devices " , dev_name ( link ) ) ;
2014-06-13 02:12:24 +04:00
}
2019-12-19 15:03:37 +03:00
EXPORT_SYMBOL_GPL ( iommu_device_unlink ) ;