aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/iommu/intel-svm.c14
-rw-r--r--include/linux/intel-iommu.h1
2 files changed, 11 insertions, 4 deletions
diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c
index 2cc0aac93201..36cc1d1b8afc 100644
--- a/drivers/iommu/intel-svm.c
+++ b/drivers/iommu/intel-svm.c
@@ -298,6 +298,7 @@ static const struct mmu_notifier_ops intel_mmuops = {
298}; 298};
299 299
300static DEFINE_MUTEX(pasid_mutex); 300static DEFINE_MUTEX(pasid_mutex);
301static LIST_HEAD(global_svm_list);
301 302
302int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_ops *ops) 303int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_ops *ops)
303{ 304{
@@ -329,13 +330,13 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_
329 330
330 mutex_lock(&pasid_mutex); 331 mutex_lock(&pasid_mutex);
331 if (pasid && !(flags & SVM_FLAG_PRIVATE_PASID)) { 332 if (pasid && !(flags & SVM_FLAG_PRIVATE_PASID)) {
332 int i; 333 struct intel_svm *t;
333 334
334 idr_for_each_entry(&iommu->pasid_idr, svm, i) { 335 list_for_each_entry(t, &global_svm_list, list) {
335 if (svm->mm != mm || 336 if (t->mm != mm || (t->flags & SVM_FLAG_PRIVATE_PASID))
336 (svm->flags & SVM_FLAG_PRIVATE_PASID))
337 continue; 337 continue;
338 338
339 svm = t;
339 if (svm->pasid >= pasid_max) { 340 if (svm->pasid >= pasid_max) {
340 dev_warn(dev, 341 dev_warn(dev,
341 "Limited PASID width. Cannot use existing PASID %d\n", 342 "Limited PASID width. Cannot use existing PASID %d\n",
@@ -404,6 +405,7 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_
404 svm->mm = mm; 405 svm->mm = mm;
405 svm->flags = flags; 406 svm->flags = flags;
406 INIT_LIST_HEAD_RCU(&svm->devs); 407 INIT_LIST_HEAD_RCU(&svm->devs);
408 INIT_LIST_HEAD(&svm->list);
407 ret = -ENOMEM; 409 ret = -ENOMEM;
408 if (mm) { 410 if (mm) {
409 ret = mmu_notifier_register(&svm->notifier, mm); 411 ret = mmu_notifier_register(&svm->notifier, mm);
@@ -430,6 +432,8 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_
430 */ 432 */
431 if (cap_caching_mode(iommu->cap)) 433 if (cap_caching_mode(iommu->cap))
432 intel_flush_pasid_dev(svm, sdev, svm->pasid); 434 intel_flush_pasid_dev(svm, sdev, svm->pasid);
435
436 list_add_tail(&svm->list, &global_svm_list);
433 } 437 }
434 list_add_rcu(&sdev->list, &svm->devs); 438 list_add_rcu(&sdev->list, &svm->devs);
435 439
@@ -485,6 +489,8 @@ int intel_svm_unbind_mm(struct device *dev, int pasid)
485 if (svm->mm) 489 if (svm->mm)
486 mmu_notifier_unregister(&svm->notifier, svm->mm); 490 mmu_notifier_unregister(&svm->notifier, svm->mm);
487 491
492 list_del(&svm->list);
493
488 /* We mandate that no page faults may be outstanding 494 /* We mandate that no page faults may be outstanding
489 * for the PASID when intel_svm_unbind_mm() is called. 495 * for the PASID when intel_svm_unbind_mm() is called.
490 * If that is not obeyed, subtle errors will happen. 496 * If that is not obeyed, subtle errors will happen.
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 6692b40ca814..e1e193855581 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -487,6 +487,7 @@ struct intel_svm {
487 int flags; 487 int flags;
488 int pasid; 488 int pasid;
489 struct list_head devs; 489 struct list_head devs;
490 struct list_head list;
490}; 491};
491 492
492extern int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev); 493extern int intel_iommu_enable_pasid(struct intel_iommu *iommu, struct intel_svm_dev *sdev);