From: sashiko-bot@kernel.org
To: "Daniel Byrne" <daniel1.byrne@intel.com>
Cc: dmaengine@vger.kernel.org, vkoul@kernel.org, Frank.Li@kernel.org
Subject: Re: [PATCH 12/17] dmaengine: idxd: hold device commands off while the reset re-creates its interrupts
Date: Mon, 19 Oct 2026 18:19:35 +0000 [thread overview]
Message-ID: <sashiko-outbox-178068@kernel.org> (raw)
In-Reply-To: <20261019150630.4026341-13-daniel1.byrne@intel.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] dmaengine: idxd: idxd_cmd_reset_state() clears hold in idxd_cmd_hold()
- [Medium] dmaengine: idxd: idxd_cmd_hold() skips hold when IDXD_FLAG_CMD_TIMEDOUT is set
--
commit adf023de4cde0518acad5bf473d3a62f589687fb
Author: Daniel Byrne <daniel1.byrne@intel.com>
dmaengine: idxd: hold device commands off while the reset re-creates its interrupts
This commit introduces idxd_cmd_hold() and idxd_cmd_unhold() to wait for
any running device command and hold IDXD_FLAG_CMD_RUNNING across the
interrupt teardown and re-setup window in idxd_pci_probe_alloc() during
reset recovery.
> diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c
> index d3b95593a6867..222c201669bdd 100644
> --- a/drivers/dma/idxd/device.c
> +++ b/drivers/dma/idxd/device.c
> @@ -724,6 +724,50 @@ void idxd_cmd_reset_state(struct idxd_device *idxd)
> spin_unlock_irqrestore(&idxd->cmd_lock, flags);
> }
>
> +/*
> + * Hold device commands off while the re-probe after a reset frees the
> + * interrupts and requests them again. A command whose completion
> + * interrupt comes while the misc vector is gone is never completed, and
> + * its owner would time out and fence the device that was just reset.
> + * The running command, if any, is waited for first: its owner gives up
> + * within its timeout, and the misc vector still takes its interrupt.
> + * RUNNING is then held without an owner, and new commands wait for it
> + * as for any running command. Returns false, holding nothing, when a
> + * command timed out, since commands then fail fast anyway.
> + */
> +bool idxd_cmd_hold(struct idxd_device *idxd, u32 *seq)
> +{
> + bool held = false;
> +
> + spin_lock_irq(&idxd->cmd_lock);
> + wait_event_lock_irq(idxd->cmd_waitq,
> + !test_bit(IDXD_FLAG_CMD_RUNNING, &idxd->flags) ||
> + test_bit(IDXD_FLAG_CMD_TIMEDOUT, &idxd->flags),
> + idxd->cmd_lock);
> + if (!test_bit(IDXD_FLAG_CMD_RUNNING, &idxd->flags)) {
> + __set_bit(IDXD_FLAG_CMD_RUNNING, &idxd->flags);
> + *seq = ++idxd->cmd_seq;
> + held = true;
> + }
[Severity: Medium]
What happens in idxd_cmd_hold() if IDXD_FLAG_CMD_TIMEDOUT is set when
wait_event_lock_irq() returns?
When a command times out in idxd_cmd_exec(), IDXD_FLAG_CMD_RUNNING remains
set alongside IDXD_FLAG_CMD_TIMEDOUT. Because IDXD_FLAG_CMD_RUNNING is still
set, idxd_cmd_hold() skips setting held = true and returns false, and
idxd_pci_probe_alloc() proceeds to tear down and re-create interrupts
without a hold.
In idxd_cleanup_interrupts(), idxd_mask_error_interrupts() only masks error
interrupts in GENCTRL and does not mask IDXD_INTC_CMD. If a late command
completion interrupt arrives in idxd_misc_thread() before free_irq()
finishes (or if idxd_cmd_reset_state() runs concurrently):
drivers/dma/idxd/irq.c:idxd_misc_thread() {
...
} else if (test_bit(IDXD_FLAG_CMD_TIMEDOUT, &idxd->flags)) {
__clear_bit(IDXD_FLAG_CMD_RUNNING, &idxd->flags);
clear_bit(IDXD_FLAG_CMD_TIMEDOUT, &idxd->flags);
wake_up(&idxd->cmd_waitq);
dev_warn(dev, "a timed-out device command completed late\n");
}
...
}
Wouldn't this clear both IDXD_FLAG_CMD_RUNNING and IDXD_FLAG_CMD_TIMEDOUT
and wake idxd->cmd_waitq while the MSI-X vectors and misc interrupt are
still being torn down and re-allocated, allowing waiting or newly issued
commands to be submitted while interrupts are absent?
> + spin_unlock_irq(&idxd->cmd_lock);
> + return held;
> +}
> +
> +/*
> + * End a hold taken by idxd_cmd_hold(). A halt's recovery may have
> + * forgotten the hold meanwhile and let another command run, which then
> + * has an owner or a newer sequence number, and its state is left alone.
> + */
> +void idxd_cmd_unhold(struct idxd_device *idxd, u32 seq)
> +{
> + spin_lock_irq(&idxd->cmd_lock);
> + if (idxd->cmd_seq == seq && !idxd->cmd_done) {
> + __clear_bit(IDXD_FLAG_CMD_RUNNING, &idxd->flags);
> + wake_up(&idxd->cmd_waitq);
> + }
> + spin_unlock_irq(&idxd->cmd_lock);
> +}
[Severity: High]
If a concurrent halt recovery in idxd_device_reinit() forgets the hold
while idxd_pci_probe_alloc() is between idxd_cleanup_interrupts() and
idxd_setup_interrupts(), won't the command started after
idxd_cmd_reset_state() still lose its completion interrupt and time out?
Specifically, idxd_cmd_hold() overloads IDXD_FLAG_CMD_RUNNING to block
new commands, while idxd_cmd_reset_state() unconditionally clears it:
drivers/dma/idxd/device.c:idxd_cmd_reset_state() {
...
__clear_bit(IDXD_FLAG_CMD_RUNNING, &idxd->flags);
clear_bit(IDXD_FLAG_CMD_TIMEDOUT, &idxd->flags);
wake_up(&idxd->cmd_waitq);
...
}
And idxd_device_reinit() immediately issues a reset command right after
resetting the command state:
drivers/dma/idxd/irq.c:idxd_device_reinit() {
...
idxd_cmd_reset_state(idxd);
rc = idxd_device_reset(idxd);
...
}
If idxd_device_reinit() runs while the misc interrupt and MSI-X vectors
are freed during the reset re-probe in idxd_pci_probe_alloc(),
idxd_cmd_reset_state() clears IDXD_FLAG_CMD_RUNNING and wakes
idxd->cmd_waitq. Because pci_restore_state() in idxd_reset_done() has
already cleared the hardware halt state, idxd_device_reset() ->
idxd_cmd_exec() (along with any woken waiters) will submit a command while
the misc interrupt is torn down.
Although idxd_cmd_unhold() avoids clobbering the new command's state when
idxd->cmd_seq != seq, hasn't that command already been submitted while
interrupts were absent, causing it to lose its completion interrupt, time
out after 30 seconds, and fence the device?
[ ... ]
> diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c
> index a037a6e763622..312b4670b3e82 100644
> --- a/drivers/dma/idxd/init.c
> +++ b/drivers/dma/idxd/init.c
> @@ -1212,6 +1212,14 @@ int idxd_pci_probe_alloc(struct idxd_device *idxd, struct pci_dev *pdev,
> }
>
> if (!alloc_idxd) {
> + bool held;
> + u32 seq;
> +
> + /*
> + * Commands complete through the misc interrupt, which is
> + * gone until it is requested again.
> + */
> + held = idxd_cmd_hold(idxd, &seq);
> /* Release interrupts in the IDXD device. */
> idxd_cleanup_interrupts(idxd);
>
> @@ -1219,6 +1227,8 @@ int idxd_pci_probe_alloc(struct idxd_device *idxd, struct pci_dev *pdev,
> rc = idxd_setup_interrupts(idxd);
> if (rc)
> dev_warn(dev, "IDXD interrupts failed to setup\n");
> + if (held)
> + idxd_cmd_unhold(idxd, seq);
> }
>
> dev_info(&pdev->dev, "Intel(R) Accelerator Device (v%x)\n",
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261019150630.4026341-1-daniel1.byrne@intel.com?part=12
next prev parent reply other threads:[~2026-10-19 18:19 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-19 15:06 [PATCH 00/17] [PATCH 00/17] dmaengine: idxd: fixes found by an in-kernel polling client Daniel Byrne
2026-10-19 15:06 ` [PATCH 01/17] dmaengine: idxd: don't queue EVL fault work for kernel WQs Daniel Byrne
2026-10-19 15:06 ` [PATCH 02/17] dmaengine: idxd: detach the user fault workqueue under the event log lock Daniel Byrne
2026-10-19 15:06 ` [PATCH 03/17] dmaengine: idxd: refuse a memcpy longer than the WQ max transfer size Daniel Byrne
2026-10-19 21:19 ` Frank Li
2026-10-19 15:06 ` [PATCH 04/17] dmaengine: idxd: list a new channel only once it is complete Daniel Byrne
2026-10-19 15:06 ` [PATCH 05/17] dmaengine: idxd: unbind the device driver before its work queues go away Daniel Byrne
2026-10-19 15:06 ` [PATCH 06/17] dmaengine: idxd: keep the interrupt handle across terminate_all Daniel Byrne
2026-10-19 15:06 ` [PATCH 07/17] dmaengine: idxd: bound device command waits and fail fast after a timeout Daniel Byrne
2026-10-19 17:05 ` sashiko-bot
2026-10-19 15:06 ` [PATCH 08/17] dmaengine: idxd: compare the device disable status code whole Daniel Byrne
2026-10-19 15:06 ` [PATCH 09/17] dmaengine: idxd: quarantine terminate_all's descriptor slots until the device has drained Daniel Byrne
2026-10-19 17:26 ` sashiko-bot
2026-10-19 15:06 ` [PATCH 10/17] dmaengine: idxd: return -ETIMEDOUT from drains and resets and leak what the device may still write Daniel Byrne
2026-10-19 17:50 ` sashiko-bot
2026-10-19 15:06 ` [PATCH 11/17] dmaengine: idxd: disable the device before its work queues are unregistered Daniel Byrne
2026-10-19 18:09 ` sashiko-bot
2026-10-19 15:06 ` [PATCH 12/17] dmaengine: idxd: hold device commands off while the reset re-creates its interrupts Daniel Byrne
2026-10-19 18:19 ` sashiko-bot [this message]
2026-10-19 15:06 ` [PATCH 13/17] dmaengine: idxd: fix the double free of a descriptor whose submission failed Daniel Byrne
2026-10-19 15:06 ` [PATCH 14/17] dmaengine: idxd: complete an iaa_crypto descriptor through its own driver on abort and flush Daniel Byrne
2026-10-19 18:56 ` sashiko-bot
2026-10-19 15:06 ` [PATCH 15/17] dmaengine: idxd: flush the work queues on every halt type Daniel Byrne
2026-10-19 19:17 ` sashiko-bot
2026-10-19 15:06 ` [PATCH 16/17] dmaengine: idxd: keep client callbacks on a halt flush and cancel resubmissions after a terminate Daniel Byrne
2026-10-19 19:36 ` sashiko-bot
2026-10-19 15:06 ` [PATCH 17/17] dmaengine: idxd: run the interrupt-handle revoke under the queue lock Daniel Byrne
2026-10-19 19:53 ` sashiko-bot
2026-10-19 19:09 ` [PATCH 00/17] [PATCH 00/17] dmaengine: idxd: fixes found by an in-kernel polling client Frank Li
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-178068@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=Frank.Li@kernel.org \
--cc=daniel1.byrne@intel.com \
--cc=dmaengine@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=vkoul@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox