Re: [PATCH v6 3/5] dmaengine: idxd: Add shared workqueue support

2020-10-04 Thread Vinod Koul
On 24-09-20, 11:00, Dave Jiang wrote:

> @@ -1154,6 +1268,8 @@ static struct attribute *idxd_wq_attributes[] = {
>   _attr_wq_mode.attr,
>   _attr_wq_size.attr,
>   _attr_wq_priority.attr,
> + _attr_wq_block_on_fault.attr,
> + _attr_wq_threshold.attr,
>   _attr_wq_type.attr,
>   _attr_wq_name.attr,
>   _attr_wq_cdev_minor.attr,
> @@ -1305,6 +1421,16 @@ static ssize_t clients_show(struct device *dev,
>  }
>  static DEVICE_ATTR_RO(clients);
>  
> +static ssize_t pasid_enabled_show(struct device *dev,
> +   struct device_attribute *attr, char *buf)
> +{
> + struct idxd_device *idxd =
> + container_of(dev, struct idxd_device, conf_dev);
> +
> + return sprintf(buf, "%u\n", device_pasid_enabled(idxd));
> +}
> +static DEVICE_ATTR_RO(pasid_enabled);
> +
>  static ssize_t state_show(struct device *dev,
> struct device_attribute *attr, char *buf)
>  {
> @@ -1424,6 +1550,7 @@ static struct attribute *idxd_device_attributes[] = {
>   _attr_gen_cap.attr,
>   _attr_configurable.attr,
>   _attr_clients.attr,
> + _attr_pasid_enabled.attr,

No Documentation again for these new files! Please add them as well

-- 
~Vinod


[PATCH v6 3/5] dmaengine: idxd: Add shared workqueue support

2020-09-24 Thread Dave Jiang
Add shared workqueue support that includes the support of Shared Virtual
memory (SVM) or in similar terms On Demand Paging (ODP). The shared
workqueue uses the enqcmds command in kernel and will respond with retry if
the workqueue is full. Shared workqueue only works when there is PASID
support from the IOMMU.

Signed-off-by: Dave Jiang 
Reviewed-by: Tony Luck 
Reviewed-by: Dan Williams 
---
 drivers/dma/Kconfig  |  10 +++
 drivers/dma/idxd/cdev.c  |  49 +-
 drivers/dma/idxd/device.c|  91 ++---
 drivers/dma/idxd/dma.c   |   9 ---
 drivers/dma/idxd/idxd.h  |  28 +++-
 drivers/dma/idxd/init.c  |  91 +++--
 drivers/dma/idxd/registers.h |  14 
 drivers/dma/idxd/submit.c|  35 --
 drivers/dma/idxd/sysfs.c | 127 +++
 9 files changed, 410 insertions(+), 44 deletions(-)

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index 518a1437862a..6a908785a5f7 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -296,6 +296,16 @@ config INTEL_IDXD
 
  If unsure, say N.
 
+# Config symbol that collects all the dependencies that's necessary to
+# support shared virtual memory for the devices supported by idxd.
+config INTEL_IDXD_SVM
+   bool "Accelerator Shared Virtual Memory Support"
+   depends on INTEL_IDXD
+   depends on INTEL_IOMMU_SVM
+   depends on PCI_PRI
+   depends on PCI_PASID
+   depends on PCI_IOV
+
 config INTEL_IOATDMA
tristate "Intel I/OAT DMA support"
depends on PCI && X86_64
diff --git a/drivers/dma/idxd/cdev.c b/drivers/dma/idxd/cdev.c
index c3976156db2f..010b820d8f74 100644
--- a/drivers/dma/idxd/cdev.c
+++ b/drivers/dma/idxd/cdev.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include "registers.h"
 #include "idxd.h"
@@ -32,7 +33,9 @@ static struct idxd_cdev_context ictx[IDXD_TYPE_MAX] = {
 struct idxd_user_context {
struct idxd_wq *wq;
struct task_struct *task;
+   unsigned int pasid;
unsigned int flags;
+   struct iommu_sva *sva;
 };
 
 enum idxd_cdev_cleanup {
@@ -75,6 +78,8 @@ static int idxd_cdev_open(struct inode *inode, struct file 
*filp)
struct idxd_wq *wq;
struct device *dev;
int rc = 0;
+   struct iommu_sva *sva;
+   unsigned int pasid;
 
wq = inode_wq(inode);
idxd = wq->idxd;
@@ -95,6 +100,34 @@ static int idxd_cdev_open(struct inode *inode, struct file 
*filp)
 
ctx->wq = wq;
filp->private_data = ctx;
+
+   if (device_pasid_enabled(idxd)) {
+   sva = iommu_sva_bind_device(dev, current->mm, NULL);
+   if (IS_ERR(sva)) {
+   rc = PTR_ERR(sva);
+   dev_err(dev, "pasid allocation failed: %d\n", rc);
+   goto failed;
+   }
+
+   pasid = iommu_sva_get_pasid(sva);
+   if (pasid == IOMMU_PASID_INVALID) {
+   iommu_sva_unbind_device(sva);
+   goto failed;
+   }
+
+   ctx->sva = sva;
+   ctx->pasid = pasid;
+
+   if (wq_dedicated(wq)) {
+   rc = idxd_wq_set_pasid(wq, pasid);
+   if (rc < 0) {
+   iommu_sva_unbind_device(sva);
+   dev_err(dev, "wq set pasid failed: %d\n", rc);
+   goto failed;
+   }
+   }
+   }
+
idxd_wq_get(wq);
mutex_unlock(>wq_lock);
return 0;
@@ -111,13 +144,27 @@ static int idxd_cdev_release(struct inode *node, struct 
file *filep)
struct idxd_wq *wq = ctx->wq;
struct idxd_device *idxd = wq->idxd;
struct device *dev = >pdev->dev;
+   int rc;
 
dev_dbg(dev, "%s called\n", __func__);
filep->private_data = NULL;
 
/* Wait for in-flight operations to complete. */
-   idxd_wq_drain(wq);
+   if (wq_shared(wq)) {
+   idxd_device_drain_pasid(idxd, ctx->pasid);
+   } else {
+   if (device_pasid_enabled(idxd)) {
+   /* The wq disable in the disable pasid function will 
drain the wq */
+   rc = idxd_wq_disable_pasid(wq);
+   if (rc < 0)
+   dev_err(dev, "wq disable pasid failed.\n");
+   } else {
+   idxd_wq_drain(wq);
+   }
+   }
 
+   if (ctx->sva)
+   iommu_sva_unbind_device(ctx->sva);
kfree(ctx);
mutex_lock(>wq_lock);
idxd_wq_put(wq);
diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c
index 200b9109cacf..3c6c6df9d2e8 100644
--- a/drivers/dma/idxd/device.c
+++ b/drivers/dma/idxd/device.c
@@ -273,10 +273,9 @@ int idxd_wq_map_portal(struct idxd_wq *wq)
start = pci_resource_start(pdev, IDXD_WQ_BAR);