diff --git a/patches.suse/dmaengine-idxd-Separate-user-and-kernel-pasid-enabli.patch b/patches.suse/dmaengine-idxd-Separate-user-and-kernel-pasid-enabli.patch new file mode 100644 index 0000000..2e69a66 --- /dev/null +++ b/patches.suse/dmaengine-idxd-Separate-user-and-kernel-pasid-enabli.patch @@ -0,0 +1,170 @@ +From 42a1b73852c4a176d233a192422b5e1d0ba67cbf Mon Sep 17 00:00:00 2001 +From: Dave Jiang +Date: Wed, 11 May 2022 17:11:57 -0700 +Subject: [PATCH] dmaengine: idxd: Separate user and kernel pasid enabling +Git-commit: 42a1b73852c4a176d233a192422b5e1d0ba67cbf +Patch-mainline: v5.19-rc1 +References: git-fixes + +The idxd driver always gated the pasid enabling under a single knob and +this assumption is incorrect. The pasid used for kernel operation can be +independently toggled and has no dependency on the user pasid (and vice +versa). Split the two so they are independent "enabled" flags. + +Signed-off-by: Dave Jiang +Link: https://lore.kernel.org/r/165231431746.986466.5666862038354800551.stgit@djiang5-desk3.ch.intel.com +Signed-off-by: Vinod Koul +Acked-by: Takashi Iwai + +--- + drivers/dma/idxd/cdev.c | 4 ++-- + drivers/dma/idxd/device.c | 4 ++-- + drivers/dma/idxd/idxd.h | 16 ++++++++++++++-- + drivers/dma/idxd/init.c | 30 +++++++++++++++--------------- + drivers/dma/idxd/sysfs.c | 2 +- + 5 files changed, 34 insertions(+), 22 deletions(-) + +--- a/drivers/dma/idxd/cdev.c ++++ b/drivers/dma/idxd/cdev.c +@@ -99,7 +99,7 @@ static int idxd_cdev_open(struct inode * + ctx->wq = wq; + filp->private_data = ctx; + +- if (device_pasid_enabled(idxd)) { ++ if (device_user_pasid_enabled(idxd)) { + sva = iommu_sva_bind_device(dev, current->mm, NULL); + if (IS_ERR(sva)) { + rc = PTR_ERR(sva); +@@ -152,7 +152,7 @@ static int idxd_cdev_release(struct inod + if (wq_shared(wq)) { + idxd_device_drain_pasid(idxd, ctx->pasid); + } else { +- if (device_pasid_enabled(idxd)) { ++ if (device_user_pasid_enabled(idxd)) { + /* The wq disable in the disable pasid function will drain the wq */ + rc = idxd_wq_disable_pasid(wq); + if (rc < 0) +--- a/drivers/dma/idxd/device.c ++++ b/drivers/dma/idxd/device.c +@@ -962,7 +962,7 @@ static int idxd_wqs_setup(struct idxd_de + if (!wq->group) + continue; + +- if (wq_shared(wq) && !device_swq_supported(idxd)) { ++ if (wq_shared(wq) && !wq_shared_supported(wq)) { + idxd->cmd_status = IDXD_SCMD_WQ_NO_SWQ_SUPPORT; + dev_warn(dev, "No shared wq support but configured.\n"); + return -EINVAL; +@@ -1267,7 +1267,7 @@ int __drv_enable_wq(struct idxd_wq *wq) + + /* Shared WQ checks */ + if (wq_shared(wq)) { +- if (!device_swq_supported(idxd)) { ++ if (!wq_shared_supported(wq)) { + idxd->cmd_status = IDXD_SCMD_WQ_NO_SVM; + dev_dbg(dev, "PASID not enabled and shared wq.\n"); + goto err; +--- a/drivers/dma/idxd/idxd.h ++++ b/drivers/dma/idxd/idxd.h +@@ -241,6 +241,7 @@ enum idxd_device_flag { + IDXD_FLAG_CONFIGURABLE = 0, + IDXD_FLAG_CMD_RUNNING, + IDXD_FLAG_PASID_ENABLED, ++ IDXD_FLAG_USER_PASID_ENABLED, + }; + + struct idxd_dma_dev { +@@ -471,9 +472,20 @@ static inline bool device_pasid_enabled( + return test_bit(IDXD_FLAG_PASID_ENABLED, &idxd->flags); + } + +-static inline bool device_swq_supported(struct idxd_device *idxd) ++static inline bool device_user_pasid_enabled(struct idxd_device *idxd) + { +- return (support_enqcmd && device_pasid_enabled(idxd)); ++ return test_bit(IDXD_FLAG_USER_PASID_ENABLED, &idxd->flags); ++} ++ ++static inline bool wq_pasid_enabled(struct idxd_wq *wq) ++{ ++ return (is_idxd_wq_kernel(wq) && device_pasid_enabled(wq->idxd)) || ++ (is_idxd_wq_user(wq) && device_user_pasid_enabled(wq->idxd)); ++} ++ ++static inline bool wq_shared_supported(struct idxd_wq *wq) ++{ ++ return (support_enqcmd && wq_pasid_enabled(wq)); + } + + enum idxd_portal_prot { +--- a/drivers/dma/idxd/init.c ++++ b/drivers/dma/idxd/init.c +@@ -512,18 +512,15 @@ static int idxd_probe(struct idxd_device + dev_dbg(dev, "IDXD reset complete\n"); + + if (IS_ENABLED(CONFIG_INTEL_IDXD_SVM) && sva) { +- rc = iommu_dev_enable_feature(dev, IOMMU_DEV_FEAT_SVA); +- if (rc == 0) { +- rc = idxd_enable_system_pasid(idxd); +- if (rc < 0) { +- iommu_dev_disable_feature(dev, IOMMU_DEV_FEAT_SVA); +- dev_warn(dev, "Failed to enable PASID. No SVA support: %d\n", rc); +- } else { +- set_bit(IDXD_FLAG_PASID_ENABLED, &idxd->flags); +- } +- } else { +- dev_warn(dev, "Unable to turn on SVA feature.\n"); +- } ++ if (iommu_dev_enable_feature(dev, IOMMU_DEV_FEAT_SVA)) ++ dev_warn(dev, "Unable to turn on user SVA feature.\n"); ++ else ++ set_bit(IDXD_FLAG_USER_PASID_ENABLED, &idxd->flags); ++ ++ if (idxd_enable_system_pasid(idxd)) ++ dev_warn(dev, "No in-kernel DMA with PASID.\n"); ++ else ++ set_bit(IDXD_FLAG_PASID_ENABLED, &idxd->flags); + } else if (!sva) { + dev_warn(dev, "User forced SVA off via module param.\n"); + } +@@ -561,7 +558,8 @@ static int idxd_probe(struct idxd_device + err: + if (device_pasid_enabled(idxd)) + idxd_disable_system_pasid(idxd); +- iommu_dev_disable_feature(dev, IOMMU_DEV_FEAT_SVA); ++ if (device_user_pasid_enabled(idxd)) ++ iommu_dev_disable_feature(dev, IOMMU_DEV_FEAT_SVA); + return rc; + } + +@@ -574,7 +572,8 @@ static void idxd_cleanup(struct idxd_dev + idxd_cleanup_internals(idxd); + if (device_pasid_enabled(idxd)) + idxd_disable_system_pasid(idxd); +- iommu_dev_disable_feature(dev, IOMMU_DEV_FEAT_SVA); ++ if (device_user_pasid_enabled(idxd)) ++ iommu_dev_disable_feature(dev, IOMMU_DEV_FEAT_SVA); + } + + static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +@@ -693,7 +692,8 @@ static void idxd_remove(struct pci_dev * + free_irq(irq_entry->vector, irq_entry); + pci_free_irq_vectors(pdev); + pci_iounmap(pdev, idxd->reg_base); +- iommu_dev_disable_feature(&pdev->dev, IOMMU_DEV_FEAT_SVA); ++ if (device_user_pasid_enabled(idxd)) ++ iommu_dev_disable_feature(&pdev->dev, IOMMU_DEV_FEAT_SVA); + pci_disable_device(pdev); + destroy_workqueue(idxd->wq); + perfmon_pmu_remove(idxd); +--- a/drivers/dma/idxd/sysfs.c ++++ b/drivers/dma/idxd/sysfs.c +@@ -588,7 +588,7 @@ static ssize_t wq_mode_store(struct devi + if (sysfs_streq(buf, "dedicated")) { + set_bit(WQ_FLAG_DEDICATED, &wq->flags); + wq->threshold = 0; +- } else if (sysfs_streq(buf, "shared") && device_swq_supported(idxd)) { ++ } else if (sysfs_streq(buf, "shared")) { + clear_bit(WQ_FLAG_DEDICATED, &wq->flags); + } else { + return -EINVAL; diff --git a/series.conf b/series.conf index 9917c1b..bbbbb17 100644 --- a/series.conf +++ b/series.conf @@ -13716,6 +13716,7 @@ patches.suse/dmaengine-idxd-update-IAA-definitions-for-user-heade.patch patches.suse/dmaengine-idxd-set-DMA_INTERRUPT-cap-bit.patch patches.suse/dmaengine-idxd-Fix-the-error-handling-path-in-idxd_c.patch + patches.suse/dmaengine-idxd-Separate-user-and-kernel-pasid-enabli.patch patches.suse/dmaengine-zynqmp_dma-In-struct-zynqmp_dma_chan-fix-d.patch patches.suse/dmaengine-idxd-add-missing-callback-function-to-supp.patch patches.suse/dmaengine-stm32-mdma-remove-GISR1-register.patch