mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v3 00/11] dmaengine: miscellaneous fixes for ioat, switchtec_dma and plx_dma
@ 2026-07-27 18:15 Logan Gunthorpe
  2026-07-27 18:15 ` [PATCH v3 01/11] dmaengine: switchtec-dma: fix double-free in switchtec_dma_free_desc() Logan Gunthorpe
                   ` (10 more replies)
  0 siblings, 11 replies; 23+ messages in thread
From: Logan Gunthorpe @ 2026-07-27 18:15 UTC (permalink / raw)
  To: linux-kernel, linux-pci, dmaengine, Vinod Koul
  Cc: Frank Li, Kelvin Cao, Thomas Weißschuh, Dave Jiang,
	George Ge, Jaeyoung Chung, Logan Gunthorpe

When reviewing the recent switchtec patchset[1], the Sashiko bot noticed
a handful of pre-existing problems in the ioat and switchtec drivers.
I attempted to fix those plus an unrelated issue reported in plxdma but
when I submitted those patches, Sashiko found even more issues[2][3] (it is
relentless!).

I've fixed the issues reported with v1 and v2 of this series and many
of the ones for the switchtec driver. But the pre-existing issues in ioat,
plxdma and the dmaengine itself I've punted until I can find some time
to dig into them.

The series is based off of v7.2-rc4.

Thanks,

Logan

[1] https://lore.kernel.org/all/20260707162045.23910-1-logang@deltatee.com
[2] https://sashiko.dev/#/patchset/20260717221001.361421-1-logang@deltatee.com
[3] https://sashiko.dev/#/patchset/20260721155739.62120-1-logang@deltatee.com

Changes since v2:

 * Fixed a race when unlisting the channels in the error path.
   The interrupt needed to be disabled before hand. (Per Sashiko)
 * Picked up Acked-by from Dave Jiang on the two ioat patches.

Changes since v1:

 * Added a fix for switchtec_dma_alloc_chan_resources()'s error path
   calling disable_channel() instead of properly halting the channel
   before freeing the descriptor rings. (Per Sashiko)
 * Added a fix for switchtec-dma channel structs being freed without
   being removed from dma_dev->channels on a registration failure,
   while the channel status IRQ is still live. (Per Sashiko)
 * Added a fix for switchtec_dma_remove() using swdma_dev after it may
   already have been freed by dma_async_device_unregister(). (Per
   Sashiko)
 * Added a fix for chan_status_irq being freed with the wrong API, and
   a valid vector index of 0 being incorrectly treated as unset.
   (Per Sashiko)
 * Made switchtec_dma_chans_release() void, since nothing checked its
   return value. (Noticed while reviewing the code for these changes).

Logan Gunthorpe (11):
  dmaengine: switchtec-dma: fix double-free in switchtec_dma_free_desc()
  dmaengine: switchtec-dma: fix resource leak in alloc_chan_resources
  dmaengine: switchtec-dma: halt channel on alloc_chan_resources error
  dmaengine: switchtec-dma: fix channel leak on registration failure
  dmaengine: switchtec-dma: make switchtec_dma_chans_release() void
  dmaengine: switchtec-dma: fix chan_status_irq cleanup on create()
    error
  dmaengine: switchtec-dma: disable channels before freeing on
    registration failure
  dmaengine: switchtec-dma: fix use-after-free of swdma_dev in remove()
  dmaengine: ioat: disable relaxed ordering before registering the
    device
  dmaengine: ioat: use sysfs_emit() in per-channel sysfs show()
  dmaengine: plx_dma: fix NULL pointer deref in plx_dma_isr()

 drivers/dma/ioat/init.c     | 18 ++++----
 drivers/dma/ioat/sysfs.c    | 22 +++++-----
 drivers/dma/plx_dma.c       | 10 ++---
 drivers/dma/switchtec_dma.c | 84 +++++++++++++++++++++++++++----------
 4 files changed, 88 insertions(+), 46 deletions(-)


base-commit: 1590cf0329716306e948a8fc29f1d3ee87d3989f
-- 
2.47.3


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v3 01/11] dmaengine: switchtec-dma: fix double-free in switchtec_dma_free_desc()
  2026-07-27 18:15 [PATCH v3 00/11] dmaengine: miscellaneous fixes for ioat, switchtec_dma and plx_dma Logan Gunthorpe
@ 2026-07-27 18:15 ` Logan Gunthorpe
  2026-07-27 20:42   ` Frank Li
  2026-07-27 18:15 ` [PATCH v3 02/11] dmaengine: switchtec-dma: fix resource leak in alloc_chan_resources Logan Gunthorpe
                   ` (9 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Logan Gunthorpe @ 2026-07-27 18:15 UTC (permalink / raw)
  To: linux-kernel, linux-pci, dmaengine, Vinod Koul
  Cc: Frank Li, Kelvin Cao, Thomas Weißschuh, Dave Jiang,
	George Ge, Jaeyoung Chung, Logan Gunthorpe

switchtec_dma_free_desc() frees swdma_chan->hw_sq, hw_cq, and every
desc_ring[] entry without clearing the pointers afterward. If
switchtec_dma_alloc_chan_resources() fails partway through and calls
it during unwind, then a later retry of alloc_chan_resources() fails
in switchtec_dma_alloc_desc() before reallocating one of those
pointers, its own failure path calls switchtec_dma_free_desc() again
and frees the same, already-freed pointers a second time.

NULL out each pointer as it's freed so a subsequent call is a no-op
for anything already released.

Fixes: 30eba9df76ad ("dmaengine: switchtec-dma: Implement hardware initialization and cleanup")
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/dma/switchtec_dma.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c
index 3ef928640615..a4a7d66d042d 100644
--- a/drivers/dma/switchtec_dma.c
+++ b/drivers/dma/switchtec_dma.c
@@ -886,14 +886,18 @@ static void switchtec_dma_free_desc(struct switchtec_dma_chan *swdma_chan)
 	if (swdma_chan->hw_sq)
 		dma_free_coherent(swdma_dev->dma_dev.dev, size,
 				  swdma_chan->hw_sq, swdma_chan->dma_addr_sq);
+	swdma_chan->hw_sq = NULL;
 
 	size = SWITCHTEC_DMA_CQ_SIZE * sizeof(*swdma_chan->hw_cq);
 	if (swdma_chan->hw_cq)
 		dma_free_coherent(swdma_dev->dma_dev.dev, size,
 				  swdma_chan->hw_cq, swdma_chan->dma_addr_cq);
+	swdma_chan->hw_cq = NULL;
 
-	for (i = 0; i < SWITCHTEC_DMA_RING_SIZE; i++)
+	for (i = 0; i < SWITCHTEC_DMA_RING_SIZE; i++) {
 		kfree(swdma_chan->desc_ring[i]);
+		swdma_chan->desc_ring[i] = NULL;
+	}
 }
 
 static int switchtec_dma_alloc_desc(struct switchtec_dma_chan *swdma_chan)
