From 797a8b4d768c58caac58ee3e8cb36a164d1b7751 Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Mon, 16 Jan 2017 12:58:07 +0000 Subject: iommu: Handle default domain attach failure We wouldn't normally expect ops->attach_dev() to fail, but on IOMMUs with limited hardware resources, or generally misconfigured systems, it is certainly possible. We report failure correctly from the external iommu_attach_device() interface, but do not do so in iommu_group_add() when attaching to the default domain. The result of failure there is that the device, group and domain all get left in a broken, part-configured state which leads to weird errors and misbehaviour down the line when IOMMU API calls sort-of-but-don't-quite work. Check the return value of __iommu_attach_device() on the default domain, and refactor the error handling paths to cope with its failure and clean up correctly in such cases. Fixes: e39cb8a3aa98 ("iommu: Make sure a device is always attached to a domain") Reported-by: Punit Agrawal Signed-off-by: Robin Murphy Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) (limited to 'drivers/iommu/iommu.c') diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index dbe7f653bb7c..aed906a3e3db 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -383,36 +383,30 @@ int iommu_group_add_device(struct iommu_group *group, struct device *dev) device->dev = dev; ret = sysfs_create_link(&dev->kobj, &group->kobj, "iommu_group"); - if (ret) { - kfree(device); - return ret; - } + if (ret) + goto err_free_device; device->name = kasprintf(GFP_KERNEL, "%s", kobject_name(&dev->kobj)); rename: if (!device->name) { - sysfs_remove_link(&dev->kobj, "iommu_group"); - kfree(device); - return -ENOMEM; + ret = -ENOMEM; + goto err_remove_link; } ret = sysfs_create_link_nowarn(group->devices_kobj, &dev->kobj, device->name); if (ret) { - kfree(device->name); if (ret == -EEXIST && i >= 0) { /* * Account for the slim chance of collision * and append an instance to the name. */ + kfree(device->name); device->name = kasprintf(GFP_KERNEL, "%s.%d", kobject_name(&dev->kobj), i++); goto rename; } - - sysfs_remove_link(&dev->kobj, "iommu_group"); - kfree(device); - return ret; + goto err_free_name; } kobject_get(group->devices_kobj); @@ -424,8 +418,10 @@ rename: mutex_lock(&group->mutex); list_add_tail(&device->list, &group->devices); if (group->domain) - __iommu_attach_device(group->domain, dev); + ret = __iommu_attach_device(group->domain, dev); mutex_unlock(&group->mutex); + if (ret) + goto err_put_group; /* Notify any listeners about change to group. */ blocking_notifier_call_chain(&group->notifier, @@ -436,6 +432,21 @@ rename: pr_info("Adding device %s to group %d\n", dev_name(dev), group->id); return 0; + +err_put_group: + mutex_lock(&group->mutex); + list_del(&device->list); + mutex_unlock(&group->mutex); + dev->iommu_group = NULL; + kobject_put(group->devices_kobj); +err_free_name: + kfree(device->name); +err_remove_link: + sysfs_remove_link(&dev->kobj, "iommu_group"); +err_free_device: + kfree(device); + pr_err("Failed to add device %s to group %d: %d\n", dev_name(dev), group->id, ret); + return ret; } EXPORT_SYMBOL_GPL(iommu_group_add_device); -- cgit v1.2.3 From e5b5234a36ca283158721d3d2e0cddfa324abdf9 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 19 Jan 2017 20:57:47 +0000 Subject: iommu: Rename iommu_dm_regions into iommu_resv_regions We want to extend the callbacks used for dm regions and use them for reserved regions. Reserved regions can be - directly mapped regions - regions that cannot be iommu mapped (PCI host bridge windows, ...) - MSI regions (because they belong to another address space or because they are not translated by the IOMMU and need special handling) So let's rename the struct and also the callbacks. Signed-off-by: Eric Auger Acked-by: Robin Murphy Reviewed-by: Tomasz Nowicki Tested-by: Tomasz Nowicki Tested-by: Bharat Bhushan Signed-off-by: Will Deacon --- drivers/iommu/amd_iommu.c | 20 ++++++++++---------- drivers/iommu/iommu.c | 22 +++++++++++----------- include/linux/iommu.h | 29 +++++++++++++++-------------- 3 files changed, 36 insertions(+), 35 deletions(-) (limited to 'drivers/iommu/iommu.c') diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 3ef0f42984f2..f7a024f1e1dc 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -3161,8 +3161,8 @@ static bool amd_iommu_capable(enum iommu_cap cap) return false; } -static void amd_iommu_get_dm_regions(struct device *dev, - struct list_head *head) +static void amd_iommu_get_resv_regions(struct device *dev, + struct list_head *head) { struct unity_map_entry *entry; int devid; @@ -3172,7 +3172,7 @@ static void amd_iommu_get_dm_regions(struct device *dev, return; list_for_each_entry(entry, &amd_iommu_unity_map, list) { - struct iommu_dm_region *region; + struct iommu_resv_region *region; if (devid < entry->devid_start || devid > entry->devid_end) continue; @@ -3195,18 +3195,18 @@ static void amd_iommu_get_dm_regions(struct device *dev, } } -static void amd_iommu_put_dm_regions(struct device *dev, +static void amd_iommu_put_resv_regions(struct device *dev, struct list_head *head) { - struct iommu_dm_region *entry, *next; + struct iommu_resv_region *entry, *next; list_for_each_entry_safe(entry, next, head, list) kfree(entry); } -static void amd_iommu_apply_dm_region(struct device *dev, +static void amd_iommu_apply_resv_region(struct device *dev, struct iommu_domain *domain, - struct iommu_dm_region *region) + struct iommu_resv_region *region) { struct dma_ops_domain *dma_dom = to_dma_ops_domain(to_pdomain(domain)); unsigned long start, end; @@ -3230,9 +3230,9 @@ static const struct iommu_ops amd_iommu_ops = { .add_device = amd_iommu_add_device, .remove_device = amd_iommu_remove_device, .device_group = amd_iommu_device_group, - .get_dm_regions = amd_iommu_get_dm_regions, - .put_dm_regions = amd_iommu_put_dm_regions, - .apply_dm_region = amd_iommu_apply_dm_region, + .get_resv_regions = amd_iommu_get_resv_regions, + .put_resv_regions = amd_iommu_put_resv_regions, + .apply_resv_region = amd_iommu_apply_resv_region, .pgsize_bitmap = AMD_IOMMU_PGSIZES, }; diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index dbe7f653bb7c..1cee5c361c21 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -318,7 +318,7 @@ static int iommu_group_create_direct_mappings(struct iommu_group *group, struct device *dev) { struct iommu_domain *domain = group->default_domain; - struct iommu_dm_region *entry; + struct iommu_resv_region *entry; struct list_head mappings; unsigned long pg_size; int ret = 0; @@ -331,14 +331,14 @@ static int iommu_group_create_direct_mappings(struct iommu_group *group, pg_size = 1UL << __ffs(domain->pgsize_bitmap); INIT_LIST_HEAD(&mappings); - iommu_get_dm_regions(dev, &mappings); + iommu_get_resv_regions(dev, &mappings); /* We need to consider overlapping regions for different devices */ list_for_each_entry(entry, &mappings, list) { dma_addr_t start, end, addr; - if (domain->ops->apply_dm_region) - domain->ops->apply_dm_region(dev, domain, entry); + if (domain->ops->apply_resv_region) + domain->ops->apply_resv_region(dev, domain, entry); start = ALIGN(entry->start, pg_size); end = ALIGN(entry->start + entry->length, pg_size); @@ -358,7 +358,7 @@ static int iommu_group_create_direct_mappings(struct iommu_group *group, } out: - iommu_put_dm_regions(dev, &mappings); + iommu_put_resv_regions(dev, &mappings); return ret; } @@ -1559,20 +1559,20 @@ int iommu_domain_set_attr(struct iommu_domain *domain, } EXPORT_SYMBOL_GPL(iommu_domain_set_attr); -void iommu_get_dm_regions(struct device *dev, struct list_head *list) +void iommu_get_resv_regions(struct device *dev, struct list_head *list) { const struct iommu_ops *ops = dev->bus->iommu_ops; - if (ops && ops->get_dm_regions) - ops->get_dm_regions(dev, list); + if (ops && ops->get_resv_regions) + ops->get_resv_regions(dev, list); } -void iommu_put_dm_regions(struct device *dev, struct list_head *list) +void iommu_put_resv_regions(struct device *dev, struct list_head *list) { const struct iommu_ops *ops = dev->bus->iommu_ops; - if (ops && ops->put_dm_regions) - ops->put_dm_regions(dev, list); + if (ops && ops->put_resv_regions) + ops->put_resv_regions(dev, list); } /* Request that a device is direct mapped by the IOMMU */ diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 0ff5111f6959..bfecb8b74078 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -118,13 +118,13 @@ enum iommu_attr { }; /** - * struct iommu_dm_region - descriptor for a direct mapped memory region + * struct iommu_resv_region - descriptor for a reserved memory region * @list: Linked list pointers * @start: System physical start address of the region * @length: Length of the region in bytes * @prot: IOMMU Protection flags (READ/WRITE/...) */ -struct iommu_dm_region { +struct iommu_resv_region { struct list_head list; phys_addr_t start; size_t length; @@ -150,9 +150,9 @@ struct iommu_dm_region { * @device_group: find iommu group for a particular device * @domain_get_attr: Query domain attributes * @domain_set_attr: Change domain attributes - * @get_dm_regions: Request list of direct mapping requirements for a device - * @put_dm_regions: Free list of direct mapping requirements for a device - * @apply_dm_region: Temporary helper call-back for iova reserved ranges + * @get_resv_regions: Request list of reserved regions for a device + * @put_resv_regions: Free list of reserved regions for a device + * @apply_resv_region: Temporary helper call-back for iova reserved ranges * @domain_window_enable: Configure and enable a particular window for a domain * @domain_window_disable: Disable a particular window for a domain * @domain_set_windows: Set the number of windows for a domain @@ -184,11 +184,12 @@ struct iommu_ops { int (*domain_set_attr)(struct iommu_domain *domain, enum iommu_attr attr, void *data); - /* Request/Free a list of direct mapping requirements for a device */ - void (*get_dm_regions)(struct device *dev, struct list_head *list); - void (*put_dm_regions)(struct device *dev, struct list_head *list); - void (*apply_dm_region)(struct device *dev, struct iommu_domain *domain, - struct iommu_dm_region *region); + /* Request/Free a list of reserved regions for a device */ + void (*get_resv_regions)(struct device *dev, struct list_head *list); + void (*put_resv_regions)(struct device *dev, struct list_head *list); + void (*apply_resv_region)(struct device *dev, + struct iommu_domain *domain, + struct iommu_resv_region *region); /* Window handling functions */ int (*domain_window_enable)(struct iommu_domain *domain, u32 wnd_nr, @@ -233,8 +234,8 @@ extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t io extern void iommu_set_fault_handler(struct iommu_domain *domain, iommu_fault_handler_t handler, void *token); -extern void iommu_get_dm_regions(struct device *dev, struct list_head *list); -extern void iommu_put_dm_regions(struct device *dev, struct list_head *list); +extern void iommu_get_resv_regions(struct device *dev, struct list_head *list); +extern void iommu_put_resv_regions(struct device *dev, struct list_head *list); extern int iommu_request_dm_for_dev(struct device *dev); extern int iommu_attach_group(struct iommu_domain *domain, @@ -443,12 +444,12 @@ static inline void iommu_set_fault_handler(struct iommu_domain *domain, { } -static inline void iommu_get_dm_regions(struct device *dev, +static inline void iommu_get_resv_regions(struct device *dev, struct list_head *list) { } -static inline void iommu_put_dm_regions(struct device *dev, +static inline void iommu_put_resv_regions(struct device *dev, struct list_head *list) { } -- cgit v1.2.3 From 2b20cbba3390a55c511acba2f0f517dd27a528b2 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 19 Jan 2017 20:57:49 +0000 Subject: iommu: iommu_alloc_resv_region Introduce a new helper serving the purpose to allocate a reserved region. This will be used in iommu driver implementing reserved region callbacks. Signed-off-by: Eric Auger Reviewed-by: Tomasz Nowicki Tested-by: Tomasz Nowicki Tested-by: Bharat Bhushan Signed-off-by: Will Deacon --- drivers/iommu/iommu.c | 18 ++++++++++++++++++ include/linux/iommu.h | 2 ++ 2 files changed, 20 insertions(+) (limited to 'drivers/iommu/iommu.c') diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 1cee5c361c21..927878d0a612 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1575,6 +1575,24 @@ void iommu_put_resv_regions(struct device *dev, struct list_head *list) ops->put_resv_regions(dev, list); } +struct iommu_resv_region *iommu_alloc_resv_region(phys_addr_t start, + size_t length, + int prot, int type) +{ + struct iommu_resv_region *region; + + region = kzalloc(sizeof(*region), GFP_KERNEL); + if (!region) + return NULL; + + INIT_LIST_HEAD(®ion->list); + region->start = start; + region->length = length; + region->prot = prot; + region->type = type; + return region; +} + /* Request that a device is direct mapped by the IOMMU */ int iommu_request_dm_for_dev(struct device *dev) { diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 233a6bf093bf..f6bb55d3e606 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -244,6 +244,8 @@ extern void iommu_set_fault_handler(struct iommu_domain *domain, extern void iommu_get_resv_regions(struct device *dev, struct list_head *list); extern void iommu_put_resv_regions(struct device *dev, struct list_head *list); extern int iommu_request_dm_for_dev(struct device *dev); +extern struct iommu_resv_region * +iommu_alloc_resv_region(phys_addr_t start, size_t length, int prot, int type); extern int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group); -- cgit v1.2.3 From 544a25d904cab2ae68bd71b334603ec3a49b60dd Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 19 Jan 2017 20:57:50 +0000 Subject: iommu: Only map direct mapped regions As we introduced new reserved region types which do not require mapping, let's make sure we only map direct mapped regions. Signed-off-by: Eric Auger Reviewed-by: Tomasz Nowicki Tested-by: Tomasz Nowicki Tested-by: Bharat Bhushan Signed-off-by: Will Deacon --- drivers/iommu/iommu.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/iommu/iommu.c') diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 927878d0a612..41c190695749 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -343,6 +343,9 @@ static int iommu_group_create_direct_mappings(struct iommu_group *group, start = ALIGN(entry->start, pg_size); end = ALIGN(entry->start + entry->length, pg_size); + if (entry->type != IOMMU_RESV_DIRECT) + continue; + for (addr = start; addr < end; addr += pg_size) { phys_addr_t phys_addr; -- cgit v1.2.3 From 6c65fb318e8bbf21e939e651028b955324f1d873 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 19 Jan 2017 20:57:51 +0000 Subject: iommu: iommu_get_group_resv_regions Introduce iommu_get_group_resv_regions whose role consists in enumerating all devices from the group and collecting their reserved regions. The list is sorted and overlaps between regions of the same type are handled by merging the regions. Signed-off-by: Eric Auger Reviewed-by: Tomasz Nowicki Tested-by: Tomasz Nowicki Tested-by: Bharat Bhushan Signed-off-by: Will Deacon --- drivers/iommu/iommu.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/iommu.h | 8 +++++ 2 files changed, 106 insertions(+) (limited to 'drivers/iommu/iommu.c') diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 41c190695749..640056ba46c2 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -133,6 +133,104 @@ static ssize_t iommu_group_show_name(struct iommu_group *group, char *buf) return sprintf(buf, "%s\n", group->name); } +/** + * iommu_insert_resv_region - Insert a new region in the + * list of reserved regions. + * @new: new region to insert + * @regions: list of regions + * + * The new element is sorted by address with respect to the other + * regions of the same type. In case it overlaps with another + * region of the same type, regions are merged. In case it + * overlaps with another region of different type, regions are + * not merged. + */ +static int iommu_insert_resv_region(struct iommu_resv_region *new, + struct list_head *regions) +{ + struct iommu_resv_region *region; + phys_addr_t start = new->start; + phys_addr_t end = new->start + new->length - 1; + struct list_head *pos = regions->next; + + while (pos != regions) { + struct iommu_resv_region *entry = + list_entry(pos, struct iommu_resv_region, list); + phys_addr_t a = entry->start; + phys_addr_t b = entry->start + entry->length - 1; + int type = entry->type; + + if (end < a) { + goto insert; + } else if (start > b) { + pos = pos->next; + } else if ((start >= a) && (end <= b)) { + if (new->type == type) + goto done; + else + pos = pos->next; + } else { + if (new->type == type) { + phys_addr_t new_start = min(a, start); + phys_addr_t new_end = max(b, end); + + list_del(&entry->list); + entry->start = new_start; + entry->length = new_end - new_start + 1; + iommu_insert_resv_region(entry, regions); + } else { + pos = pos->next; + } + } + } +insert: + region = iommu_alloc_resv_region(new->start, new->length, + new->prot, new->type); + if (!region) + return -ENOMEM; + + list_add_tail(®ion->list, pos); +done: + return 0; +} + +static int +iommu_insert_device_resv_regions(struct list_head *dev_resv_regions, + struct list_head *group_resv_regions) +{ + struct iommu_resv_region *entry; + int ret; + + list_for_each_entry(entry, dev_resv_regions, list) { + ret = iommu_insert_resv_region(entry, group_resv_regions); + if (ret) + break; + } + return ret; +} + +int iommu_get_group_resv_regions(struct iommu_group *group, + struct list_head *head) +{ + struct iommu_device *device; + int ret = 0; + + mutex_lock(&group->mutex); + list_for_each_entry(device, &group->devices, list) { + struct list_head dev_resv_regions; + + INIT_LIST_HEAD(&dev_resv_regions); + iommu_get_resv_regions(device->dev, &dev_resv_regions); + ret = iommu_insert_device_resv_regions(&dev_resv_regions, head); + iommu_put_resv_regions(device->dev, &dev_resv_regions); + if (ret) + break; + } + mutex_unlock(&group->mutex); + return ret; +} +EXPORT_SYMBOL_GPL(iommu_get_group_resv_regions); + static IOMMU_GROUP_ATTR(name, S_IRUGO, iommu_group_show_name, NULL); static void iommu_group_release(struct kobject *kobj) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index f6bb55d3e606..bec3730dc009 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -246,6 +246,8 @@ extern void iommu_put_resv_regions(struct device *dev, struct list_head *list); extern int iommu_request_dm_for_dev(struct device *dev); extern struct iommu_resv_region * iommu_alloc_resv_region(phys_addr_t start, size_t length, int prot, int type); +extern int iommu_get_group_resv_regions(struct iommu_group *group, + struct list_head *head); extern int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group); @@ -463,6 +465,12 @@ static inline void iommu_put_resv_regions(struct device *dev, { } +static inline int iommu_get_group_resv_regions(struct iommu_group *group, + struct list_head *head) +{ + return -ENODEV; +} + static inline int iommu_request_dm_for_dev(struct device *dev) { return -ENODEV; -- cgit v1.2.3 From bc7d12b91bd35477fd650c4d72b61239de9d9066 Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Thu, 19 Jan 2017 20:57:52 +0000 Subject: iommu: Implement reserved_regions iommu-group sysfs file A new iommu-group sysfs attribute file is introduced. It contains the list of reserved regions for the iommu-group. Each reserved region is described on a separate line: - first field is the start IOVA address, - second is the end IOVA address, - third is the type. Signed-off-by: Eric Auger Tested-by: Tomasz Nowicki Tested-by: Bharat Bhushan Signed-off-by: Will Deacon --- .../ABI/testing/sysfs-kernel-iommu_groups | 12 ++++++++ drivers/iommu/iommu.c | 36 ++++++++++++++++++++++ 2 files changed, 48 insertions(+) (limited to 'drivers/iommu/iommu.c') diff --git a/Documentation/ABI/testing/sysfs-kernel-iommu_groups b/Documentation/ABI/testing/sysfs-kernel-iommu_groups index 9b31556cfdda..35c64e00b35c 100644 --- a/Documentation/ABI/testing/sysfs-kernel-iommu_groups +++ b/Documentation/ABI/testing/sysfs-kernel-iommu_groups @@ -12,3 +12,15 @@ Description: /sys/kernel/iommu_groups/ contains a number of sub- file if the IOMMU driver has chosen to register a more common name for the group. Users: + +What: /sys/kernel/iommu_groups/reserved_regions +Date: January 2017 +KernelVersion: v4.11 +Contact: Eric Auger +Description: /sys/kernel/iommu_groups/reserved_regions list IOVA + regions that are reserved. Not necessarily all + reserved regions are listed. This is typically used to + output direct-mapped, MSI, non mappable regions. Each + region is described on a single line: the 1st field is + the base IOVA, the second is the end IOVA and the third + field describes the type of the region. diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 640056ba46c2..f4a176e56e39 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -68,6 +68,12 @@ struct iommu_group_attribute { const char *buf, size_t count); }; +static const char * const iommu_group_resv_type_string[] = { + [IOMMU_RESV_DIRECT] = "direct", + [IOMMU_RESV_RESERVED] = "reserved", + [IOMMU_RESV_MSI] = "msi", +}; + #define IOMMU_GROUP_ATTR(_name, _mode, _show, _store) \ struct iommu_group_attribute iommu_group_attr_##_name = \ __ATTR(_name, _mode, _show, _store) @@ -231,8 +237,33 @@ int iommu_get_group_resv_regions(struct iommu_group *group, } EXPORT_SYMBOL_GPL(iommu_get_group_resv_regions); +static ssize_t iommu_group_show_resv_regions(struct iommu_group *group, + char *buf) +{ + struct iommu_resv_region *region, *next; + struct list_head group_resv_regions; + char *str = buf; + + INIT_LIST_HEAD(&group_resv_regions); + iommu_get_group_resv_regions(group, &group_resv_regions); + + list_for_each_entry_safe(region, next, &group_resv_regions, list) { + str += sprintf(str, "0x%016llx 0x%016llx %s\n", + (long long int)region->start, + (long long int)(region->start + + region->length - 1), + iommu_group_resv_type_string[region->type]); + kfree(region); + } + + return (str - buf); +} + static IOMMU_GROUP_ATTR(name, S_IRUGO, iommu_group_show_name, NULL); +static IOMMU_GROUP_ATTR(reserved_regions, 0444, + iommu_group_show_resv_regions, NULL); + static void iommu_group_release(struct kobject *kobj) { struct iommu_group *group = to_iommu_group(kobj); @@ -310,6 +341,11 @@ struct iommu_group *iommu_group_alloc(void) */ kobject_put(&group->kobj); + ret = iommu_group_create_file(group, + &iommu_group_attr_reserved_regions); + if (ret) + return ERR_PTR(ret); + pr_debug("Allocated group %d\n", group->id); return group; -- cgit v1.2.3 From 909111ba0ba6aa228d9b6e9cf01dd68a46586cb4 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Fri, 3 Feb 2017 17:35:02 +0800 Subject: iommu: Avoid unnecessary assignment of dev->iommu_fwspec Move the assignment statement into if branch above, where it only needs to be. Signed-off-by: Zhen Lei Reviewed-by: Robin Murphy Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/iommu/iommu.c') diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index f4a176e56e39..428455a21ee7 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1869,13 +1869,14 @@ int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids) fwspec = krealloc(dev->iommu_fwspec, size, GFP_KERNEL); if (!fwspec) return -ENOMEM; + + dev->iommu_fwspec = fwspec; } for (i = 0; i < num_ids; i++) fwspec->ids[fwspec->num_ids + i] = ids[i]; fwspec->num_ids += num_ids; - dev->iommu_fwspec = fwspec; return 0; } EXPORT_SYMBOL_GPL(iommu_fwspec_add_ids); -- cgit v1.2.3 From a514a6e241f051dd8a4a00a456382dec0b1af21b Mon Sep 17 00:00:00 2001 From: Eric Auger Date: Mon, 6 Feb 2017 10:11:38 +0100 Subject: iommu: Fix static checker warning in iommu_insert_device_resv_regions In case the device reserved region list is void, the returned value of iommu_insert_device_resv_regions is uninitialized. Let's return 0 in that case. This fixes commit 6c65fb318e8b ("iommu: iommu_get_group_resv_regions"). Reported-by: Dan Carpenter Signed-off-by: Eric Auger Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/iommu/iommu.c') diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 428455a21ee7..c37d701ddaa2 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -205,7 +205,7 @@ iommu_insert_device_resv_regions(struct list_head *dev_resv_regions, struct list_head *group_resv_regions) { struct iommu_resv_region *entry; - int ret; + int ret = 0; list_for_each_entry(entry, dev_resv_regions, list) { ret = iommu_insert_resv_region(entry, group_resv_regions); -- cgit v1.2.3 From 534766dfef999f7e7349bbd91cd19c1673792af3 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 31 Jan 2017 16:58:42 +0100 Subject: iommu: Rename iommu_get_instance() Rename the function to iommu_ops_from_fwnode(), because that is what the function actually does. The new name is much more descriptive about what the function does. Signed-off-by: Joerg Roedel --- drivers/acpi/arm64/iort.c | 2 +- drivers/iommu/iommu.c | 2 +- include/linux/iommu.h | 4 ++-- include/linux/of_iommu.h | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/iommu/iommu.c') diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c index e0d2e6e6e40c..3752521c62ab 100644 --- a/drivers/acpi/arm64/iort.c +++ b/drivers/acpi/arm64/iort.c @@ -536,7 +536,7 @@ static const struct iommu_ops *iort_iommu_xlate(struct device *dev, if (!iort_fwnode) return NULL; - ops = iommu_get_instance(iort_fwnode); + ops = iommu_ops_from_fwnode(iort_fwnode); if (!ops) return NULL; diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index aed906a3e3db..2bb61e806a52 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1664,7 +1664,7 @@ void iommu_register_instance(struct fwnode_handle *fwnode, spin_unlock(&iommu_instance_lock); } -const struct iommu_ops *iommu_get_instance(struct fwnode_handle *fwnode) +const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode) { struct iommu_instance *instance; const struct iommu_ops *ops = NULL; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 0ff5111f6959..085e1f0e6c07 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -354,7 +354,7 @@ void iommu_fwspec_free(struct device *dev); int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids); void iommu_register_instance(struct fwnode_handle *fwnode, const struct iommu_ops *ops); -const struct iommu_ops *iommu_get_instance(struct fwnode_handle *fwnode); +const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode); #else /* CONFIG_IOMMU_API */ @@ -590,7 +590,7 @@ static inline void iommu_register_instance(struct fwnode_handle *fwnode, } static inline -const struct iommu_ops *iommu_get_instance(struct fwnode_handle *fwnode) +const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode) { return NULL; } diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h index 6a7fc5051099..66fcbc949899 100644 --- a/include/linux/of_iommu.h +++ b/include/linux/of_iommu.h @@ -39,7 +39,7 @@ static inline void of_iommu_set_ops(struct device_node *np, static inline const struct iommu_ops *of_iommu_get_ops(struct device_node *np) { - return iommu_get_instance(&np->fwnode); + return iommu_ops_from_fwnode(&np->fwnode); } extern struct of_device_id __iommu_of_table; -- cgit v1.2.3 From c09e22d5370739e16463c113525df51b5980b1d5 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 1 Feb 2017 12:19:46 +0100 Subject: iommu: Rename struct iommu_device The struct is used to link devices to iommu-groups, so 'struct group_device' is a better name. Further this makes the name iommu_device available for a struct representing hardware iommus. Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/iommu/iommu.c') diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 2bb61e806a52..cc569b1b66a2 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -55,7 +55,7 @@ struct iommu_group { struct iommu_domain *domain; }; -struct iommu_device { +struct group_device { struct list_head list; struct device *dev; char *name; @@ -374,7 +374,7 @@ out: int iommu_group_add_device(struct iommu_group *group, struct device *dev) { int ret, i = 0; - struct iommu_device *device; + struct group_device *device; device = kzalloc(sizeof(*device), GFP_KERNEL); if (!device) @@ -460,7 +460,7 @@ EXPORT_SYMBOL_GPL(iommu_group_add_device); void iommu_group_remove_device(struct device *dev) { struct iommu_group *group = dev->iommu_group; - struct iommu_device *tmp_device, *device = NULL; + struct group_device *tmp_device, *device = NULL; pr_info("Removing device %s from group %d\n", dev_name(dev), group->id); @@ -495,7 +495,7 @@ EXPORT_SYMBOL_GPL(iommu_group_remove_device); static int iommu_group_device_count(struct iommu_group *group) { - struct iommu_device *entry; + struct group_device *entry; int ret = 0; list_for_each_entry(entry, &group->devices, list) @@ -518,7 +518,7 @@ static int iommu_group_device_count(struct iommu_group *group) static int __iommu_group_for_each_dev(struct iommu_group *group, void *data, int (*fn)(struct device *, void *)) { - struct iommu_device *device; + struct group_device *device; int ret = 0; list_for_each_entry(device, &group->devices, list) { -- cgit v1.2.3 From b0119e870837dcd15a207b4701542ebac5d19b45 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 1 Feb 2017 13:23:08 +0100 Subject: iommu: Introduce new 'struct iommu_device' This struct represents one hardware iommu in the iommu core code. For now it only has the iommu-ops associated with it, but that will be extended soon. The register/unregister interface is also added, as well as making use of it in the Intel and AMD IOMMU drivers. Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu.c | 4 ++-- drivers/iommu/amd_iommu_init.c | 5 +++++ drivers/iommu/amd_iommu_types.h | 3 +++ drivers/iommu/dmar.c | 9 +++++++++ drivers/iommu/intel-iommu.c | 4 ++-- drivers/iommu/iommu.c | 19 +++++++++++++++++++ include/linux/intel-iommu.h | 2 ++ include/linux/iommu.h | 35 +++++++++++++++++++++++++++++++++++ 8 files changed, 77 insertions(+), 4 deletions(-) (limited to 'drivers/iommu/iommu.c') diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 019e02707cd5..689d88fa29a6 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -112,7 +112,7 @@ static struct timer_list queue_timer; * Domain for untranslated devices - only allocated * if iommu=pt passed on kernel cmd line. */ -static const struct iommu_ops amd_iommu_ops; +const struct iommu_ops amd_iommu_ops; static ATOMIC_NOTIFIER_HEAD(ppr_notifier); int amd_iommu_max_glx_val = -1; @@ -3217,7 +3217,7 @@ static void amd_iommu_apply_dm_region(struct device *dev, WARN_ON_ONCE(reserve_iova(&dma_dom->iovad, start, end) == NULL); } -static const struct iommu_ops amd_iommu_ops = { +const struct iommu_ops amd_iommu_ops = { .capable = amd_iommu_capable, .domain_alloc = amd_iommu_domain_alloc, .domain_free = amd_iommu_domain_free, diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 6799cf9713f7..b7ccfb21b271 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -94,6 +94,8 @@ * out of it. */ +extern const struct iommu_ops amd_iommu_ops; + /* * structure describing one IOMMU in the ACPI table. Typically followed by one * or more ivhd_entrys. @@ -1639,6 +1641,9 @@ static int iommu_init_pci(struct amd_iommu *iommu) amd_iommu_groups, "ivhd%d", iommu->index); + iommu_device_set_ops(&iommu->iommu, &amd_iommu_ops); + iommu_device_register(&iommu->iommu); + return pci_enable_device(iommu->dev); } diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index 0d91785ebdc3..0683505a498a 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h @@ -538,6 +538,9 @@ struct amd_iommu { /* IOMMU sysfs device */ struct device *iommu_dev; + /* Handle for IOMMU core code */ + struct iommu_device iommu; + /* * We can't rely on the BIOS to restore all values on reinit, so we * need to stash them diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index a88576d50740..83fee0e8cf43 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -74,6 +74,8 @@ static unsigned long dmar_seq_ids[BITS_TO_LONGS(DMAR_UNITS_SUPPORTED)]; static int alloc_iommu(struct dmar_drhd_unit *drhd); static void free_iommu(struct intel_iommu *iommu); +extern const struct iommu_ops intel_iommu_ops; + static void dmar_register_drhd_unit(struct dmar_drhd_unit *drhd) { /* @@ -1084,6 +1086,12 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd) err = PTR_ERR(iommu->iommu_dev); goto err_unmap; } + + iommu_device_set_ops(&iommu->iommu, &intel_iommu_ops); + + err = iommu_device_register(&iommu->iommu); + if (err) + goto err_unmap; } drhd->iommu = iommu; @@ -1102,6 +1110,7 @@ error: static void free_iommu(struct intel_iommu *iommu) { iommu_device_destroy(iommu->iommu_dev); + iommu_device_unregister(&iommu->iommu); if (iommu->irq) { if (iommu->pr_irq) { diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index c66c273dfd8a..e6e8f5bf3a8f 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -547,7 +547,7 @@ EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped); static DEFINE_SPINLOCK(device_domain_lock); static LIST_HEAD(device_domain_list); -static const struct iommu_ops intel_iommu_ops; +const struct iommu_ops intel_iommu_ops; static bool translation_pre_enabled(struct intel_iommu *iommu) { @@ -5292,7 +5292,7 @@ struct intel_iommu *intel_svm_device_to_iommu(struct device *dev) } #endif /* CONFIG_INTEL_IOMMU_SVM */ -static const struct iommu_ops intel_iommu_ops = { +const struct iommu_ops intel_iommu_ops = { .capable = intel_iommu_capable, .domain_alloc = intel_iommu_domain_alloc, .domain_free = intel_iommu_domain_free, diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index cc569b1b66a2..1dfd70ea27e4 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -77,6 +77,25 @@ struct iommu_group_attribute iommu_group_attr_##_name = \ #define to_iommu_group(_kobj) \ container_of(_kobj, struct iommu_group, kobj) +static LIST_HEAD(iommu_device_list); +static DEFINE_SPINLOCK(iommu_device_lock); + +int iommu_device_register(struct iommu_device *iommu) +{ + spin_lock(&iommu_device_lock); + list_add_tail(&iommu->list, &iommu_device_list); + spin_unlock(&iommu_device_lock); + + return 0; +} + +void iommu_device_unregister(struct iommu_device *iommu) +{ + spin_lock(&iommu_device_lock); + list_del(&iommu->list); + spin_unlock(&iommu_device_lock); +} + static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus, unsigned type); static int __iommu_attach_device(struct iommu_domain *domain, diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index d49e26c6cdc7..99a65a397861 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -440,6 +441,7 @@ struct intel_iommu { 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 */ }; diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 085e1f0e6c07..900ddd212364 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -204,6 +204,26 @@ struct iommu_ops { unsigned long pgsize_bitmap; }; +/** + * struct iommu_device - IOMMU core representation of one IOMMU hardware + * instance + * @list: Used by the iommu-core to keep a list of registered iommus + * @ops: iommu-ops for talking to this iommu + */ +struct iommu_device { + struct list_head list; + const struct iommu_ops *ops; +}; + +int iommu_device_register(struct iommu_device *iommu); +void iommu_device_unregister(struct iommu_device *iommu); + +static inline void iommu_device_set_ops(struct iommu_device *iommu, + const struct iommu_ops *ops) +{ + iommu->ops = ops; +} + #define IOMMU_GROUP_NOTIFY_ADD_DEVICE 1 /* Device added */ #define IOMMU_GROUP_NOTIFY_DEL_DEVICE 2 /* Pre Device removed */ #define IOMMU_GROUP_NOTIFY_BIND_DRIVER 3 /* Pre Driver bind */ @@ -361,6 +381,7 @@ const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode); struct iommu_ops {}; struct iommu_group {}; struct iommu_fwspec {}; +struct iommu_device {}; static inline bool iommu_present(struct bus_type *bus) { @@ -558,6 +579,20 @@ static inline void iommu_device_destroy(struct device *dev) { } +static inline int iommu_device_register(struct iommu_device *iommu) +{ + return -ENODEV; +} + +static inline void iommu_device_set_ops(struct iommu_device *iommu, + const struct iommu_ops *ops) +{ +} + +static inline void iommu_device_unregister(struct iommu_device *iommu) +{ +} + static inline int iommu_device_link(struct device *dev, struct device *link) { return -EINVAL; -- cgit v1.2.3 From d0f6f5832603931b0a8da044fb9abe8289e201ee Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 2 Feb 2017 12:19:12 +0100 Subject: iommu: Remove iommu_register_instance interface And also move its remaining functionality to iommu_device_register() and 'struct iommu_device'. Cc: Rob Herring Cc: Frank Rowand Cc: Matthias Brugger Cc: Marek Szyprowski Cc: devicetree@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Joerg Roedel --- drivers/iommu/arm-smmu-v3.c | 2 -- drivers/iommu/arm-smmu.c | 1 - drivers/iommu/exynos-iommu.c | 2 -- drivers/iommu/iommu.c | 37 ++++++------------------------------- drivers/iommu/msm_iommu.c | 2 -- drivers/iommu/mtk_iommu.c | 1 - include/linux/iommu.h | 7 ------- include/linux/of_iommu.h | 6 ------ 8 files changed, 6 insertions(+), 52 deletions(-) (limited to 'drivers/iommu/iommu.c') diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index 32133e289ff6..53751379dee3 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -2702,8 +2702,6 @@ static int arm_smmu_device_probe(struct platform_device *pdev) ret = iommu_device_register(&smmu->iommu); - iommu_register_instance(dev->fwnode, &arm_smmu_ops); - #ifdef CONFIG_PCI if (pci_bus_type.iommu_ops != &arm_smmu_ops) { pci_request_acs(); diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index f4ce1e77344e..8fb4af2dfbfa 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -2121,7 +2121,6 @@ static int arm_smmu_device_probe(struct platform_device *pdev) return err; } - iommu_register_instance(dev->fwnode, &arm_smmu_ops); platform_set_drvdata(pdev, smmu); arm_smmu_device_reset(smmu); diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 64325d8ddd40..778ecccd7a29 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -642,8 +642,6 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev) pm_runtime_enable(dev); - of_iommu_set_ops(dev->of_node, &exynos_iommu_ops); - return 0; } diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 1dfd70ea27e4..162d865e2e29 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1658,43 +1658,18 @@ out: return ret; } -struct iommu_instance { - struct list_head list; - struct fwnode_handle *fwnode; - const struct iommu_ops *ops; -}; -static LIST_HEAD(iommu_instance_list); -static DEFINE_SPINLOCK(iommu_instance_lock); - -void iommu_register_instance(struct fwnode_handle *fwnode, - const struct iommu_ops *ops) -{ - struct iommu_instance *iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); - - if (WARN_ON(!iommu)) - return; - - of_node_get(to_of_node(fwnode)); - INIT_LIST_HEAD(&iommu->list); - iommu->fwnode = fwnode; - iommu->ops = ops; - spin_lock(&iommu_instance_lock); - list_add_tail(&iommu->list, &iommu_instance_list); - spin_unlock(&iommu_instance_lock); -} - const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode) { - struct iommu_instance *instance; const struct iommu_ops *ops = NULL; + struct iommu_device *iommu; - spin_lock(&iommu_instance_lock); - list_for_each_entry(instance, &iommu_instance_list, list) - if (instance->fwnode == fwnode) { - ops = instance->ops; + spin_lock(&iommu_device_lock); + list_for_each_entry(iommu, &iommu_device_list, list) + if (iommu->fwnode == fwnode) { + ops = iommu->ops; break; } - spin_unlock(&iommu_instance_lock); + spin_unlock(&iommu_device_lock); return ops; } diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index 30795cbab5ef..d0448353d501 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -810,8 +810,6 @@ static int msm_iommu_probe(struct platform_device *pdev) goto fail; } - of_iommu_set_ops(pdev->dev.of_node, &msm_iommu_ops); - pr_info("device mapped at %p, irq %d with %d ctx banks\n", iommu->base, iommu->irq, iommu->ncb); diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index d484fa608db8..5d14cd15198d 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -681,7 +681,6 @@ static int mtk_iommu_init_fn(struct device_node *np) return ret; } - of_iommu_set_ops(np, &mtk_iommu_ops); return 0; } diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 626c935edee1..9e82fc83765e 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -382,8 +382,6 @@ int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode, const struct iommu_ops *ops); void iommu_fwspec_free(struct device *dev); int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids); -void iommu_register_instance(struct fwnode_handle *fwnode, - const struct iommu_ops *ops); const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode); #else /* CONFIG_IOMMU_API */ @@ -634,11 +632,6 @@ static inline int iommu_fwspec_add_ids(struct device *dev, u32 *ids, return -ENODEV; } -static inline void iommu_register_instance(struct fwnode_handle *fwnode, - const struct iommu_ops *ops) -{ -} - static inline const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode) { diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h index 66fcbc949899..fc4add39361a 100644 --- a/include/linux/of_iommu.h +++ b/include/linux/of_iommu.h @@ -31,12 +31,6 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev, #endif /* CONFIG_OF_IOMMU */ -static inline void of_iommu_set_ops(struct device_node *np, - const struct iommu_ops *ops) -{ - iommu_register_instance(&np->fwnode, ops); -} - static inline const struct iommu_ops *of_iommu_get_ops(struct device_node *np) { return iommu_ops_from_fwnode(&np->fwnode); -- cgit v1.2.3