diff options
Diffstat (limited to 'include/linux/iommu.h')
-rw-r--r-- | include/linux/iommu.h | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/include/linux/iommu.h b/include/linux/iommu.h index ffbbc7e39cee..a815cf6f6f47 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h | |||
@@ -48,6 +48,7 @@ struct bus_type; | |||
48 | struct device; | 48 | struct device; |
49 | struct iommu_domain; | 49 | struct iommu_domain; |
50 | struct notifier_block; | 50 | struct notifier_block; |
51 | struct iommu_sva; | ||
51 | 52 | ||
52 | /* iommu fault flags */ | 53 | /* iommu fault flags */ |
53 | #define IOMMU_FAULT_READ 0x0 | 54 | #define IOMMU_FAULT_READ 0x0 |
@@ -55,6 +56,8 @@ struct notifier_block; | |||
55 | 56 | ||
56 | typedef int (*iommu_fault_handler_t)(struct iommu_domain *, | 57 | typedef int (*iommu_fault_handler_t)(struct iommu_domain *, |
57 | struct device *, unsigned long, int, void *); | 58 | struct device *, unsigned long, int, void *); |
59 | typedef int (*iommu_mm_exit_handler_t)(struct device *dev, struct iommu_sva *, | ||
60 | void *); | ||
58 | 61 | ||
59 | struct iommu_domain_geometry { | 62 | struct iommu_domain_geometry { |
60 | dma_addr_t aperture_start; /* First address that can be mapped */ | 63 | dma_addr_t aperture_start; /* First address that can be mapped */ |
@@ -156,6 +159,33 @@ struct iommu_resv_region { | |||
156 | enum iommu_resv_type type; | 159 | enum iommu_resv_type type; |
157 | }; | 160 | }; |
158 | 161 | ||
162 | /* Per device IOMMU features */ | ||
163 | enum iommu_dev_features { | ||
164 | IOMMU_DEV_FEAT_AUX, /* Aux-domain feature */ | ||
165 | IOMMU_DEV_FEAT_SVA, /* Shared Virtual Addresses */ | ||
166 | }; | ||
167 | |||
168 | #define IOMMU_PASID_INVALID (-1U) | ||
169 | |||
170 | /** | ||
171 | * struct iommu_sva_ops - device driver callbacks for an SVA context | ||
172 | * | ||
173 | * @mm_exit: called when the mm is about to be torn down by exit_mmap. After | ||
174 | * @mm_exit returns, the device must not issue any more transaction | ||
175 | * with the PASID given as argument. | ||
176 | * | ||
177 | * The @mm_exit handler is allowed to sleep. Be careful about the | ||
178 | * locks taken in @mm_exit, because they might lead to deadlocks if | ||
179 | * they are also held when dropping references to the mm. Consider the | ||
180 | * following call chain: | ||
181 | * mutex_lock(A); mmput(mm) -> exit_mm() -> @mm_exit() -> mutex_lock(A) | ||
182 | * Using mmput_async() prevents this scenario. | ||
183 | * | ||
184 | */ | ||
185 | struct iommu_sva_ops { | ||
186 | iommu_mm_exit_handler_t mm_exit; | ||
187 | }; | ||
188 | |||
159 | #ifdef CONFIG_IOMMU_API | 189 | #ifdef CONFIG_IOMMU_API |
160 | 190 | ||
161 | /** | 191 | /** |
@@ -186,6 +216,14 @@ struct iommu_resv_region { | |||
186 | * @of_xlate: add OF master IDs to iommu grouping | 216 | * @of_xlate: add OF master IDs to iommu grouping |
187 | * @is_attach_deferred: Check if domain attach should be deferred from iommu | 217 | * @is_attach_deferred: Check if domain attach should be deferred from iommu |
188 | * driver init to device driver init (default no) | 218 | * driver init to device driver init (default no) |
219 | * @dev_has/enable/disable_feat: per device entries to check/enable/disable | ||
220 | * iommu specific features. | ||
221 | * @dev_feat_enabled: check enabled feature | ||
222 | * @aux_attach/detach_dev: aux-domain specific attach/detach entries. | ||
223 | * @aux_get_pasid: get the pasid given an aux-domain | ||
224 | * @sva_bind: Bind process address space to device | ||
225 | * @sva_unbind: Unbind process address space from device | ||
226 | * @sva_get_pasid: Get PASID associated to a SVA handle | ||
189 | * @pgsize_bitmap: bitmap of all possible supported page sizes | 227 | * @pgsize_bitmap: bitmap of all possible supported page sizes |
190 | */ | 228 | */ |
191 | struct iommu_ops { | 229 | struct iommu_ops { |
@@ -230,6 +268,22 @@ struct iommu_ops { | |||
230 | int (*of_xlate)(struct device *dev, struct of_phandle_args *args); | 268 | int (*of_xlate)(struct device *dev, struct of_phandle_args *args); |
231 | bool (*is_attach_deferred)(struct iommu_domain *domain, struct device *dev); | 269 | bool (*is_attach_deferred)(struct iommu_domain *domain, struct device *dev); |
232 | 270 | ||
271 | /* Per device IOMMU features */ | ||
272 | bool (*dev_has_feat)(struct device *dev, enum iommu_dev_features f); | ||
273 | bool (*dev_feat_enabled)(struct device *dev, enum iommu_dev_features f); | ||
274 | int (*dev_enable_feat)(struct device *dev, enum iommu_dev_features f); | ||
275 | int (*dev_disable_feat)(struct device *dev, enum iommu_dev_features f); | ||
276 | |||
277 | /* Aux-domain specific attach/detach entries */ | ||
278 | int (*aux_attach_dev)(struct iommu_domain *domain, struct device *dev); | ||
279 | void (*aux_detach_dev)(struct iommu_domain *domain, struct device *dev); | ||
280 | int (*aux_get_pasid)(struct iommu_domain *domain, struct device *dev); | ||
281 | |||
282 | struct iommu_sva *(*sva_bind)(struct device *dev, struct mm_struct *mm, | ||
283 | void *drvdata); | ||
284 | void (*sva_unbind)(struct iommu_sva *handle); | ||
285 | int (*sva_get_pasid)(struct iommu_sva *handle); | ||
286 | |||
233 | unsigned long pgsize_bitmap; | 287 | unsigned long pgsize_bitmap; |
234 | }; | 288 | }; |
235 | 289 | ||
@@ -392,10 +446,22 @@ struct iommu_fwspec { | |||
392 | const struct iommu_ops *ops; | 446 | const struct iommu_ops *ops; |
393 | struct fwnode_handle *iommu_fwnode; | 447 | struct fwnode_handle *iommu_fwnode; |
394 | void *iommu_priv; | 448 | void *iommu_priv; |
449 | u32 flags; | ||
395 | unsigned int num_ids; | 450 | unsigned int num_ids; |
396 | u32 ids[1]; | 451 | u32 ids[1]; |
397 | }; | 452 | }; |
398 | 453 | ||
454 | /* ATS is supported */ | ||
455 | #define IOMMU_FWSPEC_PCI_RC_ATS (1 << 0) | ||
456 | |||
457 | /** | ||
458 | * struct iommu_sva - handle to a device-mm bond | ||
459 | */ | ||
460 | struct iommu_sva { | ||
461 | struct device *dev; | ||
462 | const struct iommu_sva_ops *ops; | ||
463 | }; | ||
464 | |||
399 | int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode, | 465 | int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode, |
400 | const struct iommu_ops *ops); | 466 | const struct iommu_ops *ops); |
401 | void iommu_fwspec_free(struct device *dev); | 467 | void iommu_fwspec_free(struct device *dev); |
@@ -416,6 +482,22 @@ static inline void dev_iommu_fwspec_set(struct device *dev, | |||
416 | int iommu_probe_device(struct device *dev); | 482 | int iommu_probe_device(struct device *dev); |
417 | void iommu_release_device(struct device *dev); | 483 | void iommu_release_device(struct device *dev); |
418 | 484 | ||
485 | bool iommu_dev_has_feature(struct device *dev, enum iommu_dev_features f); | ||
486 | int iommu_dev_enable_feature(struct device *dev, enum iommu_dev_features f); | ||
487 | int iommu_dev_disable_feature(struct device *dev, enum iommu_dev_features f); | ||
488 | bool iommu_dev_feature_enabled(struct device *dev, enum iommu_dev_features f); | ||
489 | int iommu_aux_attach_device(struct iommu_domain *domain, struct device *dev); | ||
490 | void iommu_aux_detach_device(struct iommu_domain *domain, struct device *dev); | ||
491 | int iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev); | ||
492 | |||
493 | struct iommu_sva *iommu_sva_bind_device(struct device *dev, | ||
494 | struct mm_struct *mm, | ||
495 | void *drvdata); | ||
496 | void iommu_sva_unbind_device(struct iommu_sva *handle); | ||
497 | int iommu_sva_set_ops(struct iommu_sva *handle, | ||
498 | const struct iommu_sva_ops *ops); | ||
499 | int iommu_sva_get_pasid(struct iommu_sva *handle); | ||
500 | |||
419 | #else /* CONFIG_IOMMU_API */ | 501 | #else /* CONFIG_IOMMU_API */ |
420 | 502 | ||
421 | struct iommu_ops {}; | 503 | struct iommu_ops {}; |
@@ -700,6 +782,68 @@ const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode) | |||
700 | return NULL; | 782 | return NULL; |
701 | } | 783 | } |
702 | 784 | ||
785 | static inline bool | ||
786 | iommu_dev_has_feature(struct device *dev, enum iommu_dev_features feat) | ||
787 | { | ||
788 | return false; | ||
789 | } | ||
790 | |||
791 | static inline bool | ||
792 | iommu_dev_feature_enabled(struct device *dev, enum iommu_dev_features feat) | ||
793 | { | ||
794 | return false; | ||
795 | } | ||
796 | |||
797 | static inline int | ||
798 | iommu_dev_enable_feature(struct device *dev, enum iommu_dev_features feat) | ||
799 | { | ||
800 | return -ENODEV; | ||
801 | } | ||
802 | |||
803 | static inline int | ||
804 | iommu_dev_disable_feature(struct device *dev, enum iommu_dev_features feat) | ||
805 | { | ||
806 | return -ENODEV; | ||
807 | } | ||
808 | |||
809 | static inline int | ||
810 | iommu_aux_attach_device(struct iommu_domain *domain, struct device *dev) | ||
811 | { | ||
812 | return -ENODEV; | ||
813 | } | ||
814 | |||
815 | static inline void | ||
816 | iommu_aux_detach_device(struct iommu_domain *domain, struct device *dev) | ||
817 | { | ||
818 | } | ||
819 | |||
820 | static inline int | ||
821 | iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev) | ||
822 | { | ||
823 | return -ENODEV; | ||
824 | } | ||
825 | |||
826 | static inline struct iommu_sva * | ||
827 | iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, void *drvdata) | ||
828 | { | ||
829 | return NULL; | ||
830 | } | ||
831 | |||
832 | static inline void iommu_sva_unbind_device(struct iommu_sva *handle) | ||
833 | { | ||
834 | } | ||
835 | |||
836 | static inline int iommu_sva_set_ops(struct iommu_sva *handle, | ||
837 | const struct iommu_sva_ops *ops) | ||
838 | { | ||
839 | return -EINVAL; | ||
840 | } | ||
841 | |||
842 | static inline int iommu_sva_get_pasid(struct iommu_sva *handle) | ||
843 | { | ||
844 | return IOMMU_PASID_INVALID; | ||
845 | } | ||
846 | |||
703 | #endif /* CONFIG_IOMMU_API */ | 847 | #endif /* CONFIG_IOMMU_API */ |
704 | 848 | ||
705 | #ifdef CONFIG_IOMMU_DEBUGFS | 849 | #ifdef CONFIG_IOMMU_DEBUGFS |