diff options
author | CQ Tang <cq.tang@intel.com> | 2017-05-10 14:39:03 -0400 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2017-05-17 08:57:56 -0400 |
commit | 15060aba717115dc9f204c02213a7c6bf341163e (patch) | |
tree | 7ecaa7018f3cf6259a8b0344f63d727dbfccbab2 | |
parent | 2ea659a9ef488125eb46da6eb571de5eae5c43f6 (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.c | 30 | ||||
-rw-r--r-- | include/linux/intel-svm.h | 20 |
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 | } |
490 | EXPORT_SYMBOL_GPL(intel_svm_unbind_mm); | 490 | EXPORT_SYMBOL_GPL(intel_svm_unbind_mm); |
491 | 491 | ||
492 | int 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 | } | ||
520 | EXPORT_SYMBOL_GPL(intel_svm_is_pasid_valid); | ||
521 | |||
492 | /* Page request queue descriptor */ | 522 | /* Page request queue descriptor */ |
493 | struct page_req_dsc { | 523 | struct 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 | */ |
103 | extern int intel_svm_unbind_mm(struct device *dev, int pasid); | 103 | extern 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 | */ | ||
118 | extern 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 | ||
107 | static inline int intel_svm_bind_mm(struct device *dev, int *pasid, | 122 | static 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 | |||
133 | static 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)) |