aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCQ Tang <cq.tang@intel.com>2017-05-10 14:39:03 -0400
committerJoerg Roedel <jroedel@suse.de>2017-05-17 08:57:56 -0400
commit15060aba717115dc9f204c02213a7c6bf341163e (patch)
tree7ecaa7018f3cf6259a8b0344f63d727dbfccbab2
parent2ea659a9ef488125eb46da6eb571de5eae5c43f6 (diff)
iommu/vt-d: Helper function to query if a pasid has any active users
A driver would need to know if there are any active references to a a PASID before cleaning up its resources. This function helps check if there are any active users of a PASID before it can perform any recovery on that device. To: Joerg Roedel <joro@8bytes.org> To: linux-kernel@vger.kernel.org To: David Woodhouse <dwmw2@infradead.org> Cc: Jean-Phillipe Brucker <jean-philippe.brucker@arm.com> Cc: iommu@lists.linux-foundation.org Signed-off-by: CQ Tang <cq.tang@intel.com> Signed-off-by: Ashok Raj <ashok.raj@intel.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/iommu/intel-svm.c30
-rw-r--r--include/linux/intel-svm.h20
2 files changed, 50 insertions, 0 deletions
diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c
index 23c427602c55..f167c0d84ebf 100644
--- a/drivers/iommu/intel-svm.c
+++ b/drivers/iommu/intel-svm.c
@@ -489,6 +489,36 @@ int intel_svm_unbind_mm(struct device *dev, int pasid)
489} 489}
490EXPORT_SYMBOL_GPL(intel_svm_unbind_mm); 490EXPORT_SYMBOL_GPL(intel_svm_unbind_mm);
491 491
492int intel_svm_is_pasid_valid(struct device *dev, int pasid)
493{
494 struct intel_iommu *iommu;
495 struct intel_svm *svm;
496 int ret = -EINVAL;
497
498 mutex_lock(&pasid_mutex);
499 iommu = intel_svm_device_to_iommu(dev);
500 if (!iommu || !iommu->pasid_table)
501 goto out;
502
503 svm = idr_find(&iommu->pasid_idr, pasid);
504 if (!svm)
505 goto out;
506
507 /* init_mm is used in this case */
508 if (!svm->mm)
509 ret = 1;
510 else if (atomic_read(&svm->mm->mm_users) > 0)
511 ret = 1;
512 else
513 ret = 0;
514
515 out:
516 mutex_unlock(&pasid_mutex);
517
518 return ret;
519}
520EXPORT_SYMBOL_GPL(intel_svm_is_pasid_valid);
521
492/* Page request queue descriptor */ 522/* Page request queue descriptor */
493struct page_req_dsc { 523struct page_req_dsc {
494 u64 srr:1; 524 u64 srr:1;
diff --git a/include/linux/intel-svm.h b/include/linux/intel-svm.h
index 3c25794042f9..99bc5b3ae26e 100644
--- a/include/linux/intel-svm.h
+++ b/include/linux/intel-svm.h
@@ -102,6 +102,21 @@ extern int intel_svm_bind_mm(struct device *dev, int *pasid, int flags,
102 */ 102 */
103extern int intel_svm_unbind_mm(struct device *dev, int pasid); 103extern int intel_svm_unbind_mm(struct device *dev, int pasid);
104 104
105/**
106 * intel_svm_is_pasid_valid() - check if pasid is valid
107 * @dev: Device for which PASID was allocated
108 * @pasid: PASID value to be checked
109 *
110 * This function checks if the specified pasid is still valid. A
111 * valid pasid means the backing mm is still having a valid user.
112 * For kernel callers init_mm is always valid. for other mm, if mm->mm_users
113 * is non-zero, it is valid.
114 *
115 * returns -EINVAL if invalid pasid, 0 if pasid ref count is invalid
116 * 1 if pasid is valid.
117 */
118extern int intel_svm_is_pasid_valid(struct device *dev, int pasid);
119
105#else /* CONFIG_INTEL_IOMMU_SVM */ 120#else /* CONFIG_INTEL_IOMMU_SVM */
106 121
107static inline int intel_svm_bind_mm(struct device *dev, int *pasid, 122static inline int intel_svm_bind_mm(struct device *dev, int *pasid,
@@ -114,6 +129,11 @@ static inline int intel_svm_unbind_mm(struct device *dev, int pasid)
114{ 129{
115 BUG(); 130 BUG();
116} 131}
132
133static int intel_svm_is_pasid_valid(struct device *dev, int pasid)
134{
135 return -EINVAL;
136}
117#endif /* CONFIG_INTEL_IOMMU_SVM */ 137#endif /* CONFIG_INTEL_IOMMU_SVM */
118 138
119#define intel_svm_available(dev) (!intel_svm_bind_mm((dev), NULL, 0, NULL)) 139#define intel_svm_available(dev) (!intel_svm_bind_mm((dev), NULL, 0, NULL))