iommu/vt-d: Misc macro clean up for SVM

Use combined macros for_each_svm_dev() to simplify SVM device iteration
and error checking.

Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
Jacob Pan 2020-01-02 08:18:10 +08:00 committed by Joerg Roedel
parent 5f75585e19
commit 034d473109

View File

@ -222,6 +222,10 @@ static const struct mmu_notifier_ops intel_mmuops = {
static DEFINE_MUTEX(pasid_mutex); static DEFINE_MUTEX(pasid_mutex);
static LIST_HEAD(global_svm_list); static LIST_HEAD(global_svm_list);
#define for_each_svm_dev(sdev, svm, d) \
list_for_each_entry((sdev), &(svm)->devs, list) \
if ((d) != (sdev)->dev) {} else
int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_ops *ops) int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_ops *ops)
{ {
struct intel_iommu *iommu = intel_svm_device_to_iommu(dev); struct intel_iommu *iommu = intel_svm_device_to_iommu(dev);
@ -270,15 +274,14 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_
goto out; goto out;
} }
list_for_each_entry(sdev, &svm->devs, list) { /* Find the matching device in svm list */
if (dev == sdev->dev) { for_each_svm_dev(sdev, svm, dev) {
if (sdev->ops != ops) { if (sdev->ops != ops) {
ret = -EBUSY; ret = -EBUSY;
goto out; goto out;
}
sdev->users++;
goto success;
} }
sdev->users++;
goto success;
} }
break; break;
@ -423,40 +426,36 @@ int intel_svm_unbind_mm(struct device *dev, int pasid)
goto out; goto out;
} }
list_for_each_entry(sdev, &svm->devs, list) { for_each_svm_dev(sdev, svm, dev) {
if (dev == sdev->dev) { ret = 0;
ret = 0; sdev->users--;
sdev->users--; if (!sdev->users) {
if (!sdev->users) { list_del_rcu(&sdev->list);
list_del_rcu(&sdev->list); /* Flush the PASID cache and IOTLB for this device.
/* Flush the PASID cache and IOTLB for this device. * Note that we do depend on the hardware *not* using
* Note that we do depend on the hardware *not* using * the PASID any more. Just as we depend on other
* the PASID any more. Just as we depend on other * devices never using PASIDs that they have no right
* devices never using PASIDs that they have no right * to use. We have a *shared* PASID table, because it's
* to use. We have a *shared* PASID table, because it's * large and has to be physically contiguous. So it's
* large and has to be physically contiguous. So it's * hard to be as defensive as we might like. */
* hard to be as defensive as we might like. */ intel_pasid_tear_down_entry(iommu, dev, svm->pasid);
intel_pasid_tear_down_entry(iommu, dev, svm->pasid); intel_flush_svm_range_dev(svm, sdev, 0, -1, 0);
intel_flush_svm_range_dev(svm, sdev, 0, -1, 0); kfree_rcu(sdev, rcu);
kfree_rcu(sdev, rcu);
if (list_empty(&svm->devs)) { if (list_empty(&svm->devs)) {
ioasid_free(svm->pasid); ioasid_free(svm->pasid);
if (svm->mm) if (svm->mm)
mmu_notifier_unregister(&svm->notifier, svm->mm); mmu_notifier_unregister(&svm->notifier, svm->mm);
list_del(&svm->list);
list_del(&svm->list); /* We mandate that no page faults may be outstanding
* for the PASID when intel_svm_unbind_mm() is called.
/* We mandate that no page faults may be outstanding * If that is not obeyed, subtle errors will happen.
* for the PASID when intel_svm_unbind_mm() is called. * Let's make them less subtle... */
* If that is not obeyed, subtle errors will happen. memset(svm, 0x6b, sizeof(*svm));
* Let's make them less subtle... */ kfree(svm);
memset(svm, 0x6b, sizeof(*svm));
kfree(svm);
}
} }
break;
} }
break;
} }
out: out:
mutex_unlock(&pasid_mutex); mutex_unlock(&pasid_mutex);