-- 
2.47.3


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v3 02/11] dmaengine: switchtec-dma: fix resource leak in alloc_chan_resources
  2026-07-27 18:15 [PATCH v3 00/11] dmaengine: miscellaneous fixes for ioat, switchtec_dma and plx_dma Logan Gunthorpe
  2026-07-27 18:15 ` [PATCH v3 01/11] dmaengine: switchtec-dma: fix double-free in switchtec_dma_free_desc() Logan Gunthorpe
@ 2026-07-27 18:15 ` Logan Gunthorpe
  2026-07-27 20:44   ` Frank Li
  2026-07-27 18:15 ` [PATCH v3 03/11] dmaengine: switchtec-dma: halt channel on alloc_chan_resources error Logan Gunthorpe
                   ` (8 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Logan Gunthorpe @ 2026-07-27 18:15 UTC (permalink / raw)
  To: linux-kernel, linux-pci, dmaengine, Vinod Koul
  Cc: Frank Li, Kelvin Cao, Thomas Weißschuh, Dave Jiang,
	George Ge, Jaeyoung Chung, Logan Gunthorpe, Sashiko

switchtec_dma_alloc_chan_resources() returns directly on any later
failure, without ever freeing the descriptor rings and coherent DMA
memory it just allocated. The dmaengine core does not call
device_free_chan_resources() when device_alloc_chan_resources() fails,
so the driver has to unwind its own partial state.

The device-removed check also runs after ring_active and
comp_ring_active have already been set true, so a failure there left
the channel marked active despite alloc_chan_resources() reporting
failure.

Add an error-unwind path that disables the channel and frees the
descriptor rings on every failure after allocation. ring_active and
comp_ring_active are cleared under the same locks
switchtec_dma_free_chan_resources() already uses, since the completion
tasklet checks comp_ring_active under complete_lock before touching
the completion ring, and a stale IRQ can still be in flight when this
unwind path runs.

Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://lore.kernel.org/dmaengine/20260707165555.350951F000E9@smtp.kernel.org
Fixes: 30eba9df76ad ("dmaengine: switchtec-dma: Implement hardware initialization and cleanup")
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/dma/switchtec_dma.c | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)

diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c
index a4a7d66d042d..f77da31aeb65 100644
--- a/drivers/dma/switchtec_dma.c
+++ b/drivers/dma/switchtec_dma.c
@@ -988,15 +988,15 @@ static int switchtec_dma_alloc_chan_resources(struct dma_chan *chan)
 
 	rc = enable_channel(swdma_chan);
 	if (rc)
-		return rc;
+		goto err_free_desc;
 
 	rc = reset_channel(swdma_chan);
 	if (rc)
-		return rc;
+		goto err_disable_channel;
 
 	rc = unhalt_channel(swdma_chan);
 	if (rc)
-		return rc;
+		goto err_disable_channel;
 
 	swdma_chan->ring_active = true;
 	swdma_chan->comp_ring_active = true;
@@ -1007,7 +1007,8 @@ static int switchtec_dma_alloc_chan_resources(struct dma_chan *chan)
 	rcu_read_lock();
 	if (!rcu_dereference(swdma_dev->pdev)) {
 		rcu_read_unlock();
-		return -ENODEV;
+		rc = -ENODEV;
+		goto err_ring_inactive;
 	}
 
 	perf_cfg = readl(&swdma_chan->mmio_chan_fw->perf_cfg);
@@ -1029,6 +1030,20 @@ static int switchtec_dma_alloc_chan_resources(struct dma_chan *chan)
 		FIELD_GET(PERF_MRRS_MASK, perf_cfg));
 
 	return SWITCHTEC_DMA_SQ_SIZE;
+
+err_ring_inactive:
+	spin_lock_bh(&swdma_chan->submit_lock);
+	swdma_chan->ring_active = false;
+	spin_unlock_bh(&swdma_chan->submit_lock);
+
+	spin_lock_bh(&swdma_chan->complete_lock);
+	swdma_chan->comp_ring_active = false;
+	spin_unlock_bh(&swdma_chan->complete_lock);
+err_disable_channel:
+	disable_channel(swdma_chan);
+err_free_desc:
+	switchtec_dma_free_desc(swdma_chan);
+	return rc;
 }
 
 static void switchtec_dma_free_chan_resources(struct dma_chan *chan)
-- 
2.47.3


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v3 03/11] dmaengine: switchtec-dma: halt channel on alloc_chan_resources error
  2026-07-27 18:15 [PATCH v3 00/11] dmaengine: miscellaneous fixes for ioat, switchtec_dma and plx_dma Logan Gunthorpe
  2026-07-27 18:15 ` [PATCH v3 01/11] dmaengine: switchtec-dma: fix double-free in switchtec_dma_free_desc() Logan Gunthorpe
  2026-07-27 18:15 ` [PATCH v3 02/11] dmaengine: switchtec-dma: fix resource leak in alloc_chan_resources Logan Gunthorpe
@ 2026-07-27 18:15 ` Logan Gunthorpe
  2026-07-27 18:15 ` [PATCH v3 04/11] dmaengine: switchtec-dma: fix channel leak on registration failure Logan Gunthorpe
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Logan Gunthorpe @ 2026-07-27 18:15 UTC (permalink / raw)
  To: linux-kernel, linux-pci, dmaengine, Vinod Koul
  Cc: Frank Li, Kelvin Cao, Thomas Weißschuh, Dave Jiang,
	George Ge, Jaeyoung Chung, Logan Gunthorpe, Sashiko

The error-unwind path called disable_channel() before freeing the
descriptor rings, but that only clears the enable bit with an
unflushed write -- it doesn't halt the channel or clear its DMA base
address registers. If unhalt_channel() timed out, the channel's actual
state is unknown at that point, so nothing guarantees the hardware
isn't still touching the rings when they're freed.

Call switchtec_dma_chan_stop() first, matching what
switchtec_dma_free_chan_resources() already does before freeing
descriptors on the normal teardown path: it synchronously halts the
channel and zeroes the DMA base registers.

Fixes: 30eba9df76ad ("dmaengine: switchtec-dma: Implement hardware initialization and cleanup")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://lore.kernel.org/dmaengine/20260717223647.F0A051F000E9@smtp.kernel.org
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/dma/switchtec_dma.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c
index f77da31aeb65..107769cca772 100644
--- a/drivers/dma/switchtec_dma.c
+++ b/drivers/dma/switchtec_dma.c
@@ -1040,6 +1040,7 @@ static int switchtec_dma_alloc_chan_resources(struct dma_chan *chan)
 	swdma_chan->comp_ring_active = false;
 	spin_unlock_bh(&swdma_chan->complete_lock);
 err_disable_channel:
+	switchtec_dma_chan_stop(swdma_chan);
 	disable_channel(swdma_chan);
 err_free_desc:
 	switchtec_dma_free_desc(swdma_chan);
-- 
2.47.3


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v3 04/11] dmaengine: switchtec-dma: fix channel leak on registration failure
  2026-07-27 18:15 [PATCH v3 00/11] dmaengine: miscellaneous fixes for ioat, switchtec_dma and plx_dma Logan Gunthorpe
                   ` (2 preceding siblings ...)
  2026-07-27 18:15 ` [PATCH v3 03/11] dmaengine: switchtec-dma: halt channel on alloc_chan_resources error Logan Gunthorpe
@ 2026-07-27 18:15 ` Logan Gunthorpe
  2026-07-27 20:52   ` Frank Li
  2026-07-27 18:15 ` [PATCH v3 05/11] dmaengine: switchtec-dma: make switchtec_dma_chans_release() void Logan Gunthorpe
                   ` (6 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Logan Gunthorpe @ 2026-07-27 18:15 UTC (permalink / raw)
  To: linux-kernel, linux-pci, dmaengine, Vinod Koul
  Cc: Frank Li, Kelvin Cao, Thomas Weißschuh, Dave Jiang,
	George Ge, Jaeyoung Chung, Logan Gunthorpe, Sashiko

switchtec_dma_chans_release() is called in three places but the
underlying memory is not freed in all of those places. In order to
clean this up, introduce a switchtec_dma_chans_free() helper that
will free the memory.

Ensure each call to switchtec_dma_chans_release() has a corresponding
switchtec_dma_chans_free() call. (The release in switchtec_dma_remove()
pairs with the free in switchtec_dma_release()).

swdma_dev->chan_cnt is now set to the number of channels that succeeded
when one fails to initialise, so switchtec_dma_chans_free() can still
be used if not all channels succeed in being allocated.

Fixes: 30eba9df76ad ("dmaengine: switchtec-dma: Implement hardware initialization and cleanup")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://lore.kernel.org/dmaengine/20260717223024.9BB8A1F000E9@smtp.kernel.org
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/dma/switchtec_dma.c | 25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c
index 107769cca772..13efd4189bbb 100644
--- a/drivers/dma/switchtec_dma.c
+++ b/drivers/dma/switchtec_dma.c
@@ -1176,6 +1176,16 @@ static int switchtec_dma_chans_release(struct pci_dev *pdev,
 	return 0;
 }
 
+static void switchtec_dma_chans_free(struct switchtec_dma_dev *swdma_dev)
+{
+	int i;
+
+	for (i = 0; i < swdma_dev->chan_cnt; i++)
+		kfree(swdma_dev->swdma_chans[i]);
+
+	kfree(swdma_dev->swdma_chans);
+}
+
 static int switchtec_dma_chans_enumerate(struct switchtec_dma_dev *swdma_dev,
 					 struct pci_dev *pdev, int chan_cnt)
 {
@@ -1201,7 +1211,7 @@ static int switchtec_dma_chans_enumerate(struct switchtec_dma_dev *swdma_dev,
 		if (rc) {
 			dev_err(&pdev->dev, "Channel %d: init channel failed\n",
 				i);
-			chan_cnt = i;
+			swdma_dev->chan_cnt = i;
 			goto err_exit;
 		}
 	}
@@ -1209,10 +1219,8 @@ static int switchtec_dma_chans_enumerate(struct switchtec_dma_dev *swdma_dev,
 	return chan_cnt;
 
 err_exit:
-	for (i = 0; i < chan_cnt; i++)
-		switchtec_dma_chan_free(pdev, swdma_dev->swdma_chans[i]);
-
-	kfree(swdma_dev->swdma_chans);
+	switchtec_dma_chans_release(pdev, swdma_dev);
+	switchtec_dma_chans_free(swdma_dev);
 
 	return rc;
 }
@@ -1221,12 +1229,8 @@ static void switchtec_dma_release(struct dma_device *dma_dev)
 {
 	struct switchtec_dma_dev *swdma_dev =
 		container_of(dma_dev, struct switchtec_dma_dev, dma_dev);
-	int i;
 
-	for (i = 0; i < swdma_dev->chan_cnt; i++)
-		kfree(swdma_dev->swdma_chans[i]);
-
-	kfree(swdma_dev->swdma_chans);
+	switchtec_dma_chans_free(swdma_dev);
 
 	put_device(dma_dev->dev);
 	kfree(swdma_dev);
@@ -1317,6 +1321,7 @@ static int switchtec_dma_create(struct pci_dev *pdev)
 
 err_chans_release_exit:
 	switchtec_dma_chans_release(pdev, swdma_dev);
+	switchtec_dma_chans_free(swdma_dev);
 
 err_exit:
 	if (swdma_dev->chan_status_irq)
-- 
2.47.3


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v3 05/11] dmaengine: switchtec-dma: make switchtec_dma_chans_release() void
  2026-07-27 18:15 [PATCH v3 00/11] dmaengine: miscellaneous fixes for ioat, switchtec_dma and plx_dma Logan Gunthorpe
                   ` (3 preceding siblings ...)
  2026-07-27 18:15 ` [PATCH v3 04/11] dmaengine: switchtec-dma: fix channel leak on registration failure Logan Gunthorpe
@ 2026-07-27 18:15 ` Logan Gunthorpe
  2026-07-27 20:54   ` Frank Li
  2026-07-27 18:15 ` [PATCH v3 06/11] dmaengine: switchtec-dma: fix chan_status_irq cleanup on create() error Logan Gunthorpe
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Logan Gunthorpe @ 2026-07-27 18:15 UTC (permalink / raw)
  To: linux-kernel, linux-pci, dmaengine, Vinod Koul
  Cc: Frank Li, Kelvin Cao, Thomas Weißschuh, Dave Jiang,
	George Ge, Jaeyoung Chung, Logan Gunthorpe

