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 11/17] dmaengine: idxd: disable the device before its work queues are unregistered
Date: Mon, 19 Oct 2026 18:09:26 +0000 [thread overview]
Message-ID: <sashiko-outbox-178064@kernel.org> (raw)
In-Reply-To: <20261019150630.4026341-12-daniel1.byrne@intel.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] dmaengine: idxd: wqs freed before misc IRQ teardown in idxd_remove()
- [Medium] dmaengine: idxd: PASID detached before disabling bus mastering in idxd_remove()
--
commit 702a28ae3b6aeca10dbb038b18e88c5081667455
Author: Daniel Byrne <daniel1.byrne@intel.com>
dmaengine: idxd: disable the device before its work queues are unregistered
This commit moves idxd_shutdown() in idxd_remove() to run before
idxd_unregister_devices() so the device is disabled while the work queues
still exist, and sets idxd->state to IDXD_DEV_DISABLED after
pci_disable_device() before dropping the final reference to idxd_confdev.
> diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c
> index c4319ac27bfb1..a037a6e763622 100644
> --- a/drivers/dma/idxd/init.c
> +++ b/drivers/dma/idxd/init.c
> @@ -1296,6 +1296,13 @@ static void idxd_remove(struct pci_dev *pdev)
> * that driver while the queues still exist.
> */
> device_release_driver(idxd_confdev(idxd));
> + /*
> + * Disable the device while the queues still exist too. The
> + * sub-driver's remove leaves the device enabled when a command has
> + * timed out, a late completion can clear that state at any time,
> + * and the disable below then clears the queues' software state.
> + */
> + idxd_shutdown(pdev);
> idxd_unregister_devices(idxd);
[Severity: High]
If a command has timed out and does not complete before idxd_shutdown()
runs, idxd_device_disable() in idxd_shutdown() will also fail, leaving the
device enabled in hardware while idxd_unregister_devices() frees all
idxd->wqs[i] before idxd_cleanup_interrupts() frees MSI-X vector 0. Can a
misc interrupt fire in this window and dereference freed idxd->wqs[i]?
Specifically, when IDXD_FLAG_CMD_TIMEDOUT is set, idxd_device_drv_remove()
skips idxd_device_evl_free(), leaving Event Log interrupts enabled in
hardware (gencfg.evl_en = 1, genctrl.evl_int_en = 1). In idxd_shutdown():
drivers/dma/idxd/init.c:idxd_shutdown() {
rc = idxd_device_disable(idxd);
if (rc)
dev_err(&pdev->dev, "Disabling device failed\n");
irq_entry = &idxd->ie;
synchronize_irq(irq_entry->vector);
idxd_mask_error_interrupts(idxd);
flush_workqueue(idxd->wq);
}
synchronize_irq() is called before idxd_mask_error_interrupts(), and
idxd_mask_error_interrupts() only clears softerr_int_en and halt_int_en,
leaving EVL and IDXD_INTC_INT_HANDLE_REVOKED interrupts enabled while
MSI-X vector 0 (idxd_misc_thread) stays active until
idxd_cleanup_interrupts().
Once idxd_unregister_devices() unregisters and frees idxd->wqs[i], an
IDXD_INTC_EVL interrupt running idxd_misc_thread() -> process_evl_entries()
-> process_evl_entry() will index into the freed wq:
drivers/dma/idxd/irq.c:process_evl_entry() {
...
struct idxd_wq *wq = idxd->wqs[entry_head->wq_idx];
if (!is_idxd_wq_user(wq) || !wq->wq) {
...
}
Similarly, an IDXD_INTC_INT_HANDLE_REVOKED interrupt (or a halt/error
interrupt racing between synchronize_irq() and idxd_mask_error_interrupts())
can access freed idxd->wqs[i] or queue work onto idxd->wq after
flush_workqueue(idxd->wq) has already completed, which could then run
after pci_iounmap(pdev, idxd->reg_base).
Should idxd_cleanup_interrupts() (or disabling bus mastering / freeing IRQ
vector 0 before flushing idxd->wq) happen before idxd_unregister_devices()
frees the work queues?
> /*
> * When ->release() is called for the idxd->conf_dev, it frees all
> @@ -1305,15 +1312,20 @@ static void idxd_remove(struct pci_dev *pdev)
> */
> get_device(idxd_confdev(idxd));
> device_unregister(idxd_confdev(idxd));
> - idxd_shutdown(pdev);
> idxd_device_remove_debugfs(idxd);
> perfmon_pmu_remove(idxd);
> idxd_cleanup_interrupts(idxd);
> if (device_pasid_enabled(idxd))
> idxd_disable_system_pasid(idxd);
> pci_iounmap(pdev, idxd->reg_base);
> - put_device(idxd_confdev(idxd));
> pci_disable_device(pdev);
> + /*
> + * Bus mastering is off, so nothing the device holds can complete.
> + * The store comes before the reference taken above is dropped:
> + * that reference is the last one, and its release frees the device.
> + */
> + idxd->state = IDXD_DEV_DISABLED;
> + put_device(idxd_confdev(idxd));
> }
[Severity: Medium]
In the same command timeout case where the device remains enabled in
hardware until pci_disable_device(pdev) turns off bus mastering, is it
safe to call idxd_disable_system_pasid(idxd) before pci_disable_device(pdev)?
drivers/dma/idxd/init.c:idxd_disable_system_pasid() {
...
iommu_detach_device_pasid(domain, dev, idxd->pasid);
iommu_free_global_pasid(idxd->pasid);
idxd_set_user_intr(idxd, 0);
...
}
Because bus mastering is still active when idxd_disable_system_pasid()
runs, could in-flight descriptors on the still-enabled device issue DMA
with idxd->pasid after it has been detached and freed, or could
idxd_set_user_intr() write GENCFG while the device is still enabled?
듯
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261019150630.4026341-1-daniel1.byrne@intel.com?part=11
next prev parent reply other threads:[~2026-10-19 18:09 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 [this message]
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
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-178064@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