Skip to content

Commit

Permalink
dmaengine: idxd: fix setting up priv mode for dwq
Browse files Browse the repository at this point in the history
DSA spec says WQ priv bit is 0 if the Privileged Mode Enable field of the
PCI Express PASID capability is 0 and pasid is enabled. Make sure that the
WQCFG priv field is set correctly according to usage type. Reject config if
setting up kernel WQ type and no support. Also add the correct priv setup
for a descriptor.

Fixes: 484f910 ("dmaengine: idxd: fix wq config registers offset programming")
Cc: Ramesh Thomas <ramesh.thomas@intel.com>
Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Link: https://lore.kernel.org/r/162939084657.903168.14160019185148244596.stgit@djiang5-desk3.ch.intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
  • Loading branch information
Dave Jiang authored and Vinod Koul committed Aug 29, 2021
1 parent aac6c0f commit d807132
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 2 deletions.
1 change: 1 addition & 0 deletions drivers/dma/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ config INTEL_IDXD
tristate "Intel Data Accelerators support"
depends on PCI && X86_64 && !UML
depends on PCI_MSI
depends on PCI_PASID
depends on SBITMAP
select DMA_ENGINE
help
Expand Down
29 changes: 28 additions & 1 deletion drivers/dma/idxd/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,15 @@ static int idxd_groups_config_write(struct idxd_device *idxd)
return 0;
}

static bool idxd_device_pasid_priv_enabled(struct idxd_device *idxd)
{
struct pci_dev *pdev = idxd->pdev;

if (pdev->pasid_enabled && (pdev->pasid_features & PCI_PASID_CAP_PRIV))
return true;
return false;
}

static int idxd_wq_config_write(struct idxd_wq *wq)
{
struct idxd_device *idxd = wq->idxd;
Expand Down Expand Up @@ -850,7 +859,6 @@ static int idxd_wq_config_write(struct idxd_wq *wq)
wq->wqcfg->wq_thresh = wq->threshold;

/* byte 8-11 */
wq->wqcfg->priv = !!(wq->type == IDXD_WQT_KERNEL);
if (wq_dedicated(wq))
wq->wqcfg->mode = 1;

Expand All @@ -860,6 +868,25 @@ static int idxd_wq_config_write(struct idxd_wq *wq)
wq->wqcfg->pasid = idxd->pasid;
}

/*
* Here the priv bit is set depending on the WQ type. priv = 1 if the
* WQ type is kernel to indicate privileged access. This setting only
* matters for dedicated WQ. According to the DSA spec:
* If the WQ is in dedicated mode, WQ PASID Enable is 1, and the
* Privileged Mode Enable field of the PCI Express PASID capability
* is 0, this field must be 0.
*
* In the case of a dedicated kernel WQ that is not able to support
* the PASID cap, then the configuration will be rejected.
*/
wq->wqcfg->priv = !!(wq->type == IDXD_WQT_KERNEL);
if (wq_dedicated(wq) && wq->wqcfg->pasid_en &&
!idxd_device_pasid_priv_enabled(idxd) &&
wq->type == IDXD_WQT_KERNEL) {
idxd->cmd_status = IDXD_SCMD_WQ_NO_PRIV;
return -EOPNOTSUPP;
}

wq->wqcfg->priority = wq->priority;

if (idxd->hw.gen_cap.block_on_fault &&
Expand Down
6 changes: 5 additions & 1 deletion drivers/dma/idxd/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ static inline void idxd_prep_desc_common(struct idxd_wq *wq,
hw->src_addr = addr_f1;
hw->dst_addr = addr_f2;
hw->xfer_size = len;
hw->priv = !!(wq->type == IDXD_WQT_KERNEL);
/*
* For dedicated WQ, this field is ignored and HW will use the WQCFG.priv
* field instead. This field should be set to 1 for kernel descriptors.
*/
hw->priv = 1;
hw->completion_addr = compl;
}

Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/idxd.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ enum idxd_scmd_stat {
IDXD_SCMD_WQ_NO_SWQ_SUPPORT = 0x800c0000,
IDXD_SCMD_WQ_NONE_CONFIGURED = 0x800d0000,
IDXD_SCMD_WQ_NO_SIZE = 0x800e0000,
IDXD_SCMD_WQ_NO_PRIV = 0x800f0000,
};

#define IDXD_SCMD_SOFTERR_MASK 0x80000000
Expand Down

0 comments on commit d807132

Please sign in to comment.