It always returned 0, and no caller checked it.

Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/dma/switchtec_dma.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c
index 13efd4189bbb..c752a1b05871 100644
--- a/drivers/dma/switchtec_dma.c
+++ b/drivers/dma/switchtec_dma.c
@@ -1165,15 +1165,13 @@ static int switchtec_dma_chan_free(struct pci_dev *pdev,
 	return 0;
 }
 
-static int switchtec_dma_chans_release(struct pci_dev *pdev,
-				       struct switchtec_dma_dev *swdma_dev)
+static void switchtec_dma_chans_release(struct pci_dev *pdev,
+					struct switchtec_dma_dev *swdma_dev)
 {
 	int i;
 
 	for (i = 0; i < swdma_dev->chan_cnt; i++)
 		switchtec_dma_chan_free(pdev, swdma_dev->swdma_chans[i]);
-
-	return 0;
 }
 
 static void switchtec_dma_chans_free(struct switchtec_dma_dev *swdma_dev)
-- 
2.47.3


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v3 06/11] dmaengine: switchtec-dma: fix chan_status_irq cleanup on create() error
  2026-07-27 18:15 [PATCH v3 00/11] dmaengine: miscellaneous fixes for ioat, switchtec_dma and plx_dma Logan Gunthorpe
                   ` (4 preceding siblings ...)
  2026-07-27 18:15 ` [PATCH v3 05/11] dmaengine: switchtec-dma: make switchtec_dma_chans_release() void Logan Gunthorpe
@ 2026-07-27 18:15 ` Logan Gunthorpe
  2026-07-27 20:55   ` Frank Li
  2026-07-27 18:15 ` [PATCH v3 07/11] dmaengine: switchtec-dma: disable channels before freeing on registration failure Logan Gunthorpe
                   ` (4 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Logan Gunthorpe @ 2026-07-27 18:15 UTC (permalink / raw)
  To: linux-kernel, linux-pci, dmaengine, Vinod Koul
  Cc: Frank Li, Kelvin Cao, Thomas Weißschuh, Dave Jiang,
	George Ge, Jaeyoung Chung, Logan Gunthorpe, Sashiko

chan_status_irq stores an MSI-X vector index, but err_exit freed it
with plain free_irq() instead of pci_free_irq(), which would free the
wrong Linux IRQ. The guard also treated a valid vector index of 0 as
unset, skipping the free entirely in that case and leaving the handler
registered against soon-to-be-freed swdma_dev.

Initialize chan_status_irq to -1 and use the value being non-negative
to signal when to free it with pci_free_irq().

Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://lore.kernel.org/dmaengine/20260717223431.625EE1F000E9@smtp.kernel.org
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/dma/switchtec_dma.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c
index c752a1b05871..31feb2816e79 100644
--- a/drivers/dma/switchtec_dma.c
+++ b/drivers/dma/switchtec_dma.c
@@ -1248,6 +1248,8 @@ static int switchtec_dma_create(struct pci_dev *pdev)
 	if (!swdma_dev)
 		return -ENOMEM;
 
+	swdma_dev->chan_status_irq = -1;
+
 	swdma_dev->bar = ioremap(pci_resource_start(pdev, 0),
 				 pci_resource_len(pdev, 0));
 
@@ -1322,8 +1324,8 @@ static int switchtec_dma_create(struct pci_dev *pdev)
 	switchtec_dma_chans_free(swdma_dev);
 
 err_exit:
-	if (swdma_dev->chan_status_irq)
-		free_irq(swdma_dev->chan_status_irq, swdma_dev);
+	if (swdma_dev->chan_status_irq >= 0)
+		pci_free_irq(pdev, swdma_dev->chan_status_irq, swdma_dev);
 
 	iounmap(swdma_dev->bar);
 	kfree(swdma_dev);
-- 
2.47.3


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v3 07/11] dmaengine: switchtec-dma: disable channels before freeing on registration failure
  2026-07-27 18:15 [PATCH v3 00/11] dmaengine: miscellaneous fixes for ioat, switchtec_dma and plx_dma Logan Gunthorpe
                   ` (5 preceding siblings ...)
  2026-07-27 18:15 ` [PATCH v3 06/11] dmaengine: switchtec-dma: fix chan_status_irq cleanup on create() error Logan Gunthorpe
@ 2026-07-27 18:15 ` Logan Gunthorpe
  2026-07-27 21:21   ` Frank Li
  2026-07-27 18:15 ` [PATCH v3 08/11] dmaengine: switchtec-dma: fix use-after-free of swdma_dev in remove() Logan Gunthorpe
                   ` (3 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Logan Gunthorpe @ 2026-07-27 18:15 UTC (permalink / raw)
  To: linux-kernel, linux-pci, dmaengine, Vinod Koul
  Cc: Frank Li, Kelvin Cao, Thomas Weißschuh, Dave Jiang,
	George Ge, Jaeyoung Chung, Logan Gunthorpe, Sashiko

When switchtec_dma_create() fails after channels have been added to
dma_dev->channels (either from switchtec_dma_chans_enumerate()'s own
error path, or from dma_async_device_register() failing), the channels
are released and freed but never removed from dma_dev->channels.

Add switchtec_dma_chans_disable() which disables interrupts and
removes the channels from the list.. Call it before releasing and
freeing channels in both error paths.

Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://lore.kernel.org/dmaengine/20260717223431.625EE1F000E9@smtp.kernel.org
Link: https://lore.kernel.org/dmaengine/20260721162822.05CDD1F000E9@smtp.kernel.org
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/dma/switchtec_dma.c | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c
index 31feb2816e79..800d8ecd0717 100644
--- a/drivers/dma/switchtec_dma.c
+++ b/drivers/dma/switchtec_dma.c
@@ -1184,6 +1184,20 @@ static void switchtec_dma_chans_free(struct switchtec_dma_dev *swdma_dev)
 	kfree(swdma_dev->swdma_chans);
 }
 
+static void switchtec_dma_chans_disable(struct pci_dev *pdev,
+					struct switchtec_dma_dev *swdma_dev)
+{
+	int i;
+
+	if (swdma_dev->chan_status_irq >= 0) {
+		pci_free_irq(pdev, swdma_dev->chan_status_irq, swdma_dev);
+		swdma_dev->chan_status_irq = -1;
+	}
+
+	for (i = 0; i < swdma_dev->chan_cnt; i++)
+		list_del(&swdma_dev->swdma_chans[i]->dma_chan.device_node);
+}
+
 static int switchtec_dma_chans_enumerate(struct switchtec_dma_dev *swdma_dev,
 					 struct pci_dev *pdev, int chan_cnt)
 {
@@ -1217,6 +1231,7 @@ static int switchtec_dma_chans_enumerate(struct switchtec_dma_dev *swdma_dev,
 	return chan_cnt;
 
 err_exit:
+	switchtec_dma_chans_disable(pdev, swdma_dev);
 	switchtec_dma_chans_release(pdev, swdma_dev);
 	switchtec_dma_chans_free(swdma_dev);
 
@@ -1320,6 +1335,7 @@ static int switchtec_dma_create(struct pci_dev *pdev)
 	return 0;
 
 err_chans_release_exit:
+	switchtec_dma_chans_disable(pdev, swdma_dev);
 	switchtec_dma_chans_release(pdev, swdma_dev);
 	switchtec_dma_chans_free(swdma_dev);
 
-- 
2.47.3


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v3 08/11] dmaengine: switchtec-dma: fix use-after-free of swdma_dev in remove()
  2026-07-27 18:15 [PATCH v3 00/11] dmaengine: miscellaneous fixes for ioat, switchtec_dma and plx_dma Logan Gunthorpe
                   ` (6 preceding siblings ...)
  2026-07-27 18:15 ` [PATCH v3 07/11] dmaengine: switchtec-dma: disable channels before freeing on registration failure Logan Gunthorpe
@ 2026-07-27 18:15 ` Logan Gunthorpe
  2026-07-27 21:23   ` Frank Li
  2026-07-27 18:15 ` [PATCH v3 09/11] dmaengine: ioat: disable relaxed ordering before registering the device Logan Gunthorpe
                   ` (2 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Logan Gunthorpe @ 2026-07-27 18:15 UTC (permalink / raw)
  To: linux-kernel, linux-pci, dmaengine, Vinod Koul
  Cc: Frank Li, Kelvin Cao, Thomas Weißschuh, Dave Jiang,
	George Ge, Jaeyoung Chung, Logan Gunthorpe, Sashiko

dma_async_device_unregister() can drop the last reference on dma_dev
and free swdma_dev synchronously via switchtec_dma_release(), but
switchtec_dma_remove() then uses swdma_dev->bar for iounmap().

Cache bar in a local variable before the unregister call.

Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://lore.kernel.org/dmaengine/20260717223431.625EE1F000E9@smtp.kernel.org
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/dma/switchtec_dma.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c
index 800d8ecd0717..d73506b5cabc 100644
--- a/drivers/dma/switchtec_dma.c
+++ b/drivers/dma/switchtec_dma.c
@@ -1384,6 +1384,7 @@ static int switchtec_dma_probe(struct pci_dev *pdev,
 static void switchtec_dma_remove(struct pci_dev *pdev)
 {
 	struct switchtec_dma_dev *swdma_dev = pci_get_drvdata(pdev);
+	void __iomem *bar = swdma_dev->bar;
 
 	switchtec_dma_chans_release(pdev, swdma_dev);
 
@@ -1396,7 +1397,7 @@ static void switchtec_dma_remove(struct pci_dev *pdev)
 
 	dma_async_device_unregister(&swdma_dev->dma_dev);
 
-	iounmap(swdma_dev->bar);
+	iounmap(bar);
 	pci_release_mem_regions(pdev);
 	pci_disable_device(pdev);
 }
-- 
2.47.3


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v3 09/11] dmaengine: ioat: disable relaxed ordering before registering the device
  2026-07-27 18:15 [PATCH v3 00/11] dmaengine: miscellaneous fixes for ioat, switchtec_dma and plx_dma Logan Gunthorpe
                   ` (7 preceding siblings ...)
  2026-07-27 18:15 ` [PATCH v3 08/11] dmaengine: switchtec-dma: fix use-after-free of swdma_dev in remove() Logan Gunthorpe
@ 2026-07-27 18:15 ` Logan Gunthorpe
  2026-07-27 21:27   ` Frank Li
  2026-07-27 18:15 ` [PATCH v3 10/11] dmaengine: ioat: use sysfs_emit() in per-channel sysfs show() Logan Gunthorpe
  2026-07-27 18:15 ` [PATCH v3 11/11] dmaengine: plx_dma: fix NULL pointer deref in plx_dma_isr() Logan Gunthorpe
  10 siblings, 1 reply; 23+ messages in thread
From: Logan Gunthorpe @ 2026-07-27 18:15 UTC (permalink / raw)
  To: linux-kernel, linux-pci, dmaengine, Vinod Koul
  Cc: Frank Li, Kelvin Cao, Thomas Weißschuh, Dave Jiang,
	George Ge, Jaeyoung Chung, Logan Gunthorpe, Sashiko

ioat3_dma_probe() disabled PCIe relaxed ordering after calling
dma_async_device_register(), so if an error occurs and the code jumps
to err_disable_interrupts, the function returns with the device still
registered in the core's dma_device_list while the caller frees the
ioatdma_device struct, leaving a dangling registration that anything
walking the device list can dereference after it's been freed.

Move the capability read/write ahead of dma_async_device_register()
instead. Nothing after registration depends on relaxed ordering
already being disabled, and nothing before it depends on the device
being registered, so this is a plain reordering. It also means every
remaining step after registration can't fail, so there's no need to
ever have to unregister the device once registered.

Fixes: 511deae0261c ("dmaengine: ioatdma: disable relaxed ordering for ioatdma")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://lore.kernel.org/dmaengine/20260707165906.249F41F000E9@smtp.kernel.org
Acked-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/dma/ioat/init.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c
index 737496391109..a57024c4b066 100644
--- a/drivers/dma/ioat/init.c
+++ b/drivers/dma/ioat/init.c
@@ -1170,15 +1170,6 @@ static int ioat3_dma_probe(struct ioatdma_device *ioat_dma, int dca)
 		       ioat_chan->reg_base + IOAT_DCACTRL_OFFSET);
 	}
 
-	err = dma_async_device_register(&ioat_dma->dma_dev);
-	if (err)
-		goto err_disable_interrupts;
-
-	ioat_kobject_add(ioat_dma, &ioat_ktype);
-
-	if (dca)
-		ioat_dma->dca = ioat_dca_init(pdev, ioat_dma->reg_base);
-
 	/* disable relaxed ordering */
 	err = pcie_capability_read_word(pdev, PCI_EXP_DEVCTL, &val16);
 	if (err) {
@@ -1194,6 +1185,15 @@ static int ioat3_dma_probe(struct ioatdma_device *ioat_dma, int dca)
 		goto err_disable_interrupts;
 	}
 
+	err = dma_async_device_register(&ioat_dma->dma_dev);
+	if (err)
+		goto err_disable_interrupts;
+
+	ioat_kobject_add(ioat_dma, &ioat_ktype);
+
+	if (dca)
+		ioat_dma->dca = ioat_dca_init(pdev, ioat_dma->reg_base);
+
 	if (ioat_dma->cap & IOAT_CAP_DPS)
 		writeb(ioat_pending_level + 1,
 		       ioat_dma->reg_base + IOAT_PREFETCH_LIMIT_OFFSET);
-- 
2.47.3


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v3 10/11] dmaengine: ioat: use sysfs_emit() in per-channel sysfs show()
  2026-07-27 18:15 [PATCH v3 00/11] dmaengine: miscellaneous fixes for ioat, switchtec_dma and plx_dma Logan Gunthorpe
                   ` (8 preceding siblings ...)
  2026-07-27 18:15 ` [PATCH v3 09/11] dmaengine: ioat: disable relaxed ordering before registering the device Logan Gunthorpe
@ 2026-07-27 18:15 ` Logan Gunthorpe
  2026-07-27 21:28   ` Frank Li
  2026-07-27 18:15 ` [PATCH v3 11/11] dmaengine: plx_dma: fix NULL pointer deref in plx_dma_isr() Logan Gunthorpe
  10 siblings, 1 reply; 23+ messages in thread
From: Logan Gunthorpe @ 2026-07-27 18:15 UTC (permalink / raw)
  To: linux-kernel, linux-pci, dmaengine, Vinod Koul
  Cc: Frank Li, Kelvin Cao, Thomas Weißschuh, Dave Jiang,
	George Ge, Jaeyoung Chung, Logan Gunthorpe

Convert the sprintf() calls in the per-channel sysfs attribute show()
functions to sysfs_emit().

Acked-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/dma/ioat/sysfs.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/dma/ioat/sysfs.c b/drivers/dma/ioat/sysfs.c
index e796ddb5383f..976134df8108 100644
--- a/drivers/dma/ioat/sysfs.c
+++ b/drivers/dma/ioat/sysfs.c
@@ -24,12 +24,12 @@ static ssize_t cap_show(struct dma_chan *c, char *page)
 {
 	struct dma_device *dma = c->device;
 
-	return sprintf(page, "copy%s%s%s%s%s\n",
-		       dma_has_cap(DMA_PQ, dma->cap_mask) ? " pq" : "",
-		       dma_has_cap(DMA_PQ_VAL, dma->cap_mask) ? " pq_val" : "",
-		       dma_has_cap(DMA_XOR, dma->cap_mask) ? " xor" : "",
-		       dma_has_cap(DMA_XOR_VAL, dma->cap_mask) ? " xor_val" : "",
-		       dma_has_cap(DMA_INTERRUPT, dma->cap_mask) ? " intr" : "");
+	return sysfs_emit(page, "copy%s%s%s%s%s\n",
+		dma_has_cap(DMA_PQ, dma->cap_mask) ? " pq" : "",
+		dma_has_cap(DMA_PQ_VAL, dma->cap_mask) ? " pq_val" : "",
+		dma_has_cap(DMA_XOR, dma->cap_mask) ? " xor" : "",
+		dma_has_cap(DMA_XOR_VAL, dma->cap_mask) ? " xor_val" : "",
+		dma_has_cap(DMA_INTERRUPT, dma->cap_mask) ? " intr" : "");
 
 }
 static const struct ioat_sysfs_entry ioat_cap_attr = __ATTR_RO(cap);
@@ -39,8 +39,8 @@ static ssize_t version_show(struct dma_chan *c, char *page)
 	struct dma_device *dma = c->device;
 	struct ioatdma_device *ioat_dma = to_ioatdma_device(dma);
 
-	return sprintf(page, "%d.%d\n",
-		       ioat_dma->version >> 4, ioat_dma->version & 0xf);
+	return sysfs_emit(page, "%d.%d\n",
+			   ioat_dma->version >> 4, ioat_dma->version & 0xf);
 }
 static const struct ioat_sysfs_entry ioat_version_attr = __ATTR_RO(version);
 
@@ -118,7 +118,7 @@ static ssize_t ring_size_show(struct dma_chan *c, char *page)
 {
 	struct ioatdma_chan *ioat_chan = to_ioat_chan(c);
 
-	return sprintf(page, "%d\n", (1 << ioat_chan->alloc_order) & ~1);
+	return sysfs_emit(page, "%d\n", (1 << ioat_chan->alloc_order) & ~1);
 }
 static const struct ioat_sysfs_entry ring_size_attr = __ATTR_RO(ring_size);
 
@@ -127,7 +127,7 @@ static ssize_t ring_active_show(struct dma_chan *c, char *page)
 	struct ioatdma_chan *ioat_chan = to_ioat_chan(c);
 
 	/* ...taken outside the lock, no need to be precise */
-	return sprintf(page, "%d\n", ioat_ring_active(ioat_chan));
+	return sysfs_emit(page, "%d\n", ioat_ring_active(ioat_chan));
 }
 static const struct ioat_sysfs_entry ring_active_attr = __ATTR_RO(ring_active);
 
@@ -135,7 +135,7 @@ static ssize_t intr_coalesce_show(struct dma_chan *c, char *page)
 {
 	struct ioatdma_chan *ioat_chan = to_ioat_chan(c);
 
-	return sprintf(page, "%d\n", ioat_chan->intr_coalesce);
+	return sysfs_emit(page, "%d\n", ioat_chan->intr_coalesce);
 }
 
 static ssize_t intr_coalesce_store(struct dma_chan *c, const char *page,
-- 
2.47.3


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [PATCH v3 11/11] dmaengine: plx_dma: fix NULL pointer deref in plx_dma_isr()
  2026-07-27 18:15 [PATCH v3 00/11] dmaengine: miscellaneous fixes for ioat, switchtec_dma and plx_dma Logan Gunthorpe
                   ` (9 preceding siblings ...)
  2026-07-27 18:15 ` [PATCH v3 10/11] dmaengine: ioat: use sysfs_emit() in per-channel sysfs show() Logan Gunthorpe
@ 2026-07-27 18:15 ` Logan Gunthorpe
  2026-07-27 21:29   ` Frank Li
  10 siblings, 1 reply; 23+ messages in thread
From: Logan Gunthorpe @ 2026-07-27 18:15 UTC (permalink / raw)
  To: linux-kernel, linux-pci, dmaengine, Vinod Koul
  Cc: Frank Li, Kelvin Cao, Thomas Weißschuh, Dave Jiang,
	George Ge, Jaeyoung Chung, Logan Gunthorpe, Sangyun Kim,
	Kyungwook Boo

plx_dma_create() registered the interrupt handler with request_irq()
before initializing plxdev->bar. If the device raised an interrupt in
that window, plx_dma_isr() would dereference the still-NULL bar.

Move the bar assignment ahead of request_irq() so everything the
handler can touch is initialized before it can run.

Reported-by: Sangyun Kim <sangyun.kim@snu.ac.kr>
Reported-by: Kyungwook Boo <bookyungwook@gmail.com>
Link: https://lore.kernel.org/all/20260610112121.676561-1-jjy600901@snu.ac.kr
Fixes: c2dbcaa8c672 ("dmaengine: plx-dma: Implement hardware initialization and cleanup")
Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
---
 drivers/dma/plx_dma.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/dma/plx_dma.c b/drivers/dma/plx_dma.c
index 84941a918b01..409898e92c32 100644
--- a/drivers/dma/plx_dma.c
+++ b/drivers/dma/plx_dma.c
@@ -504,17 +504,17 @@ static int plx_dma_create(struct pci_dev *pdev)
 	if (!plxdev)
 		return -ENOMEM;
 
-	rc = request_irq(pci_irq_vector(pdev, 0), plx_dma_isr, 0,
-			 KBUILD_MODNAME, plxdev);
-	if (rc)
-		goto free_plx;
-
 	spin_lock_init(&plxdev->ring_lock);
 	tasklet_setup(&plxdev->desc_task, plx_dma_desc_task);
 
 	RCU_INIT_POINTER(plxdev->pdev, pdev);
 	plxdev->bar = pcim_iomap_table(pdev)[0];
 
+	rc = request_irq(pci_irq_vector(pdev, 0), plx_dma_isr, 0,
+			 KBUILD_MODNAME, plxdev);
+	if (rc)
+		goto free_plx;
+
 	dma = &plxdev->dma_dev;
 	INIT_LIST_HEAD(&dma->channels);
 	dma_cap_set(DMA_MEMCPY, dma->cap_mask);
-- 
2.47.3


^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 01/11] dmaengine: switchtec-dma: fix double-free in switchtec_dma_free_desc()
  2026-07-27 18:15 ` [PATCH v3 01/11] dmaengine: switchtec-dma: fix double-free in switchtec_dma_free_desc() Logan Gunthorpe
