From 1aed074869a9cbe0a846ea7b254d8fd9a4a4d31f Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 3 Sep 2014 18:34:04 +0200 Subject: iommu: Convert iommu-caps from define to enum Allow compile-time type-checking. Signed-off-by: Joerg Roedel --- include/linux/iommu.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 20f9a527922a..98fc126655ae 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -57,8 +57,11 @@ struct iommu_domain { struct iommu_domain_geometry geometry; }; -#define IOMMU_CAP_CACHE_COHERENCY 0x1 -#define IOMMU_CAP_INTR_REMAP 0x2 /* isolates device intrs */ +enum iommu_cap { + IOMMU_CAP_CACHE_COHERENCY, /* IOMMU can enforce cache coherent DMA + transactions */ + IOMMU_CAP_INTR_REMAP, /* IOMMU supports interrupt isolation */ +}; /* * Following constraints are specifc to FSL_PAMUV1: @@ -155,7 +158,7 @@ extern size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size); extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova); extern int iommu_domain_has_cap(struct iommu_domain *domain, - unsigned long cap); + enum iommu_cap cap); extern void iommu_set_fault_handler(struct iommu_domain *domain, iommu_fault_handler_t handler, void *token); @@ -305,7 +308,7 @@ static inline phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_ad } static inline int iommu_domain_has_cap(struct iommu_domain *domain, - unsigned long cap) + enum iommu_cap cap) { return 0; } -- cgit v1.2.3-58-ga151 From 3c0e0ca0a4e757159d868c4870556515d66b6c97 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 3 Sep 2014 18:47:25 +0200 Subject: iommu: Introduce iommu_capable API function This function will replace the current iommu_domain_has_cap function and clean up the interface while at it. Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 18 +++++++++++++++--- include/linux/iommu.h | 7 +++++++ 2 files changed, 22 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index bc45478e26db..aeb243f46332 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -817,6 +817,15 @@ bool iommu_present(struct bus_type *bus) } EXPORT_SYMBOL_GPL(iommu_present); +bool iommu_capable(struct bus_type *bus, enum iommu_cap cap) +{ + if (!bus->iommu_ops || !bus->iommu_ops->capable) + return false; + + return bus->iommu_ops->capable(cap); +} +EXPORT_SYMBOL_GPL(iommu_capable); + /** * iommu_set_fault_handler() - set a fault handler for an iommu domain * @domain: iommu domain @@ -950,10 +959,13 @@ EXPORT_SYMBOL_GPL(iommu_iova_to_phys); int iommu_domain_has_cap(struct iommu_domain *domain, enum iommu_cap cap) { - if (unlikely(domain->ops->domain_has_cap == NULL)) - return 0; + if (domain->ops->domain_has_cap != NULL) + return domain->ops->domain_has_cap(domain, cap); + + if (domain->ops->capable != NULL) + return domain->ops->capable(cap); - return domain->ops->domain_has_cap(domain, cap); + return 0; } EXPORT_SYMBOL_GPL(iommu_domain_has_cap); diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 98fc126655ae..d5534d554693 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -105,6 +105,7 @@ enum iommu_attr { * @pgsize_bitmap: bitmap of supported page sizes */ struct iommu_ops { + bool (*capable)(enum iommu_cap); int (*domain_init)(struct iommu_domain *domain); void (*domain_destroy)(struct iommu_domain *domain); int (*attach_dev)(struct iommu_domain *domain, struct device *dev); @@ -145,6 +146,7 @@ struct iommu_ops { extern int bus_set_iommu(struct bus_type *bus, const struct iommu_ops *ops); extern bool iommu_present(struct bus_type *bus); +extern bool iommu_capable(struct bus_type *bus, enum iommu_cap cap); extern struct iommu_domain *iommu_domain_alloc(struct bus_type *bus); extern struct iommu_group *iommu_group_get_by_id(int id); extern void iommu_domain_free(struct iommu_domain *domain); @@ -253,6 +255,11 @@ static inline bool iommu_present(struct bus_type *bus) return false; } +static inline bool iommu_capable(struct bus_type *bus, enum iommu_cap cap) +{ + return false; +} + static inline struct iommu_domain *iommu_domain_alloc(struct bus_type *bus) { return NULL; -- cgit v1.2.3-58-ga151 From 24278a24d88ae730229417e5d3bd452d7545fbcc Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Fri, 5 Sep 2014 10:57:11 +0200 Subject: iommu: Remove iommu_domain_has_cap() API function Signed-off-by: Joerg Roedel --- drivers/iommu/iommu.c | 13 ------------- include/linux/iommu.h | 11 ----------- 2 files changed, 24 deletions(-) (limited to 'include') diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index aeb243f46332..d2d242fcaa3d 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -956,19 +956,6 @@ phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova) } EXPORT_SYMBOL_GPL(iommu_iova_to_phys); -int iommu_domain_has_cap(struct iommu_domain *domain, - enum iommu_cap cap) -{ - if (domain->ops->domain_has_cap != NULL) - return domain->ops->domain_has_cap(domain, cap); - - if (domain->ops->capable != NULL) - return domain->ops->capable(cap); - - return 0; -} -EXPORT_SYMBOL_GPL(iommu_domain_has_cap); - static size_t iommu_pgsize(struct iommu_domain *domain, unsigned long addr_merge, size_t size) { diff --git a/include/linux/iommu.h b/include/linux/iommu.h index d5534d554693..379a6179fd96 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -97,7 +97,6 @@ enum iommu_attr { * @map: map a physically contiguous memory region to an iommu domain * @unmap: unmap a physically contiguous memory region from an iommu domain * @iova_to_phys: translate iova to physical address - * @domain_has_cap: domain capabilities query * @add_device: add device to iommu grouping * @remove_device: remove device from iommu grouping * @domain_get_attr: Query domain attributes @@ -115,8 +114,6 @@ struct iommu_ops { size_t (*unmap)(struct iommu_domain *domain, unsigned long iova, size_t size); phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t iova); - int (*domain_has_cap)(struct iommu_domain *domain, - unsigned long cap); int (*add_device)(struct device *dev); void (*remove_device)(struct device *dev); int (*device_group)(struct device *dev, unsigned int *groupid); @@ -159,8 +156,6 @@ extern int iommu_map(struct iommu_domain *domain, unsigned long iova, extern size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova, size_t size); extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova); -extern int iommu_domain_has_cap(struct iommu_domain *domain, - enum iommu_cap cap); extern void iommu_set_fault_handler(struct iommu_domain *domain, iommu_fault_handler_t handler, void *token); @@ -314,12 +309,6 @@ static inline phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_ad return 0; } -static inline int iommu_domain_has_cap(struct iommu_domain *domain, - enum iommu_cap cap) -{ - return 0; -} - static inline void iommu_set_fault_handler(struct iommu_domain *domain, iommu_fault_handler_t handler, void *token) { -- cgit v1.2.3-58-ga151 From 599bad38cf7163123af7c9efea0fcf228bc74fe1 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Tue, 30 Sep 2014 13:02:02 +0200 Subject: driver core: Add BUS_NOTIFY_REMOVED_DEVICE event This event closes an important gap in the bus notifiers. There is already the BUS_NOTIFY_DEL_DEVICE event, but that is sent when the device is still bound to its device driver. This is too early for the IOMMU code to destroy any mappings for the device, as they might still be in use by the driver. The new BUS_NOTIFY_REMOVED_DEVICE event introduced with this patch closes this gap as it is sent when the device is already unbound from its device driver and almost completly removed from the driver core. With this event the IOMMU code can safely destroy any mappings and other data structures when a device is removed. Signed-off-by: Joerg Roedel Acked-by: Greg Kroah-Hartman Tested-by: Jerry Hoemann --- drivers/base/core.c | 3 +++ include/linux/device.h | 11 ++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'include') diff --git a/drivers/base/core.c b/drivers/base/core.c index 20da3ad1696b..7b270a2e6ed5 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1211,6 +1211,9 @@ void device_del(struct device *dev) */ if (platform_notify_remove) platform_notify_remove(dev); + if (dev->bus) + blocking_notifier_call_chain(&dev->bus->p->bus_notifier, + BUS_NOTIFY_REMOVED_DEVICE, dev); kobject_uevent(&dev->kobj, KOBJ_REMOVE); cleanup_device_parent(dev); kobject_del(&dev->kobj); diff --git a/include/linux/device.h b/include/linux/device.h index 43d183aeb25b..d0d5c5db509d 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -181,13 +181,14 @@ extern int bus_unregister_notifier(struct bus_type *bus, * with the device lock held in the core, so be careful. */ #define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */ -#define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */ -#define BUS_NOTIFY_BIND_DRIVER 0x00000003 /* driver about to be +#define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device to be removed */ +#define BUS_NOTIFY_REMOVED_DEVICE 0x00000003 /* device removed */ +#define BUS_NOTIFY_BIND_DRIVER 0x00000004 /* driver about to be bound */ -#define BUS_NOTIFY_BOUND_DRIVER 0x00000004 /* driver bound to device */ -#define BUS_NOTIFY_UNBIND_DRIVER 0x00000005 /* driver about to be +#define BUS_NOTIFY_BOUND_DRIVER 0x00000005 /* driver bound to device */ +#define BUS_NOTIFY_UNBIND_DRIVER 0x00000006 /* driver about to be unbound */ -#define BUS_NOTIFY_UNBOUND_DRIVER 0x00000006 /* driver is unbound +#define BUS_NOTIFY_UNBOUND_DRIVER 0x00000007 /* driver is unbound from the device */ extern struct kset *bus_get_kset(struct bus_type *bus); -- cgit v1.2.3-58-ga151 From 57384592c43375d2c9a14d82aebbdc95fdda9e9d Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 2 Oct 2014 11:50:25 +0200 Subject: iommu/vt-d: Store bus information in RMRR PCI device path This will be used later to match broken RMRR entries. Signed-off-by: Joerg Roedel --- drivers/iommu/dmar.c | 1 + include/linux/dmar.h | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 8ed55b0a1ce4..68da1ab0f2cd 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -155,6 +155,7 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned long event) if (event == BUS_NOTIFY_ADD_DEVICE) { for (tmp = dev; tmp; tmp = tmp->bus->self) { level--; + info->path[level].bus = tmp->bus->number; info->path[level].device = PCI_SLOT(tmp->devfn); info->path[level].function = PCI_FUNC(tmp->devfn); if (pci_is_root_bus(tmp->bus)) diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 1deece46a0ca..593fff99e6bf 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -56,13 +56,19 @@ struct dmar_drhd_unit { struct intel_iommu *iommu; }; +struct dmar_pci_path { + u8 bus; + u8 device; + u8 function; +}; + struct dmar_pci_notify_info { struct pci_dev *dev; unsigned long event; int bus; u16 seg; u16 level; - struct acpi_dmar_pci_path path[]; + struct dmar_pci_path path[]; } __attribute__((packed)); extern struct rw_semaphore dmar_global_lock; -- cgit v1.2.3-58-ga151