diff options
Diffstat (limited to 'include/linux/iommu.h')
| -rw-r--r-- | include/linux/iommu.h | 76 | 
1 files changed, 66 insertions, 10 deletions
diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 9940319d6f9..432acc4c054 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -25,15 +25,29 @@  #define IOMMU_WRITE	(2)  #define IOMMU_CACHE	(4) /* DMA cache coherency */ +struct iommu_ops; +struct bus_type;  struct device; +struct iommu_domain; + +/* iommu fault flags */ +#define IOMMU_FAULT_READ	0x0 +#define IOMMU_FAULT_WRITE	0x1 + +typedef int (*iommu_fault_handler_t)(struct iommu_domain *, +				struct device *, unsigned long, int);  struct iommu_domain { +	struct iommu_ops *ops;  	void *priv; +	iommu_fault_handler_t handler;  };  #define IOMMU_CAP_CACHE_COHERENCY	0x1  #define IOMMU_CAP_INTR_REMAP		0x2	/* isolates device intrs */ +#ifdef CONFIG_IOMMU_API +  struct iommu_ops {  	int (*domain_init)(struct iommu_domain *domain);  	void (*domain_destroy)(struct iommu_domain *domain); @@ -49,11 +63,9 @@ struct iommu_ops {  			      unsigned long cap);  }; -#ifdef CONFIG_IOMMU_API - -extern void register_iommu(struct iommu_ops *ops); -extern bool iommu_found(void); -extern struct iommu_domain *iommu_domain_alloc(void); +extern int bus_set_iommu(struct bus_type *bus, struct iommu_ops *ops); +extern bool iommu_present(struct bus_type *bus); +extern struct iommu_domain *iommu_domain_alloc(struct bus_type *bus);  extern void iommu_domain_free(struct iommu_domain *domain);  extern int iommu_attach_device(struct iommu_domain *domain,  			       struct device *dev); @@ -67,19 +79,58 @@ extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain,  				      unsigned long iova);  extern int iommu_domain_has_cap(struct iommu_domain *domain,  				unsigned long cap); +extern void iommu_set_fault_handler(struct iommu_domain *domain, +					iommu_fault_handler_t handler); -#else /* CONFIG_IOMMU_API */ - -static inline void register_iommu(struct iommu_ops *ops) +/** + * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework + * @domain: the iommu domain where the fault has happened + * @dev: the device where the fault has happened + * @iova: the faulting address + * @flags: mmu fault flags (e.g. IOMMU_FAULT_READ/IOMMU_FAULT_WRITE/...) + * + * This function should be called by the low-level IOMMU implementations + * whenever IOMMU faults happen, to allow high-level users, that are + * interested in such events, to know about them. + * + * This event may be useful for several possible use cases: + * - mere logging of the event + * - dynamic TLB/PTE loading + * - if restarting of the faulting device is required + * + * Returns 0 on success and an appropriate error code otherwise (if dynamic + * PTE/TLB loading will one day be supported, implementations will be able + * to tell whether it succeeded or not according to this return value). + * + * Specifically, -ENOSYS is returned if a fault handler isn't installed + * (though fault handlers can also return -ENOSYS, in case they want to + * elicit the default behavior of the IOMMU drivers). + */ +static inline int report_iommu_fault(struct iommu_domain *domain, +		struct device *dev, unsigned long iova, int flags)  { +	int ret = -ENOSYS; + +	/* +	 * if upper layers showed interest and installed a fault handler, +	 * invoke it. +	 */ +	if (domain->handler) +		ret = domain->handler(domain, dev, iova, flags); + +	return ret;  } -static inline bool iommu_found(void) +#else /* CONFIG_IOMMU_API */ + +struct iommu_ops {}; + +static inline bool iommu_present(struct bus_type *bus)  {  	return false;  } -static inline struct iommu_domain *iommu_domain_alloc(void) +static inline struct iommu_domain *iommu_domain_alloc(struct bus_type *bus)  {  	return NULL;  } @@ -123,6 +174,11 @@ static inline int domain_has_cap(struct iommu_domain *domain,  	return 0;  } +static inline void iommu_set_fault_handler(struct iommu_domain *domain, +					iommu_fault_handler_t handler) +{ +} +  #endif /* CONFIG_IOMMU_API */  #endif /* __LINUX_IOMMU_H */  |