mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Daniel Byrne <daniel1.byrne@intel.com>
To: Vinod Koul <vkoul@kernel.org>, Dave Jiang <dave.jiang@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>, Dan Williams <djbw@kernel.org>,
	Vinicius Costa Gomes <vinicius.gomes@intel.com>,
	Frank Li <Frank.Li@kernel.org>,
	Herbert Xu <herbert@gondor.apana.org.au>,
	Tom Zanussi <tom.zanussi@linux.intel.com>,
	Kristen Accardi <kristen.c.accardi@intel.com>,
	dmaengine@vger.kernel.org, linux-crypto@vger.kernel.org,
	linux-kernel@vger.kernel.org, stable@vger.kernel.org
Subject: [PATCH 17/17] dmaengine: idxd: run the interrupt-handle revoke under the queue lock
Date: Mon, 19 Oct 2026 08:06:30 -0700	[thread overview]
Message-ID: <20261019150630.4026341-18-daniel1.byrne@intel.com> (raw)
In-Reply-To: <20261019150630.4026341-1-daniel1.byrne@intel.com>

The interrupt-handle revoke worker requests each new handle without
wq_lock, so that a reset can end the request, and the queue may be
unbound while it waits. It reads the queue's state without the lock,
submits the drain after unlocking, and on a failed request quiesces the
queue and completes the descriptors that carry the revoked handle
outside the lock, so an unbind can unmap the portal under the drain, or
free the descriptors, the allocator and the driver under the
completions.

The unbind invalidates the handle in the same wq_lock hold that tears
the queue down, so after the request the worker takes wq_lock and goes
on only if the handle is still valid. The handle swap and the drain, or
the quiesce and the completions after a failed request, then run in
that hold. A queue a halt already killed and did not revive is left
dead rather than revived behind the halt.

Assisted-by: Claude:claude-opus-5
Assisted-by: Claude:claude-opus-5-5
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Daniel Byrne <daniel1.byrne@intel.com>
---
 drivers/dma/idxd/irq.c | 45 +++++++++++++++++++++++++++++++-----------
 1 file changed, 33 insertions(+), 12 deletions(-)

diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c
index 4517a09fcf1b..8217698056bb 100644
--- a/drivers/dma/idxd/irq.c
+++ b/drivers/dma/idxd/irq.c
@@ -115,6 +115,11 @@ static void idxd_abort_invalid_int_handle_descs(struct idxd_irq_entry *ie)
 	struct idxd_desc *d, *t;
 	struct llist_node *head;
 
+	/*
+	 * An unbind frees the descriptors and the allocator under
+	 * wq_lock, so they are completed under it as well.
+	 */
+	lockdep_assert_held(&ie_to_wq(ie)->wq_lock);
 	spin_lock(&ie->list_lock);
 	head = llist_del_all(&ie->pending_llist);
 	if (head) {
@@ -142,6 +147,7 @@ static void idxd_int_handle_revoke(struct work_struct *work)
 	struct pci_dev *pdev = idxd->pdev;
 	struct device *dev = &pdev->dev;
 	int i, new_handle, rc;
+	bool killed;
 
 	if (!idxd->request_int_handles) {
 		kfree(revoke);
@@ -166,15 +172,31 @@ static void idxd_int_handle_revoke(struct work_struct *work)
 			continue;
 
 		rc = idxd_device_request_int_handle(idxd, i, &new_handle, IDXD_IRQ_MSIX);
-		if (rc < 0) {
+		if (rc < 0)
 			dev_warn(dev, "get int handle %d failed: %d\n", i, rc);
+
+		/*
+		 * The request runs without wq_lock, so that a reset can end
+		 * it, and the queue may have been unbound meanwhile. An
+		 * unbind invalidates the handle in the same wq_lock hold
+		 * that unmaps the portal and frees the descriptors, so a
+		 * handle still valid under the lock means that the queue
+		 * still has its portal, its descriptors and its completion
+		 * handler. Everything below, the drain included, stays in
+		 * this hold.
+		 */
+		guard(mutex)(&wq->wq_lock);
+		if (ie->int_handle == INVALID_INT_HANDLE)
+			continue;
+
+		if (rc < 0) {
 			/*
 			 * Failed to acquire new interrupt handle. Kill the WQ
 			 * and release all the pending submitters. The submitters will
 			 * get error return code and handle appropriately.
 			 */
 			ie->int_handle = INVALID_INT_HANDLE;
-			idxd_wq_quiesce(wq);
+			__idxd_wq_quiesce(wq);
 			idxd_abort_invalid_int_handle_descs(ie);
 			continue;
 		}
@@ -193,21 +215,20 @@ static void idxd_int_handle_revoke(struct work_struct *work)
 			continue;
 		}
 
-		mutex_lock(&wq->wq_lock);
-		reinit_completion(&wq->wq_resurrect);
-
-		/* Kill percpu_ref to pause additional descriptor submissions */
-		percpu_ref_kill(&wq->wq_active);
-
-		/* Wait for all submitters quiesce before we change interrupt handle */
-		wait_for_completion(&wq->wq_dead);
+		/*
+		 * Kill percpu_ref to pause additional descriptor submissions
+		 * and wait for all submitters to quiesce before we change
+		 * the interrupt handle. A queue a halt already killed and did
+		 * not revive is left dead.
+		 */
+		killed = idxd_wq_kill(wq);
 
 		ie->int_handle = new_handle;
 
 		/* Revive percpu ref and wake up all the waiting submitters */
-		percpu_ref_reinit(&wq->wq_active);
+		if (killed)
+			percpu_ref_reinit(&wq->wq_active);
 		complete_all(&wq->wq_resurrect);
-		mutex_unlock(&wq->wq_lock);
 
 		/*
 		 * The delay here is to wait for all possible MOVDIR64B that
-- 
2.43.0


  parent reply	other threads:[~2026-10-19 15:14 UTC|newest]

Thread overview: 20+ 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 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 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 15:06 ` [PATCH 11/17] dmaengine: idxd: disable the device before its work queues are unregistered Daniel Byrne
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 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 15:06 ` [PATCH 15/17] dmaengine: idxd: flush the work queues on every halt type Daniel Byrne
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 15:06 ` Daniel Byrne [this message]
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=20261019150630.4026341-18-daniel1.byrne@intel.com \
    --to=daniel1.byrne@intel.com \
    --cc=Frank.Li@kernel.org \
    --cc=dave.jiang@intel.com \
    --cc=djbw@kernel.org \
    --cc=dmaengine@vger.kernel.org \
    --cc=fenghua.yu@intel.com \
    --cc=herbert@gondor.apana.org.au \
    --cc=kristen.c.accardi@intel.com \
    --cc=linux-crypto@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=tom.zanussi@linux.intel.com \
    --cc=vinicius.gomes@intel.com \
    --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

all inboxes | Powered by JetHome®