@ 2026-07-27 20:42   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2026-07-27 20:42 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, dmaengine, Vinod Koul, Frank Li,
	Kelvin Cao, Thomas Weißschuh, Dave Jiang, George Ge,
	Jaeyoung Chung

On Mon, Jul 27, 2026 at 12:15:16PM -0600, Logan Gunthorpe wrote:
> switchtec_dma_free_desc() frees swdma_chan->hw_sq, hw_cq, and every
> desc_ring[] entry without clearing the pointers afterward. If
> switchtec_dma_alloc_chan_resources() fails partway through and calls
> it during unwind, then a later retry of alloc_chan_resources() fails
> in switchtec_dma_alloc_desc() before reallocating one of those
> pointers, its own failure path calls switchtec_dma_free_desc() again
> and frees the same, already-freed pointers a second time.
>
> NULL out each pointer as it's freed so a subsequent call is a no-op
> for anything already released.
>
> Fixes: 30eba9df76ad ("dmaengine: switchtec-dma: Implement hardware initialization and cleanup")
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/dma/switchtec_dma.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c
> index 3ef928640615..a4a7d66d042d 100644
> --- a/drivers/dma/switchtec_dma.c
> +++ b/drivers/dma/switchtec_dma.c
> @@ -886,14 +886,18 @@ static void switchtec_dma_free_desc(struct switchtec_dma_chan *swdma_chan)
>  	if (swdma_chan->hw_sq)
>  		dma_free_coherent(swdma_dev->dma_dev.dev, size,
>  				  swdma_chan->hw_sq, swdma_chan->dma_addr_sq);
> +	swdma_chan->hw_sq = NULL;
>
>  	size = SWITCHTEC_DMA_CQ_SIZE * sizeof(*swdma_chan->hw_cq);
>  	if (swdma_chan->hw_cq)
>  		dma_free_coherent(swdma_dev->dma_dev.dev, size,
>  				  swdma_chan->hw_cq, swdma_chan->dma_addr_cq);
> +	swdma_chan->hw_cq = NULL;
>
> -	for (i = 0; i < SWITCHTEC_DMA_RING_SIZE; i++)
> +	for (i = 0; i < SWITCHTEC_DMA_RING_SIZE; i++) {
>  		kfree(swdma_chan->desc_ring[i]);
> +		swdma_chan->desc_ring[i] = NULL;
> +	}
>  }
>
>  static int switchtec_dma_alloc_desc(struct switchtec_dma_chan *swdma_chan)
> --
> 2.47.3
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 02/11] dmaengine: switchtec-dma: fix resource leak in alloc_chan_resources
  2026-07-27 18:15 ` [PATCH v3 02/11] dmaengine: switchtec-dma: fix resource leak in alloc_chan_resources Logan Gunthorpe
@ 2026-07-27 20:44   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2026-07-27 20:44 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, dmaengine, Vinod Koul, Frank Li,
	Kelvin Cao, Thomas Weißschuh, Dave Jiang, George Ge,
	Jaeyoung Chung, Sashiko

On Mon, Jul 27, 2026 at 12:15:17PM -0600, Logan Gunthorpe wrote:
> switchtec_dma_alloc_chan_resources() returns directly on any later
> failure, without ever freeing the descriptor rings and coherent DMA
> memory it just allocated. The dmaengine core does not call
> device_free_chan_resources() when device_alloc_chan_resources() fails,
> so the driver has to unwind its own partial state.
>
> The device-removed check also runs after ring_active and
> comp_ring_active have already been set true, so a failure there left
> the channel marked active despite alloc_chan_resources() reporting
> failure.
>
> Add an error-unwind path that disables the channel and frees the
> descriptor rings on every failure after allocation. ring_active and
> comp_ring_active are cleared under the same locks
> switchtec_dma_free_chan_resources() already uses, since the completion
> tasklet checks comp_ring_active under complete_lock before touching
> the completion ring, and a stale IRQ can still be in flight when this
> unwind path runs.
>
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Link: https://lore.kernel.org/dmaengine/20260707165555.350951F000E9@smtp.kernel.org
> Fixes: 30eba9df76ad ("dmaengine: switchtec-dma: Implement hardware initialization and cleanup")
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/dma/switchtec_dma.c | 23 +++++++++++++++++++----
>  1 file changed, 19 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c
> index a4a7d66d042d..f77da31aeb65 100644
> --- a/drivers/dma/switchtec_dma.c
> +++ b/drivers/dma/switchtec_dma.c
> @@ -988,15 +988,15 @@ static int switchtec_dma_alloc_chan_resources(struct dma_chan *chan)
>
>  	rc = enable_channel(swdma_chan);
>  	if (rc)
> -		return rc;
> +		goto err_free_desc;
>
>  	rc = reset_channel(swdma_chan);
>  	if (rc)
> -		return rc;
> +		goto err_disable_channel;
>
>  	rc = unhalt_channel(swdma_chan);
>  	if (rc)
> -		return rc;
> +		goto err_disable_channel;
>
>  	swdma_chan->ring_active = true;
>  	swdma_chan->comp_ring_active = true;
> @@ -1007,7 +1007,8 @@ static int switchtec_dma_alloc_chan_resources(struct dma_chan *chan)
>  	rcu_read_lock();
>  	if (!rcu_dereference(swdma_dev->pdev)) {
>  		rcu_read_unlock();
> -		return -ENODEV;
> +		rc = -ENODEV;
> +		goto err_ring_inactive;
>  	}
>
>  	perf_cfg = readl(&swdma_chan->mmio_chan_fw->perf_cfg);
> @@ -1029,6 +1030,20 @@ static int switchtec_dma_alloc_chan_resources(struct dma_chan *chan)
>  		FIELD_GET(PERF_MRRS_MASK, perf_cfg));
>
>  	return SWITCHTEC_DMA_SQ_SIZE;
> +
> +err_ring_inactive:
> +	spin_lock_bh(&swdma_chan->submit_lock);
> +	swdma_chan->ring_active = false;
> +	spin_unlock_bh(&swdma_chan->submit_lock);
> +
> +	spin_lock_bh(&swdma_chan->complete_lock);
> +	swdma_chan->comp_ring_active = false;
> +	spin_unlock_bh(&swdma_chan->complete_lock);
> +err_disable_channel:
> +	disable_channel(swdma_chan);
> +err_free_desc:
> +	switchtec_dma_free_desc(swdma_chan);
> +	return rc;
>  }
>
>  static void switchtec_dma_free_chan_resources(struct dma_chan *chan)
> --
> 2.47.3
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 04/11] dmaengine: switchtec-dma: fix channel leak on registration failure
  2026-07-27 18:15 ` [PATCH v3 04/11] dmaengine: switchtec-dma: fix channel leak on registration failure Logan Gunthorpe
@ 2026-07-27 20:52   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2026-07-27 20:52 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, dmaengine, Vinod Koul, Frank Li,
	Kelvin Cao, Thomas Weißschuh, Dave Jiang, George Ge,
	Jaeyoung Chung, Sashiko

