dmaengine: idxd: track enabled workqueues in bitmap

Now that idxd_wq_disable_cleanup() sets the workqueue state to
IDXD_WQ_DISABLED, use a bitmap to track which workqueues have been
enabled. This will then be used to determine which workqueues
should be re-enabled when attempting a software reset to recover
from a device halt state.

Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Dave Jiang <dave.jiang@intel.com>
Cc: Vinod Koul <vkoul@kernel.org>
Signed-off-by: Jerry Snitselaar <jsnitsel@redhat.com>
Reviewed-by: Dave Jiang <dave.jiang@intel.com>
Link: https://lore.kernel.org/r/20220928154856.623545-3-jsnitsel@redhat.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
Jerry Snitselaar 2022-09-28 08:48:56 -07:00 committed by Vinod Koul
parent 8e527aac05
commit de5819b994
5 changed files with 14 additions and 2 deletions

View File

@ -196,6 +196,7 @@ int idxd_wq_enable(struct idxd_wq *wq)
} }
wq->state = IDXD_WQ_ENABLED; wq->state = IDXD_WQ_ENABLED;
set_bit(wq->id, idxd->wq_enable_map);
dev_dbg(dev, "WQ %d enabled\n", wq->id); dev_dbg(dev, "WQ %d enabled\n", wq->id);
return 0; return 0;
} }
@ -223,6 +224,7 @@ int idxd_wq_disable(struct idxd_wq *wq, bool reset_config)
if (reset_config) if (reset_config)
idxd_wq_disable_cleanup(wq); idxd_wq_disable_cleanup(wq);
clear_bit(wq->id, idxd->wq_enable_map);
wq->state = IDXD_WQ_DISABLED; wq->state = IDXD_WQ_DISABLED;
dev_dbg(dev, "WQ %d disabled\n", wq->id); dev_dbg(dev, "WQ %d disabled\n", wq->id);
return 0; return 0;

View File

@ -11,6 +11,7 @@
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/ioasid.h> #include <linux/ioasid.h>
#include <linux/bitmap.h>
#include <linux/perf_event.h> #include <linux/perf_event.h>
#include <uapi/linux/idxd.h> #include <uapi/linux/idxd.h>
#include "registers.h" #include "registers.h"
@ -299,6 +300,7 @@ struct idxd_device {
int rdbuf_limit; int rdbuf_limit;
int nr_rdbufs; /* non-reserved read buffers */ int nr_rdbufs; /* non-reserved read buffers */
unsigned int wqcfg_size; unsigned int wqcfg_size;
unsigned long *wq_enable_map;
union sw_err_reg sw_err; union sw_err_reg sw_err;
wait_queue_head_t cmd_waitq; wait_queue_head_t cmd_waitq;

View File

@ -151,6 +151,12 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
if (!idxd->wqs) if (!idxd->wqs)
return -ENOMEM; return -ENOMEM;
idxd->wq_enable_map = bitmap_zalloc_node(idxd->max_wqs, GFP_KERNEL, dev_to_node(dev));
if (!idxd->wq_enable_map) {
kfree(idxd->wqs);
return -ENOMEM;
}
for (i = 0; i < idxd->max_wqs; i++) { for (i = 0; i < idxd->max_wqs; i++) {
wq = kzalloc_node(sizeof(*wq), GFP_KERNEL, dev_to_node(dev)); wq = kzalloc_node(sizeof(*wq), GFP_KERNEL, dev_to_node(dev));
if (!wq) { if (!wq) {

View File

@ -49,11 +49,12 @@ static void idxd_device_reinit(struct work_struct *work)
goto out; goto out;
for (i = 0; i < idxd->max_wqs; i++) { for (i = 0; i < idxd->max_wqs; i++) {
if (test_bit(i, idxd->wq_enable_map)) {
struct idxd_wq *wq = idxd->wqs[i]; struct idxd_wq *wq = idxd->wqs[i];
if (wq->state == IDXD_WQ_ENABLED) {
rc = idxd_wq_enable(wq); rc = idxd_wq_enable(wq);
if (rc < 0) { if (rc < 0) {
clear_bit(i, idxd->wq_enable_map);
dev_warn(dev, "Unable to re-enable wq %s\n", dev_warn(dev, "Unable to re-enable wq %s\n",
dev_name(wq_confdev(wq))); dev_name(wq_confdev(wq)));
} }

View File

@ -1405,6 +1405,7 @@ static void idxd_conf_device_release(struct device *dev)
struct idxd_device *idxd = confdev_to_idxd(dev); struct idxd_device *idxd = confdev_to_idxd(dev);
kfree(idxd->groups); kfree(idxd->groups);
bitmap_free(idxd->wq_enable_map);
kfree(idxd->wqs); kfree(idxd->wqs);
kfree(idxd->engines); kfree(idxd->engines);
ida_free(&idxd_ida, idxd->id); ida_free(&idxd_ida, idxd->id);