diff options
| -rw-r--r-- | drivers/iommu/iommu.c | 13 | ||||
| -rw-r--r-- | include/linux/iommu.h | 51 |
2 files changed, 64 insertions, 0 deletions
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 6e6b6a11b3ce..b75d9fb2fa91 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c | |||
| @@ -39,6 +39,19 @@ bool iommu_found(void) | |||
| 39 | } | 39 | } |
| 40 | EXPORT_SYMBOL_GPL(iommu_found); | 40 | EXPORT_SYMBOL_GPL(iommu_found); |
| 41 | 41 | ||
| 42 | /** | ||
| 43 | * iommu_set_fault_handler() - set a fault handler for an iommu domain | ||
| 44 | * @domain: iommu domain | ||
| 45 | * @handler: fault handler | ||
| 46 | */ | ||
| 47 | void iommu_set_fault_handler(struct iommu_domain *domain, | ||
| 48 | iommu_fault_handler_t handler) | ||
| 49 | { | ||
| 50 | BUG_ON(!domain); | ||
| 51 | |||
| 52 | domain->handler = handler; | ||
| 53 | } | ||
| 54 | |||
| 42 | struct iommu_domain *iommu_domain_alloc(void) | 55 | struct iommu_domain *iommu_domain_alloc(void) |
| 43 | { | 56 | { |
| 44 | struct iommu_domain *domain; | 57 | struct iommu_domain *domain; |
diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 9940319d6f9d..d084e8777e0e 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h | |||
| @@ -26,9 +26,18 @@ | |||
| 26 | #define IOMMU_CACHE (4) /* DMA cache coherency */ | 26 | #define IOMMU_CACHE (4) /* DMA cache coherency */ |
| 27 | 27 | ||
| 28 | struct device; | 28 | struct device; |
| 29 | struct iommu_domain; | ||
| 30 | |||
| 31 | /* iommu fault flags */ | ||
| 32 | #define IOMMU_FAULT_READ 0x0 | ||
| 33 | #define IOMMU_FAULT_WRITE 0x1 | ||
| 34 | |||
| 35 | typedef int (*iommu_fault_handler_t)(struct iommu_domain *, | ||
| 36 | struct device *, unsigned long, int); | ||
| 29 | 37 | ||
| 30 | struct iommu_domain { | 38 | struct iommu_domain { |
| 31 | void *priv; | 39 | void *priv; |
| 40 | iommu_fault_handler_t handler; | ||
| 32 | }; | 41 | }; |
| 33 | 42 | ||
| 34 | #define IOMMU_CAP_CACHE_COHERENCY 0x1 | 43 | #define IOMMU_CAP_CACHE_COHERENCY 0x1 |
| @@ -67,6 +76,43 @@ extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, | |||
| 67 | unsigned long iova); | 76 | unsigned long iova); |
| 68 | extern int iommu_domain_has_cap(struct iommu_domain *domain, | 77 | extern int iommu_domain_has_cap(struct iommu_domain *domain, |
| 69 | unsigned long cap); | 78 | unsigned long cap); |
| 79 | extern void iommu_set_fault_handler(struct iommu_domain *domain, | ||
| 80 | iommu_fault_handler_t handler); | ||
| 81 | |||
| 82 | /** | ||
| 83 | * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework | ||
| 84 | * @domain: the iommu domain where the fault has happened | ||
| 85 | * @dev: the device where the fault has happened | ||
| 86 | * @iova: the faulting address | ||
| 87 | * @flags: mmu fault flags (e.g. IOMMU_FAULT_READ/IOMMU_FAULT_WRITE/...) | ||
| 88 | * | ||
| 89 | * This function should be called by the low-level IOMMU implementations | ||
| 90 | * whenever IOMMU faults happen, to allow high-level users, that are | ||
| 91 | * interested in such events, to know about them. | ||
| 92 | * | ||
| 93 | * This event may be useful for several possible use cases: | ||
| 94 | * - mere logging of the event | ||
| 95 | * - dynamic TLB/PTE loading | ||
| 96 | * - if restarting of the faulting device is required | ||
| 97 | * | ||
| 98 | * Returns 0 on success and an appropriate error code otherwise (if dynamic | ||
| 99 | * PTE/TLB loading will one day be supported, implementations will be able | ||
| 100 | * to tell whether it succeeded or not according to this return value). | ||
| 101 | */ | ||
| 102 | static inline int report_iommu_fault(struct iommu_domain *domain, | ||
| 103 | struct device *dev, unsigned long iova, int flags) | ||
| 104 | { | ||
| 105 | int ret = 0; | ||
| 106 | |||
| 107 | /* | ||
| 108 | * if upper layers showed interest and installed a fault handler, | ||
| 109 | * invoke it. | ||
| 110 | */ | ||
| 111 | if (domain->handler) | ||
| 112 | ret = domain->handler(domain, dev, iova, flags); | ||
| 113 | |||
| 114 | return ret; | ||
| 115 | } | ||
| 70 | 116 | ||
| 71 | #else /* CONFIG_IOMMU_API */ | 117 | #else /* CONFIG_IOMMU_API */ |
| 72 | 118 | ||
| @@ -123,6 +169,11 @@ static inline int domain_has_cap(struct iommu_domain *domain, | |||
| 123 | return 0; | 169 | return 0; |
| 124 | } | 170 | } |
| 125 | 171 | ||
| 172 | static inline void iommu_set_fault_handler(struct iommu_domain *domain, | ||
| 173 | iommu_fault_handler_t handler) | ||
| 174 | { | ||
| 175 | } | ||
| 176 | |||
| 126 | #endif /* CONFIG_IOMMU_API */ | 177 | #endif /* CONFIG_IOMMU_API */ |
| 127 | 178 | ||
| 128 | #endif /* __LINUX_IOMMU_H */ | 179 | #endif /* __LINUX_IOMMU_H */ |