On Mon, Jul 27, 2026 at 12:15:19PM -0600, Logan Gunthorpe wrote:
> switchtec_dma_chans_release() is called in three places but the
> underlying memory is not freed in all of those places. In order to
> clean this up, introduce a switchtec_dma_chans_free() helper that
> will free the memory.
>
> Ensure each call to switchtec_dma_chans_release() has a corresponding
> switchtec_dma_chans_free() call. (The release in switchtec_dma_remove()
> pairs with the free in switchtec_dma_release()).
>
> swdma_dev->chan_cnt is now set to the number of channels that succeeded
> when one fails to initialise, so switchtec_dma_chans_free() can still
> be used if not all channels succeed in being allocated.
>
> Fixes: 30eba9df76ad ("dmaengine: switchtec-dma: Implement hardware initialization and cleanup")
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Link: https://lore.kernel.org/dmaengine/20260717223024.9BB8A1F000E9@smtp.kernel.org
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/dma/switchtec_dma.c | 25 +++++++++++++++----------
>  1 file changed, 15 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c
> index 107769cca772..13efd4189bbb 100644
> --- a/drivers/dma/switchtec_dma.c
> +++ b/drivers/dma/switchtec_dma.c
> @@ -1176,6 +1176,16 @@ static int switchtec_dma_chans_release(struct pci_dev *pdev,
>  	return 0;
>  }
>
> +static void switchtec_dma_chans_free(struct switchtec_dma_dev *swdma_dev)
> +{
> +	int i;
> +
> +	for (i = 0; i < swdma_dev->chan_cnt; i++)
> +		kfree(swdma_dev->swdma_chans[i]);
> +
> +	kfree(swdma_dev->swdma_chans);
> +}
> +
>  static int switchtec_dma_chans_enumerate(struct switchtec_dma_dev *swdma_dev,
>  					 struct pci_dev *pdev, int chan_cnt)
>  {
> @@ -1201,7 +1211,7 @@ static int switchtec_dma_chans_enumerate(struct switchtec_dma_dev *swdma_dev,
>  		if (rc) {
>  			dev_err(&pdev->dev, "Channel %d: init channel failed\n",
>  				i);
> -			chan_cnt = i;
> +			swdma_dev->chan_cnt = i;
>  			goto err_exit;
>  		}
>  	}
> @@ -1209,10 +1219,8 @@ static int switchtec_dma_chans_enumerate(struct switchtec_dma_dev *swdma_dev,
>  	return chan_cnt;
>
>  err_exit:
> -	for (i = 0; i < chan_cnt; i++)
> -		switchtec_dma_chan_free(pdev, swdma_dev->swdma_chans[i]);
> -
> -	kfree(swdma_dev->swdma_chans);
> +	switchtec_dma_chans_release(pdev, swdma_dev);
> +	switchtec_dma_chans_free(swdma_dev);
>
>  	return rc;
>  }
> @@ -1221,12 +1229,8 @@ static void switchtec_dma_release(struct dma_device *dma_dev)
>  {
>  	struct switchtec_dma_dev *swdma_dev =
>  		container_of(dma_dev, struct switchtec_dma_dev, dma_dev);
> -	int i;
>
> -	for (i = 0; i < swdma_dev->chan_cnt; i++)
> -		kfree(swdma_dev->swdma_chans[i]);
> -
> -	kfree(swdma_dev->swdma_chans);
> +	switchtec_dma_chans_free(swdma_dev);
>
>  	put_device(dma_dev->dev);
>  	kfree(swdma_dev);
> @@ -1317,6 +1321,7 @@ static int switchtec_dma_create(struct pci_dev *pdev)
>
>  err_chans_release_exit:
>  	switchtec_dma_chans_release(pdev, swdma_dev);
> +	switchtec_dma_chans_free(swdma_dev);
>
>  err_exit:
>  	if (swdma_dev->chan_status_irq)
> --
> 2.47.3
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 05/11] dmaengine: switchtec-dma: make switchtec_dma_chans_release() void
  2026-07-27 18:15 ` [PATCH v3 05/11] dmaengine: switchtec-dma: make switchtec_dma_chans_release() void Logan Gunthorpe
@ 2026-07-27 20:54   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2026-07-27 20:54 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, dmaengine, Vinod Koul, Frank Li,
	Kelvin Cao, Thomas Weißschuh, Dave Jiang, George Ge,
	Jaeyoung Chung

On Mon, Jul 27, 2026 at 12:15:20PM -0600, Logan Gunthorpe wrote:
> It always returned 0, and no caller checked it.
>

Nit: s/It/switchtec_dma_chans_release()

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> ---
>  drivers/dma/switchtec_dma.c | 6 ++----
>  1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c
> index 13efd4189bbb..c752a1b05871 100644
> --- a/drivers/dma/switchtec_dma.c
> +++ b/drivers/dma/switchtec_dma.c
> @@ -1165,15 +1165,13 @@ static int switchtec_dma_chan_free(struct pci_dev *pdev,
>  	return 0;
>  }
>
> -static int switchtec_dma_chans_release(struct pci_dev *pdev,
> -				       struct switchtec_dma_dev *swdma_dev)
> +static void switchtec_dma_chans_release(struct pci_dev *pdev,
> +					struct switchtec_dma_dev *swdma_dev)
>  {
>  	int i;
>
>  	for (i = 0; i < swdma_dev->chan_cnt; i++)
>  		switchtec_dma_chan_free(pdev, swdma_dev->swdma_chans[i]);
> -
> -	return 0;
>  }
>
>  static void switchtec_dma_chans_free(struct switchtec_dma_dev *swdma_dev)
> --
> 2.47.3
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 06/11] dmaengine: switchtec-dma: fix chan_status_irq cleanup on create() error
  2026-07-27 18:15 ` [PATCH v3 06/11] dmaengine: switchtec-dma: fix chan_status_irq cleanup on create() error Logan Gunthorpe
@ 2026-07-27 20:55   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2026-07-27 20:55 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, dmaengine, Vinod Koul, Frank Li,
	Kelvin Cao, Thomas Weißschuh, Dave Jiang, George Ge,
	Jaeyoung Chung, Sashiko

On Mon, Jul 27, 2026 at 12:15:21PM -0600, Logan Gunthorpe wrote:
> chan_status_irq stores an MSI-X vector index, but err_exit freed it
> with plain free_irq() instead of pci_free_irq(), which would free the
> wrong Linux IRQ. The guard also treated a valid vector index of 0 as
> unset, skipping the free entirely in that case and leaving the handler
> registered against soon-to-be-freed swdma_dev.
>
> Initialize chan_status_irq to -1 and use the value being non-negative
> to signal when to free it with pci_free_irq().
>
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Link: https://lore.kernel.org/dmaengine/20260717223431.625EE1F000E9@smtp.kernel.org
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/dma/switchtec_dma.c | 6 ++++--
>  1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c
> index c752a1b05871..31feb2816e79 100644
> --- a/drivers/dma/switchtec_dma.c
> +++ b/drivers/dma/switchtec_dma.c
> @@ -1248,6 +1248,8 @@ static int switchtec_dma_create(struct pci_dev *pdev)
>  	if (!swdma_dev)
>  		return -ENOMEM;
>
> +	swdma_dev->chan_status_irq = -1;
> +
>  	swdma_dev->bar = ioremap(pci_resource_start(pdev, 0),
>  				 pci_resource_len(pdev, 0));
>
> @@ -1322,8 +1324,8 @@ static int switchtec_dma_create(struct pci_dev *pdev)
>  	switchtec_dma_chans_free(swdma_dev);
>
>  err_exit:
> -	if (swdma_dev->chan_status_irq)
> -		free_irq(swdma_dev->chan_status_irq, swdma_dev);
> +	if (swdma_dev->chan_status_irq >= 0)
> +		pci_free_irq(pdev, swdma_dev->chan_status_irq, swdma_dev);
>
>  	iounmap(swdma_dev->bar);
>  	kfree(swdma_dev);
> --
> 2.47.3
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 07/11] dmaengine: switchtec-dma: disable channels before freeing on registration failure
  2026-07-27 18:15 ` [PATCH v3 07/11] dmaengine: switchtec-dma: disable channels before freeing on registration failure Logan Gunthorpe
@ 2026-07-27 21:21   ` Frank Li
  2026-07-27 21:51     ` Logan Gunthorpe
  0 siblings, 1 reply; 23+ messages in thread
From: Frank Li @ 2026-07-27 21:21 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, dmaengine, Vinod Koul, Frank Li,
	Kelvin Cao, Thomas Weißschuh, Dave Jiang, George Ge,
	Jaeyoung Chung, Sashiko

On Mon, Jul 27, 2026 at 12:15:22PM -0600, Logan Gunthorpe wrote:
> When switchtec_dma_create() fails after channels have been added to
> dma_dev->channels (either from switchtec_dma_chans_enumerate()'s own
> error path, or from dma_async_device_register() failing), the channels
> are released and freed but never removed from dma_dev->channels.
>
> Add switchtec_dma_chans_disable() which disables interrupts and
> removes the channels from the list.. Call it before releasing and
> freeing channels in both error paths.
>
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Link: https://lore.kernel.org/dmaengine/20260717223431.625EE1F000E9@smtp.kernel.org
> Link: https://lore.kernel.org/dmaengine/20260721162822.05CDD1F000E9@smtp.kernel.org
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> ---
>  drivers/dma/switchtec_dma.c | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
>
> diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c
> index 31feb2816e79..800d8ecd0717 100644
> --- a/drivers/dma/switchtec_dma.c
> +++ b/drivers/dma/switchtec_dma.c
> @@ -1184,6 +1184,20 @@ static void switchtec_dma_chans_free(struct switchtec_dma_dev *swdma_dev)
>  	kfree(swdma_dev->swdma_chans);
>  }
>
> +static void switchtec_dma_chans_disable(struct pci_dev *pdev,
> +					struct switchtec_dma_dev *swdma_dev)
> +{
> +	int i;
> +
> +	if (swdma_dev->chan_status_irq >= 0) {
> +		pci_free_irq(pdev, swdma_dev->chan_status_irq, swdma_dev);
> +		swdma_dev->chan_status_irq = -1;
> +	}
> +
> +	for (i = 0; i < swdma_dev->chan_cnt; i++)
> +		list_del(&swdma_dev->swdma_chans[i]->dma_chan.device_node);
> +}
> +

Maybe historic reason, it is not good to touch dma_chan::device_node.
Suppose some hepler function to manage channels.

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  static int switchtec_dma_chans_enumerate(struct switchtec_dma_dev *swdma_dev,
>  					 struct pci_dev *pdev, int chan_cnt)
>  {
> @@ -1217,6 +1231,7 @@ static int switchtec_dma_chans_enumerate(struct switchtec_dma_dev *swdma_dev,
>  	return chan_cnt;
>
>  err_exit:
> +	switchtec_dma_chans_disable(pdev, swdma_dev);
>  	switchtec_dma_chans_release(pdev, swdma_dev);
>  	switchtec_dma_chans_free(swdma_dev);
>
> @@ -1320,6 +1335,7 @@ static int switchtec_dma_create(struct pci_dev *pdev)
>  	return 0;
>
>  err_chans_release_exit:
> +	switchtec_dma_chans_disable(pdev, swdma_dev);
>  	switchtec_dma_chans_release(pdev, swdma_dev);
>  	switchtec_dma_chans_free(swdma_dev);
>
> --
> 2.47.3
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 08/11] dmaengine: switchtec-dma: fix use-after-free of swdma_dev in remove()
  2026-07-27 18:15 ` [PATCH v3 08/11] dmaengine: switchtec-dma: fix use-after-free of swdma_dev in remove() Logan Gunthorpe
@ 2026-07-27 21:23   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2026-07-27 21:23 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, dmaengine, Vinod Koul, Frank Li,
	Kelvin Cao, Thomas Weißschuh, Dave Jiang, George Ge,
	Jaeyoung Chung, Sashiko

On Mon, Jul 27, 2026 at 12:15:23PM -0600, Logan Gunthorpe wrote:
> dma_async_device_unregister() can drop the last reference on dma_dev
> and free swdma_dev synchronously via switchtec_dma_release(), but
> switchtec_dma_remove() then uses swdma_dev->bar for iounmap().
>
> Cache bar in a local variable before the unregister call.
>
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Link: https://lore.kernel.org/dmaengine/20260717223431.625EE1F000E9@smtp.kernel.org
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/dma/switchtec_dma.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c
> index 800d8ecd0717..d73506b5cabc 100644
> --- a/drivers/dma/switchtec_dma.c
> +++ b/drivers/dma/switchtec_dma.c
> @@ -1384,6 +1384,7 @@ static int switchtec_dma_probe(struct pci_dev *pdev,
>  static void switchtec_dma_remove(struct pci_dev *pdev)
>  {
>  	struct switchtec_dma_dev *swdma_dev = pci_get_drvdata(pdev);
> +	void __iomem *bar = swdma_dev->bar;
>
>  	switchtec_dma_chans_release(pdev, swdma_dev);
>
> @@ -1396,7 +1397,7 @@ static void switchtec_dma_remove(struct pci_dev *pdev)
>
>  	dma_async_device_unregister(&swdma_dev->dma_dev);
>
> -	iounmap(swdma_dev->bar);
> +	iounmap(bar);
>  	pci_release_mem_regions(pdev);
>  	pci_disable_device(pdev);
>  }
> --
> 2.47.3
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 09/11] dmaengine: ioat: disable relaxed ordering before registering the device
  2026-07-27 18:15 ` [PATCH v3 09/11] dmaengine: ioat: disable relaxed ordering before registering the device Logan Gunthorpe
@ 2026-07-27 21:27   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2026-07-27 21:27 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, dmaengine, Vinod Koul, Frank Li,
	Kelvin Cao, Thomas Weißschuh, Dave Jiang, George Ge,
	Jaeyoung Chung, Sashiko

On Mon, Jul 27, 2026 at 12:15:24PM -0600, Logan Gunthorpe wrote:
> ioat3_dma_probe() disabled PCIe relaxed ordering after calling
> dma_async_device_register(), so if an error occurs and the code jumps
> to err_disable_interrupts, the function returns with the device still
> registered in the core's dma_device_list while the caller frees the
> ioatdma_device struct, leaving a dangling registration that anything
> walking the device list can dereference after it's been freed.
>
> Move the capability read/write ahead of dma_async_device_register()
> instead. Nothing after registration depends on relaxed ordering
> already being disabled, and nothing before it depends on the device
> being registered, so this is a plain reordering. It also means every
> remaining step after registration can't fail, so there's no need to
> ever have to unregister the device once registered.
>
> Fixes: 511deae0261c ("dmaengine: ioatdma: disable relaxed ordering for ioatdma")
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Link: https://lore.kernel.org/dmaengine/20260707165906.249F41F000E9@smtp.kernel.org
> Acked-by: Dave Jiang <dave.jiang@intel.com>
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/dma/ioat/init.c | 18 +++++++++---------
>  1 file changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/dma/ioat/init.c b/drivers/dma/ioat/init.c
> index 737496391109..a57024c4b066 100644
> --- a/drivers/dma/ioat/init.c
> +++ b/drivers/dma/ioat/init.c
> @@ -1170,15 +1170,6 @@ static int ioat3_dma_probe(struct ioatdma_device *ioat_dma, int dca)
>  		       ioat_chan->reg_base + IOAT_DCACTRL_OFFSET);
>  	}
>
> -	err = dma_async_device_register(&ioat_dma->dma_dev);
> -	if (err)
> -		goto err_disable_interrupts;
> -
> -	ioat_kobject_add(ioat_dma, &ioat_ktype);
> -
> -	if (dca)
> -		ioat_dma->dca = ioat_dca_init(pdev, ioat_dma->reg_base);
> -
>  	/* disable relaxed ordering */
>  	err = pcie_capability_read_word(pdev, PCI_EXP_DEVCTL, &val16);
>  	if (err) {
> @@ -1194,6 +1185,15 @@ static int ioat3_dma_probe(struct ioatdma_device *ioat_dma, int dca)
>  		goto err_disable_interrupts;
>  	}
>
> +	err = dma_async_device_register(&ioat_dma->dma_dev);
> +	if (err)
> +		goto err_disable_interrupts;
> +
> +	ioat_kobject_add(ioat_dma, &ioat_ktype);
> +
> +	if (dca)
> +		ioat_dma->dca = ioat_dca_init(pdev, ioat_dma->reg_base);
> +
>  	if (ioat_dma->cap & IOAT_CAP_DPS)
>  		writeb(ioat_pending_level + 1,
>  		       ioat_dma->reg_base + IOAT_PREFETCH_LIMIT_OFFSET);
> --
> 2.47.3
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 10/11] dmaengine: ioat: use sysfs_emit() in per-channel sysfs show()
  2026-07-27 18:15 ` [PATCH v3 10/11] dmaengine: ioat: use sysfs_emit() in per-channel sysfs show() Logan Gunthorpe
@ 2026-07-27 21:28   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2026-07-27 21:28 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, dmaengine, Vinod Koul, Frank Li,
	Kelvin Cao, Thomas Weißschuh, Dave Jiang, George Ge,
	Jaeyoung Chung

