Skip to content

Commit

Permalink
iommu: Add sysfs bindings for struct iommu_device
Browse files Browse the repository at this point in the history
There is currently support for iommu sysfs bindings, but
those need to be implemented in the IOMMU drivers. Add a
more generic version of this by adding a struct device to
struct iommu_device and use that for the sysfs bindings.

Also convert the AMD and Intel IOMMU driver to make use of
it.

Signed-off-by: Joerg Roedel <jroedel@suse.de>
  • Loading branch information
Joerg Roedel committed Feb 10, 2017
1 parent b0119e8 commit 39ab955
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 69 deletions.
14 changes: 9 additions & 5 deletions drivers/iommu/amd_iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,7 @@ static void init_iommu_group(struct device *dev)
static int iommu_init_device(struct device *dev)
{
struct iommu_dev_data *dev_data;
struct amd_iommu *iommu;
int devid;

if (dev->archdata.iommu)
Expand All @@ -454,6 +455,8 @@ static int iommu_init_device(struct device *dev)
if (devid < 0)
return devid;

iommu = amd_iommu_rlookup_table[devid];

dev_data = find_dev_data(devid);
if (!dev_data)
return -ENOMEM;
Expand All @@ -469,8 +472,7 @@ static int iommu_init_device(struct device *dev)

dev->archdata.iommu = dev_data;

iommu_device_link(amd_iommu_rlookup_table[dev_data->devid]->iommu_dev,
dev);
iommu_device_link(&iommu->iommu.dev, dev);

return 0;
}
Expand All @@ -495,22 +497,24 @@ static void iommu_ignore_device(struct device *dev)

