Merge tag 'iommu-updates-v6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/joro...
[platform/kernel/linux-rpi.git] / drivers / iommu / intel / svm.c
index 8f6d680..50a481c 100644 (file)
@@ -26,8 +26,6 @@
 #include "trace.h"
 
 static irqreturn_t prq_event_thread(int irq, void *d);
-static void intel_svm_drain_prq(struct device *dev, u32 pasid);
-#define to_intel_svm_dev(handle) container_of(handle, struct intel_svm_dev, sva)
 
 static DEFINE_XARRAY_ALLOC(pasid_private_array);
 static int pasid_private_add(ioasid_t pasid, void *priv)
@@ -259,8 +257,6 @@ static const struct mmu_notifier_ops intel_mmuops = {
        .arch_invalidate_secondary_tlbs = intel_arch_invalidate_secondary_tlbs,
 };
 
-static DEFINE_MUTEX(pasid_mutex);
-
 static int pasid_to_svm_sdev(struct device *dev, unsigned int pasid,
                             struct intel_svm **rsvm,
                             struct intel_svm_dev **rsdev)
@@ -268,10 +264,6 @@ static int pasid_to_svm_sdev(struct device *dev, unsigned int pasid,
        struct intel_svm_dev *sdev = NULL;
        struct intel_svm *svm;
 
-       /* The caller should hold the pasid_mutex lock */
-       if (WARN_ON(!mutex_is_locked(&pasid_mutex)))
-               return -EINVAL;
-
        if (pasid == IOMMU_PASID_INVALID || pasid >= PASID_MAX)
                return -EINVAL;
 
@@ -371,37 +363,23 @@ free_svm:
        return ret;
 }
 
-/* Caller must hold pasid_mutex */
-static int intel_svm_unbind_mm(struct device *dev, u32 pasid)
+void intel_svm_remove_dev_pasid(struct device *dev, u32 pasid)
 {
        struct intel_svm_dev *sdev;
        struct intel_iommu *iommu;
        struct intel_svm *svm;
        struct mm_struct *mm;
-       int ret = -EINVAL;
 
        iommu = device_to_iommu(dev, NULL, NULL);
        if (!iommu)
-               goto out;
+               return;
 
-       ret = pasid_to_svm_sdev(dev, pasid, &svm, &sdev);
-       if (ret)
-               goto out;
+       if (pasid_to_svm_sdev(dev, pasid, &svm, &sdev))
+               return;
        mm = svm->mm;
 
        if (sdev) {
                list_del_rcu(&sdev->list);
-               /*
-                * Flush the PASID cache and IOTLB for this device.
-                * Note that we do depend on the hardware *not* using
-                * the PASID any more. Just as we depend on other
-                * devices never using PASIDs that they have no right
-                * to use. We have a *shared* PASID table, because it's
-                * large and has to be physically contiguous. So it's
-                * hard to be as defensive as we might like.
-                */
-               intel_pasid_tear_down_entry(iommu, dev, svm->pasid, false);
-               intel_svm_drain_prq(dev, svm->pasid);
                kfree_rcu(sdev, rcu);
 
                if (list_empty(&svm->devs)) {
@@ -418,8 +396,6 @@ static int intel_svm_unbind_mm(struct device *dev, u32 pasid)
                        kfree(svm);
                }
        }
-out:
-       return ret;
 }
 
 /* Page request queue descriptor */
@@ -460,7 +436,7 @@ static bool is_canonical_address(u64 addr)
 }
 
 /**
- * intel_svm_drain_prq - Drain page requests and responses for a pasid
+ * intel_drain_pasid_prq - Drain page requests and responses for a pasid
  * @dev: target device
  * @pasid: pasid for draining
  *
@@ -474,7 +450,7 @@ static bool is_canonical_address(u64 addr)
  * described in VT-d spec CH7.10 to drain all page requests and page
  * responses pending in the hardware.
  */
-static void intel_svm_drain_prq(struct device *dev, u32 pasid)
+void intel_drain_pasid_prq(struct device *dev, u32 pasid)
 {
        struct device_domain_info *info;
        struct dmar_domain *domain;
@@ -520,19 +496,7 @@ prq_retry:
                goto prq_retry;
        }
 
-       /*
-        * A work in IO page fault workqueue may try to lock pasid_mutex now.
-        * Holding pasid_mutex while waiting in iopf_queue_flush_dev() for
-        * all works in the workqueue to finish may cause deadlock.
-        *
-        * It's unnecessary to hold pasid_mutex in iopf_queue_flush_dev().
-        * Unlock it to allow the works to be handled while waiting for
-        * them to finish.
-        */
-       lockdep_assert_held(&pasid_mutex);
-       mutex_unlock(&pasid_mutex);
        iopf_queue_flush_dev(dev);
-       mutex_lock(&pasid_mutex);
 
        /*
         * Perform steps described in VT-d spec CH7.10 to drain page
@@ -827,26 +791,14 @@ out:
        return ret;
 }
 
-void intel_svm_remove_dev_pasid(struct device *dev, ioasid_t pasid)
-{
-       mutex_lock(&pasid_mutex);
-       intel_svm_unbind_mm(dev, pasid);
-       mutex_unlock(&pasid_mutex);
-}
-
 static int intel_svm_set_dev_pasid(struct iommu_domain *domain,
                                   struct device *dev, ioasid_t pasid)
 {
        struct device_domain_info *info = dev_iommu_priv_get(dev);
        struct intel_iommu *iommu = info->iommu;
        struct mm_struct *mm = domain->mm;
-       int ret;
 
-       mutex_lock(&pasid_mutex);
-       ret = intel_svm_bind_mm(iommu, dev, mm);
-       mutex_unlock(&pasid_mutex);
-
-       return ret;
+       return intel_svm_bind_mm(iommu, dev, mm);
 }
 
 static void intel_svm_domain_free(struct iommu_domain *domain)