On Mon, Jul 27, 2026 at 12:15:25PM -0600, Logan Gunthorpe wrote:
> Convert the sprintf() calls in the per-channel sysfs attribute show()
> functions to sysfs_emit().
>
> Acked-by: Dave Jiang <dave.jiang@intel.com>
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/dma/ioat/sysfs.c | 22 +++++++++++-----------
>  1 file changed, 11 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/dma/ioat/sysfs.c b/drivers/dma/ioat/sysfs.c
> index e796ddb5383f..976134df8108 100644
> --- a/drivers/dma/ioat/sysfs.c
> +++ b/drivers/dma/ioat/sysfs.c
> @@ -24,12 +24,12 @@ static ssize_t cap_show(struct dma_chan *c, char *page)
>  {
>  	struct dma_device *dma = c->device;
>
> -	return sprintf(page, "copy%s%s%s%s%s\n",
> -		       dma_has_cap(DMA_PQ, dma->cap_mask) ? " pq" : "",
> -		       dma_has_cap(DMA_PQ_VAL, dma->cap_mask) ? " pq_val" : "",
> -		       dma_has_cap(DMA_XOR, dma->cap_mask) ? " xor" : "",
> -		       dma_has_cap(DMA_XOR_VAL, dma->cap_mask) ? " xor_val" : "",
> -		       dma_has_cap(DMA_INTERRUPT, dma->cap_mask) ? " intr" : "");
> +	return sysfs_emit(page, "copy%s%s%s%s%s\n",
> +		dma_has_cap(DMA_PQ, dma->cap_mask) ? " pq" : "",
> +		dma_has_cap(DMA_PQ_VAL, dma->cap_mask) ? " pq_val" : "",
> +		dma_has_cap(DMA_XOR, dma->cap_mask) ? " xor" : "",
> +		dma_has_cap(DMA_XOR_VAL, dma->cap_mask) ? " xor_val" : "",
> +		dma_has_cap(DMA_INTERRUPT, dma->cap_mask) ? " intr" : "");
>
>  }
>  static const struct ioat_sysfs_entry ioat_cap_attr = __ATTR_RO(cap);
> @@ -39,8 +39,8 @@ static ssize_t version_show(struct dma_chan *c, char *page)
>  	struct dma_device *dma = c->device;
>  	struct ioatdma_device *ioat_dma = to_ioatdma_device(dma);
>
> -	return sprintf(page, "%d.%d\n",
> -		       ioat_dma->version >> 4, ioat_dma->version & 0xf);
> +	return sysfs_emit(page, "%d.%d\n",
> +			   ioat_dma->version >> 4, ioat_dma->version & 0xf);
>  }
>  static const struct ioat_sysfs_entry ioat_version_attr = __ATTR_RO(version);
>
> @@ -118,7 +118,7 @@ static ssize_t ring_size_show(struct dma_chan *c, char *page)
>  {
>  	struct ioatdma_chan *ioat_chan = to_ioat_chan(c);
>
> -	return sprintf(page, "%d\n", (1 << ioat_chan->alloc_order) & ~1);
> +	return sysfs_emit(page, "%d\n", (1 << ioat_chan->alloc_order) & ~1);
>  }
>  static const struct ioat_sysfs_entry ring_size_attr = __ATTR_RO(ring_size);
>
> @@ -127,7 +127,7 @@ static ssize_t ring_active_show(struct dma_chan *c, char *page)
>  	struct ioatdma_chan *ioat_chan = to_ioat_chan(c);
>
>  	/* ...taken outside the lock, no need to be precise */
> -	return sprintf(page, "%d\n", ioat_ring_active(ioat_chan));
> +	return sysfs_emit(page, "%d\n", ioat_ring_active(ioat_chan));
>  }
>  static const struct ioat_sysfs_entry ring_active_attr = __ATTR_RO(ring_active);
>
> @@ -135,7 +135,7 @@ static ssize_t intr_coalesce_show(struct dma_chan *c, char *page)
>  {
>  	struct ioatdma_chan *ioat_chan = to_ioat_chan(c);
>
> -	return sprintf(page, "%d\n", ioat_chan->intr_coalesce);
> +	return sysfs_emit(page, "%d\n", ioat_chan->intr_coalesce);
>  }
>
>  static ssize_t intr_coalesce_store(struct dma_chan *c, const char *page,
> --
> 2.47.3
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 11/11] dmaengine: plx_dma: fix NULL pointer deref in plx_dma_isr()
  2026-07-27 18:15 ` [PATCH v3 11/11] dmaengine: plx_dma: fix NULL pointer deref in plx_dma_isr() Logan Gunthorpe
@ 2026-07-27 21:29   ` Frank Li
  0 siblings, 0 replies; 23+ messages in thread
From: Frank Li @ 2026-07-27 21:29 UTC (permalink / raw)
  To: Logan Gunthorpe
  Cc: linux-kernel, linux-pci, dmaengine, Vinod Koul, Frank Li,
	Kelvin Cao, Thomas Weißschuh, Dave Jiang, George Ge,
	Jaeyoung Chung, Sangyun Kim, Kyungwook Boo

On Mon, Jul 27, 2026 at 12:15:26PM -0600, Logan Gunthorpe wrote:
> plx_dma_create() registered the interrupt handler with request_irq()
> before initializing plxdev->bar. If the device raised an interrupt in
> that window, plx_dma_isr() would dereference the still-NULL bar.
>
> Move the bar assignment ahead of request_irq() so everything the
> handler can touch is initialized before it can run.
>
> Reported-by: Sangyun Kim <sangyun.kim@snu.ac.kr>
> Reported-by: Kyungwook Boo <bookyungwook@gmail.com>
> Link: https://lore.kernel.org/all/20260610112121.676561-1-jjy600901@snu.ac.kr
> Fixes: c2dbcaa8c672 ("dmaengine: plx-dma: Implement hardware initialization and cleanup")
> Signed-off-by: Logan Gunthorpe <logang@deltatee.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>  drivers/dma/plx_dma.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/dma/plx_dma.c b/drivers/dma/plx_dma.c
> index 84941a918b01..409898e92c32 100644
> --- a/drivers/dma/plx_dma.c
> +++ b/drivers/dma/plx_dma.c
> @@ -504,17 +504,17 @@ static int plx_dma_create(struct pci_dev *pdev)
>  	if (!plxdev)
>  		return -ENOMEM;
>
> -	rc = request_irq(pci_irq_vector(pdev, 0), plx_dma_isr, 0,
> -			 KBUILD_MODNAME, plxdev);
> -	if (rc)
> -		goto free_plx;
> -
>  	spin_lock_init(&plxdev->ring_lock);
>  	tasklet_setup(&plxdev->desc_task, plx_dma_desc_task);
>
>  	RCU_INIT_POINTER(plxdev->pdev, pdev);
>  	plxdev->bar = pcim_iomap_table(pdev)[0];
>
> +	rc = request_irq(pci_irq_vector(pdev, 0), plx_dma_isr, 0,
> +			 KBUILD_MODNAME, plxdev);
> +	if (rc)
> +		goto free_plx;
> +
>  	dma = &plxdev->dma_dev;
>  	INIT_LIST_HEAD(&dma->channels);
>  	dma_cap_set(DMA_MEMCPY, dma->cap_mask);
> --
> 2.47.3
>

^ permalink raw reply	[flat|nested] 23+ messages in thread

* Re: [PATCH v3 07/11] dmaengine: switchtec-dma: disable channels before freeing on registration failure
  2026-07-27 21:21   ` Frank Li
@ 2026-07-27 21:51     ` Logan Gunthorpe
  0 siblings, 0 replies; 23+ messages in thread
From: Logan Gunthorpe @ 2026-07-27 21:51 UTC (permalink / raw)
  To: Frank Li
  Cc: linux-kernel, linux-pci, dmaengine, Vinod Koul, Frank Li,
	Kelvin Cao, Thomas Weißschuh, Dave Jiang, George Ge,
	Jaeyoung Chung, Sashiko



On 2026-07-27 15:21, Frank Li wrote:
> On Mon, Jul 27, 2026 at 12:15:22PM -0600, Logan Gunthorpe wrote:
>> +static void switchtec_dma_chans_disable(struct pci_dev *pdev,
>> +					struct switchtec_dma_dev *swdma_dev)
>> +{
>> +	int i;
>> +
>> +	if (swdma_dev->chan_status_irq >= 0) {
>> +		pci_free_irq(pdev, swdma_dev->chan_status_irq, swdma_dev);
>> +		swdma_dev->chan_status_irq = -1;
>> +	}
>> +
>> +	for (i = 0; i < swdma_dev->chan_cnt; i++)
>> +		list_del(&swdma_dev->swdma_chans[i]->dma_chan.device_node);
>> +}
>> +
> 
> Maybe historic reason, it is not good to touch dma_chan::device_node.
> Suppose some hepler function to manage channels.
> 
> Reviewed-by: Frank Li <Frank.Li@nxp.com>

Ok, thanks. When I have some free time I'll see if I can clean that up,
but not for this series.

Logan

^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2026-07-27 21:51 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-27 18:15 [PATCH v3 00/11] dmaengine: miscellaneous fixes for ioat, switchtec_dma and plx_dma Logan Gunthorpe
2026-07-27 18:15 ` [PATCH v3 01/11] dmaengine: switchtec-dma: fix double-free in switchtec_dma_free_desc() Logan Gunthorpe
2026-07-27 20:42   ` Frank Li
2026-07-27 18:15 ` [PATCH v3 02/11] dmaengine: switchtec-dma: fix resource leak in alloc_chan_resources Logan Gunthorpe
2026-07-27 20:44   ` Frank Li
2026-07-27 18:15 ` [PATCH v3 03/11] dmaengine: switchtec-dma: halt channel on alloc_chan_resources error Logan Gunthorpe
2026-07-27 18:15 ` [PATCH v3 04/11] dmaengine: switchtec-dma: fix channel leak on registration failure Logan Gunthorpe
2026-07-27 20:52   ` Frank Li
2026-07-27 18:15 ` [PATCH v3 05/11] dmaengine: switchtec-dma: make switchtec_dma_chans_release() void Logan Gunthorpe
2026-07-27 20:54   ` Frank Li
2026-07-27 18:15 ` [PATCH v3 06/11] dmaengine: switchtec-dma: fix chan_status_irq cleanup on create() error Logan Gunthorpe
2026-07-27 20:55   ` Frank Li
2026-07-27 18:15 ` [PATCH v3 07/11] dmaengine: switchtec-dma: disable channels before freeing on registration failure Logan Gunthorpe
2026-07-27 21:21   ` Frank Li
2026-07-27 21:51     ` Logan Gunthorpe
2026-07-27 18:15 ` [PATCH v3 08/11] dmaengine: switchtec-dma: fix use-after-free of swdma_dev in remove() Logan Gunthorpe
2026-07-27 21:23   ` Frank Li
2026-07-27 18:15 ` [PATCH v3 09/11] dmaengine: ioat: disable relaxed ordering before registering the device Logan Gunthorpe
2026-07-27 21:27   ` Frank Li
2026-07-27 18:15 ` [PATCH v3 10/11] dmaengine: ioat: use sysfs_emit() in per-channel sysfs show() Logan Gunthorpe
2026-07-27 21:28   ` Frank Li
2026-07-27 18:15 ` [PATCH v3 11/11] dmaengine: plx_dma: fix NULL pointer deref in plx_dma_isr() Logan Gunthorpe
2026-07-27 21:29   ` Frank Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome