Commit 125d1037 authored by Dave Jiang's avatar Dave Jiang Committed by Vinod Koul

dmanegine: idxd: add software command status

Enabling device and wq returns standard errno and that does not provide
enough details to indicate what exactly failed. The hardware command status
is only 8bits. Expand the command status to 32bits and use the upper 16
bits to define software errors to provide more details on the exact
failure. Bit 31 will be used to indicate the error is software set as the
driver is using some of the spec defined hardware error as well.

Cc: Ramesh Thomas <ramesh.thomas@intel.com>
Signed-off-by: default avatarDave Jiang <dave.jiang@intel.com>
Link: https://lore.kernel.org/r/162681373579.1968485.5891788397526827892.stgit@djiang5-desk3.ch.intel.comSigned-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent a9c17152
...@@ -128,6 +128,8 @@ Date: Aug 28, 2020 ...@@ -128,6 +128,8 @@ Date: Aug 28, 2020
KernelVersion: 5.10.0 KernelVersion: 5.10.0
Contact: dmaengine@vger.kernel.org Contact: dmaengine@vger.kernel.org
Description: The last executed device administrative command's status/error. Description: The last executed device administrative command's status/error.
Also last configuration error overloaded.
Writing to it will clear the status.
What: /sys/bus/dsa/devices/wq<m>.<n>/block_on_fault What: /sys/bus/dsa/devices/wq<m>.<n>/block_on_fault
Date: Oct 27, 2020 Date: Oct 27, 2020
......
...@@ -320,9 +320,12 @@ static int idxd_user_drv_probe(struct idxd_dev *idxd_dev) ...@@ -320,9 +320,12 @@ static int idxd_user_drv_probe(struct idxd_dev *idxd_dev)
goto err; goto err;
rc = idxd_wq_add_cdev(wq); rc = idxd_wq_add_cdev(wq);
if (rc < 0) if (rc < 0) {
idxd->cmd_status = IDXD_SCMD_CDEV_ERR;
goto err_cdev; goto err_cdev;
}
idxd->cmd_status = 0;
mutex_unlock(&wq->wq_lock); mutex_unlock(&wq->wq_lock);
return 0; return 0;
......
...@@ -840,6 +840,7 @@ static int idxd_wq_config_write(struct idxd_wq *wq) ...@@ -840,6 +840,7 @@ static int idxd_wq_config_write(struct idxd_wq *wq)
wq->wqcfg->wq_size = wq->size; wq->wqcfg->wq_size = wq->size;
if (wq->size == 0) { if (wq->size == 0) {
idxd->cmd_status = IDXD_SCMD_WQ_NO_SIZE;
dev_warn(dev, "Incorrect work queue size: 0\n"); dev_warn(dev, "Incorrect work queue size: 0\n");
return -EINVAL; return -EINVAL;
} }
...@@ -975,6 +976,7 @@ static int idxd_wqs_setup(struct idxd_device *idxd) ...@@ -975,6 +976,7 @@ static int idxd_wqs_setup(struct idxd_device *idxd)
continue; continue;
if (wq_shared(wq) && !device_swq_supported(idxd)) { if (wq_shared(wq) && !device_swq_supported(idxd)) {
idxd->cmd_status = IDXD_SCMD_WQ_NO_SWQ_SUPPORT;
dev_warn(dev, "No shared wq support but configured.\n"); dev_warn(dev, "No shared wq support but configured.\n");
return -EINVAL; return -EINVAL;
} }
...@@ -983,8 +985,10 @@ static int idxd_wqs_setup(struct idxd_device *idxd) ...@@ -983,8 +985,10 @@ static int idxd_wqs_setup(struct idxd_device *idxd)
configured++; configured++;
} }
if (configured == 0) if (configured == 0) {
idxd->cmd_status = IDXD_SCMD_WQ_NONE_CONFIGURED;
return -EINVAL; return -EINVAL;
}
return 0; return 0;
} }
...@@ -1140,21 +1144,26 @@ int __drv_enable_wq(struct idxd_wq *wq) ...@@ -1140,21 +1144,26 @@ int __drv_enable_wq(struct idxd_wq *wq)
lockdep_assert_held(&wq->wq_lock); lockdep_assert_held(&wq->wq_lock);
if (idxd->state != IDXD_DEV_ENABLED) if (idxd->state != IDXD_DEV_ENABLED) {
idxd->cmd_status = IDXD_SCMD_DEV_NOT_ENABLED;
goto err; goto err;
}
if (wq->state != IDXD_WQ_DISABLED) { if (wq->state != IDXD_WQ_DISABLED) {
dev_dbg(dev, "wq %d already enabled.\n", wq->id); dev_dbg(dev, "wq %d already enabled.\n", wq->id);
idxd->cmd_status = IDXD_SCMD_WQ_ENABLED;
rc = -EBUSY; rc = -EBUSY;
goto err; goto err;
} }
if (!wq->group) { if (!wq->group) {
dev_dbg(dev, "wq %d not attached to group.\n", wq->id); dev_dbg(dev, "wq %d not attached to group.\n", wq->id);
idxd->cmd_status = IDXD_SCMD_WQ_NO_GRP;
goto err; goto err;
} }
if (strlen(wq->name) == 0) { if (strlen(wq->name) == 0) {
idxd->cmd_status = IDXD_SCMD_WQ_NO_NAME;
dev_dbg(dev, "wq %d name not set.\n", wq->id); dev_dbg(dev, "wq %d name not set.\n", wq->id);
goto err; goto err;
} }
...@@ -1162,6 +1171,7 @@ int __drv_enable_wq(struct idxd_wq *wq) ...@@ -1162,6 +1171,7 @@ int __drv_enable_wq(struct idxd_wq *wq)
/* Shared WQ checks */ /* Shared WQ checks */
if (wq_shared(wq)) { if (wq_shared(wq)) {
if (!device_swq_supported(idxd)) { if (!device_swq_supported(idxd)) {
idxd->cmd_status = IDXD_SCMD_WQ_NO_SVM;
dev_dbg(dev, "PASID not enabled and shared wq.\n"); dev_dbg(dev, "PASID not enabled and shared wq.\n");
goto err; goto err;
} }
...@@ -1174,6 +1184,7 @@ int __drv_enable_wq(struct idxd_wq *wq) ...@@ -1174,6 +1184,7 @@ int __drv_enable_wq(struct idxd_wq *wq)
* threshold via sysfs. * threshold via sysfs.
*/ */
if (wq->threshold == 0) { if (wq->threshold == 0) {
idxd->cmd_status = IDXD_SCMD_WQ_NO_THRESH;
dev_dbg(dev, "Shared wq and threshold 0.\n"); dev_dbg(dev, "Shared wq and threshold 0.\n");
goto err; goto err;
} }
...@@ -1197,6 +1208,7 @@ int __drv_enable_wq(struct idxd_wq *wq) ...@@ -1197,6 +1208,7 @@ int __drv_enable_wq(struct idxd_wq *wq)
rc = idxd_wq_map_portal(wq); rc = idxd_wq_map_portal(wq);
if (rc < 0) { if (rc < 0) {
idxd->cmd_status = IDXD_SCMD_WQ_PORTAL_ERR;
dev_dbg(dev, "wq %d portal mapping failed: %d\n", wq->id, rc); dev_dbg(dev, "wq %d portal mapping failed: %d\n", wq->id, rc);
goto err_map_portal; goto err_map_portal;
} }
...@@ -1259,8 +1271,10 @@ int idxd_device_drv_probe(struct idxd_dev *idxd_dev) ...@@ -1259,8 +1271,10 @@ int idxd_device_drv_probe(struct idxd_dev *idxd_dev)
* enabled state, then the device was altered outside of driver's control. * enabled state, then the device was altered outside of driver's control.
* If the state is in halted state, then we don't want to proceed. * If the state is in halted state, then we don't want to proceed.
*/ */
if (idxd->state != IDXD_DEV_DISABLED) if (idxd->state != IDXD_DEV_DISABLED) {
idxd->cmd_status = IDXD_SCMD_DEV_ENABLED;
return -ENXIO; return -ENXIO;
}
/* Device configuration */ /* Device configuration */
spin_lock_irqsave(&idxd->dev_lock, flags); spin_lock_irqsave(&idxd->dev_lock, flags);
...@@ -1279,9 +1293,11 @@ int idxd_device_drv_probe(struct idxd_dev *idxd_dev) ...@@ -1279,9 +1293,11 @@ int idxd_device_drv_probe(struct idxd_dev *idxd_dev)
rc = idxd_register_dma_device(idxd); rc = idxd_register_dma_device(idxd);
if (rc < 0) { if (rc < 0) {
idxd_device_disable(idxd); idxd_device_disable(idxd);
idxd->cmd_status = IDXD_SCMD_DEV_DMA_ERR;
return rc; return rc;
} }
idxd->cmd_status = 0;
return 0; return 0;
} }
......
...@@ -284,22 +284,26 @@ static int idxd_dmaengine_drv_probe(struct idxd_dev *idxd_dev) ...@@ -284,22 +284,26 @@ static int idxd_dmaengine_drv_probe(struct idxd_dev *idxd_dev)
rc = idxd_wq_alloc_resources(wq); rc = idxd_wq_alloc_resources(wq);
if (rc < 0) { if (rc < 0) {
idxd->cmd_status = IDXD_SCMD_WQ_RES_ALLOC_ERR;
dev_dbg(dev, "WQ resource alloc failed\n"); dev_dbg(dev, "WQ resource alloc failed\n");
goto err_res_alloc; goto err_res_alloc;
} }
rc = idxd_wq_init_percpu_ref(wq); rc = idxd_wq_init_percpu_ref(wq);
if (rc < 0) { if (rc < 0) {
idxd->cmd_status = IDXD_SCMD_PERCPU_ERR;
dev_dbg(dev, "percpu_ref setup failed\n"); dev_dbg(dev, "percpu_ref setup failed\n");
goto err_ref; goto err_ref;
} }
rc = idxd_register_dma_channel(wq); rc = idxd_register_dma_channel(wq);
if (rc < 0) { if (rc < 0) {
idxd->cmd_status = IDXD_SCMD_DMA_CHAN_ERR;
dev_dbg(dev, "Failed to register dma channel\n"); dev_dbg(dev, "Failed to register dma channel\n");
goto err_dma; goto err_dma;
} }
idxd->cmd_status = 0;
mutex_unlock(&wq->wq_lock); mutex_unlock(&wq->wq_lock);
return 0; return 0;
......
...@@ -252,7 +252,7 @@ struct idxd_device { ...@@ -252,7 +252,7 @@ struct idxd_device {
unsigned long flags; unsigned long flags;
int id; int id;
int major; int major;
u8 cmd_status; u32 cmd_status;
struct pci_dev *pdev; struct pci_dev *pdev;
void __iomem *reg_base; void __iomem *reg_base;
......
...@@ -1217,7 +1217,16 @@ static ssize_t cmd_status_show(struct device *dev, ...@@ -1217,7 +1217,16 @@ static ssize_t cmd_status_show(struct device *dev,
return sysfs_emit(buf, "%#x\n", idxd->cmd_status); return sysfs_emit(buf, "%#x\n", idxd->cmd_status);
} }
static DEVICE_ATTR_RO(cmd_status);
static ssize_t cmd_status_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct idxd_device *idxd = confdev_to_idxd(dev);
idxd->cmd_status = 0;
return count;
}
static DEVICE_ATTR_RW(cmd_status);
static struct attribute *idxd_device_attributes[] = { static struct attribute *idxd_device_attributes[] = {
&dev_attr_version.attr, &dev_attr_version.attr,
......
...@@ -9,6 +9,29 @@ ...@@ -9,6 +9,29 @@
#include <stdint.h> #include <stdint.h>
#endif #endif
/* Driver command error status */
enum idxd_scmd_stat {
IDXD_SCMD_DEV_ENABLED = 0x80000010,
IDXD_SCMD_DEV_NOT_ENABLED = 0x80000020,
IDXD_SCMD_WQ_ENABLED = 0x80000021,
IDXD_SCMD_DEV_DMA_ERR = 0x80020000,
IDXD_SCMD_WQ_NO_GRP = 0x80030000,
IDXD_SCMD_WQ_NO_NAME = 0x80040000,
IDXD_SCMD_WQ_NO_SVM = 0x80050000,
IDXD_SCMD_WQ_NO_THRESH = 0x80060000,
IDXD_SCMD_WQ_PORTAL_ERR = 0x80070000,
IDXD_SCMD_WQ_RES_ALLOC_ERR = 0x80080000,
IDXD_SCMD_PERCPU_ERR = 0x80090000,
IDXD_SCMD_DMA_CHAN_ERR = 0x800a0000,
IDXD_SCMD_CDEV_ERR = 0x800b0000,
IDXD_SCMD_WQ_NO_SWQ_SUPPORT = 0x800c0000,
IDXD_SCMD_WQ_NONE_CONFIGURED = 0x800d0000,
IDXD_SCMD_WQ_NO_SIZE = 0x800e0000,
};
#define IDXD_SCMD_SOFTERR_MASK 0x80000000
#define IDXD_SCMD_SOFTERR_SHIFT 16
/* Descriptor flags */ /* Descriptor flags */
#define IDXD_OP_FLAG_FENCE 0x0001 #define IDXD_OP_FLAG_FENCE 0x0001
#define IDXD_OP_FLAG_BOF 0x0002 #define IDXD_OP_FLAG_BOF 0x0002
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment