The IOPF (I/O Page Fault) feature is now enabled independently from the
SVA feature, because some IOPF implementations are device-specific and
do not require IOMMU support for PCIe PRI or Arm SMMU stall.

Enable IOPF unconditionally when enabling SVA for now. In the future, if
a device driver implementing a uacce interface doesn't need IOPF
support, it will need to tell the uacce module, for example with a new
flag.

Acked-by: Zhangfei Gao <zhangfei....@linaro.org>
Signed-off-by: Jean-Philippe Brucker <jean-phili...@linaro.org>
---
Cc: Arnd Bergmann <a...@arndb.de>
Cc: Greg Kroah-Hartman <gre...@linuxfoundation.org>
Cc: Zhangfei Gao <zhangfei....@linaro.org>
Cc: Zhou Wang <wangzh...@hisilicon.com>
---
 drivers/misc/uacce/uacce.c | 39 +++++++++++++++++++++++++++++---------
 1 file changed, 30 insertions(+), 9 deletions(-)

diff --git a/drivers/misc/uacce/uacce.c b/drivers/misc/uacce/uacce.c
index d07af4edfcac..6db7a98486ec 100644
--- a/drivers/misc/uacce/uacce.c
+++ b/drivers/misc/uacce/uacce.c
@@ -385,6 +385,33 @@ static void uacce_release(struct device *dev)
        kfree(uacce);
 }
 
+static unsigned int uacce_enable_sva(struct device *parent, unsigned int flags)
+{
+       if (!(flags & UACCE_DEV_SVA))
+               return flags;
+
+       flags &= ~UACCE_DEV_SVA;
+
+       if (iommu_dev_enable_feature(parent, IOMMU_DEV_FEAT_IOPF))
+               return flags;
+
+       if (iommu_dev_enable_feature(parent, IOMMU_DEV_FEAT_SVA)) {
+               iommu_dev_disable_feature(parent, IOMMU_DEV_FEAT_IOPF);
+               return flags;
+       }
+
+       return flags | UACCE_DEV_SVA;
+}
+
+static void uacce_disable_sva(struct uacce_device *uacce)
+{
+       if (!(uacce->flags & UACCE_DEV_SVA))
+               return;
+
+       iommu_dev_disable_feature(uacce->parent, IOMMU_DEV_FEAT_SVA);
+       iommu_dev_disable_feature(uacce->parent, IOMMU_DEV_FEAT_IOPF);
+}
+
 /**
  * uacce_alloc() - alloc an accelerator
  * @parent: pointer of uacce parent device
@@ -404,11 +431,7 @@ struct uacce_device *uacce_alloc(struct device *parent,
        if (!uacce)
                return ERR_PTR(-ENOMEM);
 
-       if (flags & UACCE_DEV_SVA) {
-               ret = iommu_dev_enable_feature(parent, IOMMU_DEV_FEAT_SVA);
-               if (ret)
-                       flags &= ~UACCE_DEV_SVA;
-       }
+       flags = uacce_enable_sva(parent, flags);
 
        uacce->parent = parent;
        uacce->flags = flags;
@@ -432,8 +455,7 @@ struct uacce_device *uacce_alloc(struct device *parent,
        return uacce;
 
 err_with_uacce:
-       if (flags & UACCE_DEV_SVA)
-               iommu_dev_disable_feature(uacce->parent, IOMMU_DEV_FEAT_SVA);
+       uacce_disable_sva(uacce);
        kfree(uacce);
        return ERR_PTR(ret);
 }
@@ -487,8 +509,7 @@ void uacce_remove(struct uacce_device *uacce)
        mutex_unlock(&uacce->queues_lock);
 
        /* disable sva now since no opened queues */
-       if (uacce->flags & UACCE_DEV_SVA)
-               iommu_dev_disable_feature(uacce->parent, IOMMU_DEV_FEAT_SVA);
+       uacce_disable_sva(uacce);
 
        if (uacce->cdev)
                cdev_device_del(uacce->cdev, &uacce->dev);
-- 
2.30.0

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Reply via email to