dmaengine: idxd: Add enable/disable device IOPF feature
The iommu subsystem requires IOMMU_DEV_FEAT_IOPF must be enabled before and disabled after IOMMU_DEV_FEAT_SVA, if device's I/O page faults rely on the IOMMU. Add explicit IOMMU_DEV_FEAT_IOPF enabling/disabling in this driver. At present, missing IOPF enabling/disabling doesn't cause any real issue, because the IOMMU driver places the IOPF enabling/disabling in the path of SVA feature handling. But this may change. Reviewed-by: Dave Jiang <dave.jiang@intel.com> Reviewed-by: Fenghua Yu <fenghua.yu@intel.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Acked-by: Vinod Koul <vkoul@kernel.org> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Link: https://lore.kernel.org/r/20230324120234.313643-2-baolu.lu@linux.intel.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
e8d018dd02
commit
84c9ef72b6
1 changed files with 25 additions and 6 deletions
|
@ -516,6 +516,27 @@ static void idxd_disable_system_pasid(struct idxd_device *idxd)
|
|||
idxd->sva = NULL;
|
||||
}
|
||||
|
||||
static int idxd_enable_sva(struct pci_dev *pdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = iommu_dev_enable_feature(&pdev->dev, IOMMU_DEV_FEAT_IOPF);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = iommu_dev_enable_feature(&pdev->dev, IOMMU_DEV_FEAT_SVA);
|
||||
if (ret)
|
||||
iommu_dev_disable_feature(&pdev->dev, IOMMU_DEV_FEAT_IOPF);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void idxd_disable_sva(struct pci_dev *pdev)
|
||||
{
|
||||
iommu_dev_disable_feature(&pdev->dev, IOMMU_DEV_FEAT_SVA);
|
||||
iommu_dev_disable_feature(&pdev->dev, IOMMU_DEV_FEAT_IOPF);
|
||||
}
|
||||
|
||||
static int idxd_probe(struct idxd_device *idxd)
|
||||
{
|
||||
struct pci_dev *pdev = idxd->pdev;
|
||||
|
@ -530,7 +551,7 @@ static int idxd_probe(struct idxd_device *idxd)
|
|||
dev_dbg(dev, "IDXD reset complete\n");
|
||||
|
||||
if (IS_ENABLED(CONFIG_INTEL_IDXD_SVM) && sva) {
|
||||
if (iommu_dev_enable_feature(dev, IOMMU_DEV_FEAT_SVA)) {
|
||||
if (idxd_enable_sva(pdev)) {
|
||||
dev_warn(dev, "Unable to turn on user SVA feature.\n");
|
||||
} else {
|
||||
set_bit(IDXD_FLAG_USER_PASID_ENABLED, &idxd->flags);
|
||||
|
@ -578,21 +599,19 @@ static int idxd_probe(struct idxd_device *idxd)
|
|||
if (device_pasid_enabled(idxd))
|
||||
idxd_disable_system_pasid(idxd);
|
||||
if (device_user_pasid_enabled(idxd))
|
||||
iommu_dev_disable_feature(dev, IOMMU_DEV_FEAT_SVA);
|
||||
idxd_disable_sva(pdev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void idxd_cleanup(struct idxd_device *idxd)
|
||||
{
|
||||
struct device *dev = &idxd->pdev->dev;
|
||||
|
||||
perfmon_pmu_remove(idxd);
|
||||
idxd_cleanup_interrupts(idxd);
|
||||
idxd_cleanup_internals(idxd);
|
||||
if (device_pasid_enabled(idxd))
|
||||
idxd_disable_system_pasid(idxd);
|
||||
if (device_user_pasid_enabled(idxd))
|
||||
iommu_dev_disable_feature(dev, IOMMU_DEV_FEAT_SVA);
|
||||
idxd_disable_sva(idxd->pdev);
|
||||
}
|
||||
|
||||
static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
|
@ -710,7 +729,7 @@ static void idxd_remove(struct pci_dev *pdev)
|
|||
pci_free_irq_vectors(pdev);
|
||||
pci_iounmap(pdev, idxd->reg_base);
|
||||
if (device_user_pasid_enabled(idxd))
|
||||
iommu_dev_disable_feature(&pdev->dev, IOMMU_DEV_FEAT_SVA);
|
||||
idxd_disable_sva(pdev);
|
||||
pci_disable_device(pdev);
|
||||
destroy_workqueue(idxd->wq);
|
||||
perfmon_pmu_remove(idxd);
|
||||
|
|
Loading…
Add table
Reference in a new issue