uacce: Enable IOMMU_DEV_FEAT_IOPF

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.gao@linaro.org>
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
Link: https://lore.kernel.org/r/20210401154718.307519-6-jean-philippe@linaro.org
Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
Jean-Philippe Brucker 2021-04-01 17:47:14 +02:00 committed by Joerg Roedel
parent 9003351cb6
commit 0860788df7
1 changed files with 30 additions and 9 deletions

View File

@ -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);