summaryrefslogtreecommitdiffstats
path: root/drivers/dma/idxd/irq.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2020-08-07 12:41:36 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2020-08-07 12:41:36 -0700
commitce615f5c1f73537c8267035d58b3d0c70e19b8da (patch)
tree54b8e1d34536eed62d898e7d9e81779f6728d286 /drivers/dma/idxd/irq.c
parent81e11336d97e7a4c25a65c302ef2bf9cd9808ed4 (diff)
parent00043a2689232631f39ebbf6719d545b1d799086 (diff)
downloadlinux-ce615f5c1f73537c8267035d58b3d0c70e19b8da.tar.bz2
Merge tag 'dmaengine-5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine
Pull dmaengine updates from Vinod Koul: "Core: - Support out of order dma completion - Support for repeating transaction New controllers: - Support for Actions S700 DMA engine - Renesas R8A774E1, r8a7742 controller binding - New driver for Xilinx DPDMA controller Other: - Support of out of order dma completion in idxd driver - W=1 warning cleanup of subsystem - Updates to ti-k3-dma, dw, idxd drivers" * tag 'dmaengine-5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine: (68 commits) dmaengine: dw: Don't include unneeded header to platform data header dmaengine: Actions: Add support for S700 DMA engine dmaengine: Actions: get rid of bit fields from dma descriptor dt-bindings: dmaengine: convert Actions Semi Owl SoCs bindings to yaml dmaengine: idxd: add missing invalid flags field to completion dmaengine: dw: Initialize max_sg_burst capability dmaengine: dw: Introduce max burst length hw config dmaengine: dw: Initialize min and max burst DMA device capability dmaengine: dw: Set DMA device max segment size parameter dmaengine: dw: Take HC_LLP flag into account for noLLP auto-config dmaengine: Introduce DMA-device device_caps callback dmaengine: Introduce max SG burst capability dmaengine: Introduce min burst length capability dt-bindings: dma: dw: Add max burst transaction length property dt-bindings: dma: dw: Convert DW DMAC to DT binding dmaengine: ti: k3-udma: Query throughput level information from hardware dmaengine: ti: k3-udma: Use defines for capabilities register parsing dmaengine: xilinx: dpdma: Fix kerneldoc warning dmaengine: xilinx: dpdma: add missing kernel doc dmaengine: xilinx: dpdma: remove comparison of unsigned expression ...
Diffstat (limited to 'drivers/dma/idxd/irq.c')
-rw-r--r--drivers/dma/idxd/irq.c43
1 files changed, 19 insertions, 24 deletions
diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c
index 8a35f58da689..b5142556cc4e 100644
--- a/drivers/dma/idxd/irq.c
+++ b/drivers/dma/idxd/irq.c
@@ -23,16 +23,13 @@ void idxd_device_wqs_clear_state(struct idxd_device *idxd)
}
}
-static int idxd_restart(struct idxd_device *idxd)
+static void idxd_device_reinit(struct work_struct *work)
{
- int i, rc;
-
- lockdep_assert_held(&idxd->dev_lock);
-
- rc = __idxd_device_reset(idxd);
- if (rc < 0)
- goto out;
+ struct idxd_device *idxd = container_of(work, struct idxd_device, work);
+ struct device *dev = &idxd->pdev->dev;
+ int rc, i;
+ idxd_device_reset(idxd);
rc = idxd_device_config(idxd);
if (rc < 0)
goto out;
@@ -47,19 +44,16 @@ static int idxd_restart(struct idxd_device *idxd)
if (wq->state == IDXD_WQ_ENABLED) {
rc = idxd_wq_enable(wq);
if (rc < 0) {
- dev_warn(&idxd->pdev->dev,
- "Unable to re-enable wq %s\n",
+ dev_warn(dev, "Unable to re-enable wq %s\n",
dev_name(&wq->conf_dev));
}
}
}
- return 0;
+ return;
out:
idxd_device_wqs_clear_state(idxd);
- idxd->state = IDXD_DEV_HALTED;
- return rc;
}
irqreturn_t idxd_irq_handler(int vec, void *data)
@@ -78,7 +72,7 @@ irqreturn_t idxd_misc_thread(int vec, void *data)
struct device *dev = &idxd->pdev->dev;
union gensts_reg gensts;
u32 cause, val = 0;
- int i, rc;
+ int i;
bool err = false;
cause = ioread32(idxd->reg_base + IDXD_INTCAUSE_OFFSET);
@@ -117,8 +111,8 @@ irqreturn_t idxd_misc_thread(int vec, void *data)
}
if (cause & IDXD_INTC_CMD) {
- /* Driver does use command interrupts */
val |= IDXD_INTC_CMD;
+ complete(idxd->cmd_done);
}
if (cause & IDXD_INTC_OCCUPY) {
@@ -145,21 +139,24 @@ irqreturn_t idxd_misc_thread(int vec, void *data)
gensts.bits = ioread32(idxd->reg_base + IDXD_GENSTATS_OFFSET);
if (gensts.state == IDXD_DEVICE_STATE_HALT) {
- spin_lock_bh(&idxd->dev_lock);
+ idxd->state = IDXD_DEV_HALTED;
if (gensts.reset_type == IDXD_DEVICE_RESET_SOFTWARE) {
- rc = idxd_restart(idxd);
- if (rc < 0)
- dev_err(&idxd->pdev->dev,
- "idxd restart failed, device halt.");
+ /*
+ * If we need a software reset, we will throw the work
+ * on a system workqueue in order to allow interrupts
+ * for the device command completions.
+ */
+ INIT_WORK(&idxd->work, idxd_device_reinit);
+ queue_work(idxd->wq, &idxd->work);
} else {
+ spin_lock_bh(&idxd->dev_lock);
idxd_device_wqs_clear_state(idxd);
- idxd->state = IDXD_DEV_HALTED;
dev_err(&idxd->pdev->dev,
"idxd halted, need %s.\n",
gensts.reset_type == IDXD_DEVICE_RESET_FLR ?
"FLR" : "system reset");
+ spin_unlock_bh(&idxd->dev_lock);
}
- spin_unlock_bh(&idxd->dev_lock);
}
out:
@@ -264,8 +261,6 @@ irqreturn_t idxd_wq_thread(int irq, void *data)
processed = idxd_desc_process(irq_entry);
idxd_unmask_msix_vector(irq_entry->idxd, irq_entry->id);
- /* catch anything unprocessed after unmasking */
- processed += idxd_desc_process(irq_entry);
if (processed == 0)
return IRQ_NONE;