static void iommu_uninit_device(struct device *dev)
{
int devid;
struct iommu_dev_data *dev_data;
struct amd_iommu *iommu;
int devid;

devid = get_device_id(dev);
if (devid < 0)
return;

iommu = amd_iommu_rlookup_table[devid];

dev_data = search_dev_data(devid);
if (!dev_data)
return;

if (dev_data->domain)
detach_device(dev);

iommu_device_unlink(amd_iommu_rlookup_table[dev_data->devid]->iommu_dev,
dev);
iommu_device_unlink(&iommu->iommu.dev, dev);

iommu_group_remove_device(dev);

Expand Down
6 changes: 2 additions & 4 deletions drivers/iommu/amd_iommu_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -1637,10 +1637,8 @@ static int iommu_init_pci(struct amd_iommu *iommu)
amd_iommu_erratum_746_workaround(iommu);
amd_iommu_ats_write_check_workaround(iommu);

iommu->iommu_dev = iommu_device_create(&iommu->dev->dev, iommu,
amd_iommu_groups, "ivhd%d",
iommu->index);

iommu_device_sysfs_add(&iommu->iommu, &iommu->dev->dev,
amd_iommu_groups, "ivhd%d", iommu->index);
iommu_device_set_ops(&iommu->iommu, &amd_iommu_ops);
iommu_device_register(&iommu->iommu);

Expand Down
3 changes: 0 additions & 3 deletions drivers/iommu/amd_iommu_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -535,9 +535,6 @@ struct amd_iommu {
/* if one, we need to send a completion wait command */
bool need_sync;

/* IOMMU sysfs device */
struct device *iommu_dev;

/* Handle for IOMMU core code */
struct iommu_device iommu;

Expand Down
13 changes: 5 additions & 8 deletions drivers/iommu/dmar.c
Original file line number Diff line number Diff line change
Expand Up @@ -1078,14 +1078,11 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
raw_spin_lock_init(&iommu->register_lock);

if (intel_iommu_enabled) {
iommu->iommu_dev = iommu_device_create(NULL, iommu,
intel_iommu_groups,
"%s", iommu->name);

if (IS_ERR(iommu->iommu_dev)) {
err = PTR_ERR(iommu->iommu_dev);
err = iommu_device_sysfs_add(&iommu->iommu, NULL,
intel_iommu_groups,
"%s", iommu->name);
if (err)
goto err_unmap;
}

iommu_device_set_ops(&iommu->iommu, &intel_iommu_ops);

Expand All @@ -1109,7 +1106,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)

static void free_iommu(struct intel_iommu *iommu)
{
iommu_device_destroy(iommu->iommu_dev);
iommu_device_sysfs_remove(&iommu->iommu);
iommu_device_unregister(&iommu->iommu);

if (iommu->irq) {
Expand Down
15 changes: 9 additions & 6 deletions drivers/iommu/intel-iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -4834,10 +4834,13 @@ int __init intel_iommu_init(void)

init_iommu_pm_ops();

for_each_active_iommu(iommu, drhd)
iommu->iommu_dev = iommu_device_create(NULL, iommu,
intel_iommu_groups,
"%s", iommu->name);
for_each_active_iommu(iommu, drhd) {
iommu_device_sysfs_add(&iommu->iommu, NULL,
intel_iommu_groups,
"%s", iommu->name);
iommu_device_set_ops(&iommu->iommu, &intel_iommu_ops);
iommu_device_register(&iommu->iommu);
}

bus_set_iommu(&pci_bus_type, &intel_iommu_ops);
bus_register_notifier(&pci_bus_type, &device_nb);
Expand Down Expand Up @@ -5159,7 +5162,7 @@ static int intel_iommu_add_device(struct device *dev)
if (!iommu)
return -ENODEV;

iommu_device_link(iommu->iommu_dev, dev);
iommu_device_link(&iommu->iommu.dev, dev);

group = iommu_group_get_for_dev(dev);

Expand All @@ -5181,7 +5184,7 @@ static void intel_iommu_remove_device(struct device *dev)

iommu_group_remove_device(dev);

iommu_device_unlink(iommu->iommu_dev, dev);
iommu_device_unlink(&iommu->iommu.dev, dev);
}

#ifdef CONFIG_INTEL_IOMMU_SVM
Expand Down
45 changes: 18 additions & 27 deletions drivers/iommu/iommu-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,54 +50,45 @@ static int __init iommu_dev_init(void)
postcore_initcall(iommu_dev_init);

/*
* Create an IOMMU device and return a pointer to it. IOMMU specific
* attributes can be provided as an attribute group, allowing a unique
* namespace per IOMMU type.
* Init the struct device for the IOMMU. IOMMU specific attributes can
* be provided as an attribute group, allowing a unique namespace per
* IOMMU type.
*/
struct device *iommu_device_create(struct device *parent, void *drvdata,
const struct attribute_group **groups,
const char *fmt, ...)
int iommu_device_sysfs_add(struct iommu_device *iommu,
struct device *parent,
const struct attribute_group **groups,
const char *fmt, ...)
{
struct device *dev;
va_list vargs;
int ret;

dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev)
return ERR_PTR(-ENOMEM);
device_initialize(&iommu->dev);

device_initialize(dev);

dev->class = &iommu_class;
dev->parent = parent;
dev->groups = groups;
dev_set_drvdata(dev, drvdata);
iommu->dev.class = &iommu_class;
iommu->dev.parent = parent;
iommu->dev.groups = groups;

va_start(vargs, fmt);
ret = kobject_set_name_vargs(&dev->kobj, fmt, vargs);
ret = kobject_set_name_vargs(&iommu->dev.kobj, fmt, vargs);
va_end(vargs);
if (ret)
goto error;

ret = device_add(dev);
ret = device_add(&iommu->dev);
if (ret)
goto error;

return dev;
return 0;

error:
put_device(dev);
return ERR_PTR(ret);
put_device(&iommu->dev);
return ret;
}

void iommu_device_destroy(struct device *dev)
void iommu_device_sysfs_remove(struct iommu_device *iommu)
{
if (!dev || IS_ERR(dev))
return;

device_unregister(dev);
device_unregister(&iommu->dev);
}

/*
* 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"
Expand Down
1 change: 0 additions & 1 deletion include/linux/intel-iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,6 @@ struct intel_iommu {
struct irq_domain *ir_domain;
struct irq_domain *ir_msi_domain;
#endif
struct device *iommu_dev; /* IOMMU-sysfs device */
struct iommu_device iommu; /* IOMMU core code handle */
int node;
u32 flags; /* Software defined flags */
Expand Down
33 changes: 18 additions & 15 deletions include/linux/iommu.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,14 +209,21 @@ struct iommu_ops {
* instance
* @list: Used by the iommu-core to keep a list of registered iommus
* @ops: iommu-ops for talking to this iommu
* @dev: struct device for sysfs handling
*/
struct iommu_device {
struct list_head list;
const struct iommu_ops *ops;
struct device dev;
};

int iommu_device_register(struct iommu_device *iommu);
void iommu_device_unregister(struct iommu_device *iommu);
int iommu_device_sysfs_add(struct iommu_device *iommu,
struct device *parent,
const struct attribute_group **groups,
const char *fmt, ...) __printf(4, 5);
void iommu_device_sysfs_remove(struct iommu_device *iommu);

static inline void iommu_device_set_ops(struct iommu_device *iommu,
const struct iommu_ops *ops)
Expand Down Expand Up @@ -287,10 +294,6 @@ extern int iommu_domain_get_attr(struct iommu_domain *domain, enum iommu_attr,
void *data);
extern int iommu_domain_set_attr(struct iommu_domain *domain, enum iommu_attr,
void *data);
struct device *iommu_device_create(struct device *parent, void *drvdata,
const struct attribute_group **groups,
const char *fmt, ...) __printf(4, 5);
void iommu_device_destroy(struct device *dev);
int iommu_device_link(struct device *dev, struct device *link);
void iommu_device_unlink(struct device *dev, struct device *link);

Expand Down Expand Up @@ -567,29 +570,29 @@ static inline int iommu_domain_set_attr(struct iommu_domain *domain,
return -EINVAL;
}

static inline struct device *iommu_device_create(struct device *parent,
void *drvdata,
const struct attribute_group **groups,
const char *fmt, ...)
static inline int iommu_device_register(struct iommu_device *iommu)
{
return ERR_PTR(-ENODEV);
return -ENODEV;
}

static inline void iommu_device_destroy(struct device *dev)
static inline void iommu_device_set_ops(struct iommu_device *iommu,
const struct iommu_ops *ops)
{
}

static inline int iommu_device_register(struct iommu_device *iommu)
static inline void iommu_device_unregister(struct iommu_device *iommu)
{
return -ENODEV;
}

static inline void iommu_device_set_ops(struct iommu_device *iommu,
const struct iommu_ops *ops)
static inline int iommu_device_sysfs_add(struct iommu_device *iommu,
struct device *parent,
const struct attribute_group **groups,
const char *fmt, ...)
{
return -ENODEV;
}

static inline void iommu_device_unregister(struct iommu_device *iommu)
static inline void iommu_device_sysfs_remove(struct iommu_device *iommu)
{
}

Expand Down

0 comments on commit 39ab955

Please sign in to comment.