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