DMA Engine development
 help / color / mirror / Atom feed
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

  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