Skip to content

Commit 0c40bfb

Browse files
davejiangvinodkoul
authored andcommitted
dmaengine: idxd: make misc interrupt one shot
Current code continuously processes the interrupt as long as the hardware is setting the status bit. There's no reason to do that since the threaded handler will get called again if another interrupt is asserted. Also through testing, it has shown that if a misprogrammed (or malicious) agent can continuously submit descriptors with bad completion record and causes errors to be reported via the misc interrupt. Continuous processing by the thread can cause software hang watchdog to kick off since the thread isn't giving up the CPU. Reported-by: Sanjay Kumar <sanjay.k.kumar@intel.com> Tested-by: Tony Zhu <tony.zhu@intel.com> Signed-off-by: Dave Jiang <dave.jiang@intel.com> Co-developed-by: Fenghua Yu <fenghua.yu@intel.com> Signed-off-by: Fenghua Yu <fenghua.yu@intel.com> Link: https://lore.kernel.org/r/20230407203143.2189681-2-fenghua.yu@intel.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent c956612 commit 0c40bfb

1 file changed

Lines changed: 12 additions & 26 deletions

File tree

drivers/dma/idxd/irq.c

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -217,13 +217,22 @@ static void idxd_int_handle_revoke(struct work_struct *work)
217217
kfree(revoke);
218218
}
219219

220-
static int process_misc_interrupts(struct idxd_device *idxd, u32 cause)
220+
irqreturn_t idxd_misc_thread(int vec, void *data)
221221
{
222+
struct idxd_irq_entry *irq_entry = data;
223+
struct idxd_device *idxd = ie_to_idxd(irq_entry);
222224
struct device *dev = &idxd->pdev->dev;
223225
union gensts_reg gensts;
224226
u32 val = 0;
225227
int i;
226228
bool err = false;
229+
u32 cause;
230+
231+
cause = ioread32(idxd->reg_base + IDXD_INTCAUSE_OFFSET);
232+
if (!cause)
233+
return IRQ_NONE;
234+
235+
iowrite32(cause, idxd->reg_base + IDXD_INTCAUSE_OFFSET);
227236

228237
if (cause & IDXD_INTC_HALT_STATE)
229238
goto halt;
@@ -301,7 +310,7 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause)
301310
val);
302311

303312
if (!err)
304-
return 0;
313+
goto out;
305314

306315
halt:
307316
gensts.bits = ioread32(idxd->reg_base + IDXD_GENSTATS_OFFSET);
@@ -324,33 +333,10 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause)
324333
"idxd halted, need %s.\n",
325334
gensts.reset_type == IDXD_DEVICE_RESET_FLR ?
326335
"FLR" : "system reset");
327-
return -ENXIO;
328336
}
329337
}
330338

331-
return 0;
332-
}
333-
334-
irqreturn_t idxd_misc_thread(int vec, void *data)
335-
{
336-
struct idxd_irq_entry *irq_entry = data;
337-
struct idxd_device *idxd = ie_to_idxd(irq_entry);
338-
int rc;
339-
u32 cause;
340-
341-
cause = ioread32(idxd->reg_base + IDXD_INTCAUSE_OFFSET);
342-
if (cause)
343-
iowrite32(cause, idxd->reg_base + IDXD_INTCAUSE_OFFSET);
344-
345-
while (cause) {
346-
rc = process_misc_interrupts(idxd, cause);
347-
if (rc < 0)
348-
break;
349-
cause = ioread32(idxd->reg_base + IDXD_INTCAUSE_OFFSET);
350-
if (cause)
351-
iowrite32(cause, idxd->reg_base + IDXD_INTCAUSE_OFFSET);
352-
}
353-
339+
out:
354340
return IRQ_HANDLED;
355341
}
356342

0 commit comments

Comments
 (0)