Global PASID allocation is under IOMMU SVA code since it is the primary use case. However, some architecture such as VT-d, global PASIDs are necessary for its internal use of DMA API with PASID. This patch introduces SVA APIs to reserve and release global PASIDs. Link: https://lore.kernel.org/all/20230301235646.2692846-4-jacob.jun.pan@xxxxxxxxxxxxxxx/ Signed-off-by: Jacob Pan <jacob.jun.pan@xxxxxxxxxxxxxxx> --- drivers/iommu/iommu-sva.c | 25 +++++++++++++++++++++++++ include/linux/iommu.h | 14 ++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c index 8c92a145e15d..cfdeafde88a9 100644 --- a/drivers/iommu/iommu-sva.c +++ b/drivers/iommu/iommu-sva.c @@ -149,6 +149,31 @@ u32 iommu_sva_get_pasid(struct iommu_sva *handle) } EXPORT_SYMBOL_GPL(iommu_sva_get_pasid); +ioasid_t iommu_sva_reserve_pasid(ioasid_t min, ioasid_t max) +{ + int ret; + + if (min == IOMMU_PASID_INVALID || max == IOMMU_PASID_INVALID || + min == 0 || max < min) + return IOMMU_PASID_INVALID; + + ret = ida_alloc_range(&iommu_global_pasid_ida, min, max, GFP_KERNEL); + if (ret < 0) + return IOMMU_PASID_INVALID; + + return ret; +} +EXPORT_SYMBOL_GPL(iommu_sva_reserve_pasid); + +void iommu_sva_unreserve_pasid(ioasid_t pasid) +{ + if (!pasid_valid(pasid)) + return; + + ida_free(&iommu_global_pasid_ida, pasid); +} +EXPORT_SYMBOL_GPL(iommu_sva_unreserve_pasid); + /* * I/O page fault handler for SVA */ diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 39a97bd8f04a..8ba07eb03d32 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -1192,6 +1192,9 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm); void iommu_sva_unbind_device(struct iommu_sva *handle); u32 iommu_sva_get_pasid(struct iommu_sva *handle); +ioasid_t iommu_sva_reserve_pasid(ioasid_t min, ioasid_t max); +void iommu_sva_unreserve_pasid(ioasid_t pasid); + #else static inline struct iommu_sva * iommu_sva_bind_device(struct device *dev, struct mm_struct *mm) @@ -1207,6 +1210,17 @@ static inline u32 iommu_sva_get_pasid(struct iommu_sva *handle) { return IOMMU_PASID_INVALID; } + +static inline ioasid_t iommu_sva_reserve_pasid(ioasid_t min, ioasid_t max); +{ + return IOMMU_PASID_INVALID; +} + +static inline void iommu_sva_unreserve_pasid(ioasid_t pasid) +{ + +} + #endif /* CONFIG_IOMMU_SVA */ #endif /* __LINUX_IOMMU_H */ -- 2.25.1