Commit 0860788d authored by Jean-Philippe Brucker's avatar Jean-Philippe Brucker Committed by Joerg Roedel
Browse files

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: default avatarZhangfei Gao <zhangfei.gao@linaro.org>
Signed-off-by: default avatarJean-Philippe Brucker <jean-philippe@linaro.org>
Link: https://lore.kernel.org/r/20210401154718.307519-6-jean-philippe@linaro.org


Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 9003351c
Loading
Loading
Loading
Loading
+30 −9
Original line number Diff line number Diff line
@@ -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);