DMA Engine development
 help / color / mirror / Atom feed
* [PATCH v3 00/24] dmaengine: dw-edma: Support dynamic LL appends
@ 2026-07-27 17:02 Koichiro Den
  2026-07-27 17:03 ` [PATCH v3 01/24] dmaengine: dw-edma: Add dw_edma_core_ll_cur_idx() to get current LL entry index Koichiro Den
                   ` (23 more replies)
  0 siblings, 24 replies; 40+ messages in thread
From: Koichiro Den @ 2026-07-27 17:02 UTC (permalink / raw)
  To: Manivannan Sadhasivam, Vinod Koul, Frank Li, Gustavo Pimentel,
	Kees Cook, Krzysztof Wilczyński, Kishon Vijay Abraham I,
	Bjorn Helgaas, Christoph Hellwig, Serge Semin, Cai Huoqing,
	Niklas Cassel
  Cc: Devendra K Verma, dmaengine, linux-kernel

Hi,

This is v3 of the dw-edma dynamic-append work originally proposed by
Frank Li in his RFT:

  https://lore.kernel.org/r/20260109-edma_dymatic-v1-0-9a98c9c98536@nxp.com/

The driver currently treats each linked list as a finite transfer and
waits for completion before publishing more work. This series turns the
list into a circular producer/consumer ring and lets LL channels accept
new requests while running.

The motivation and hardware observations are unchanged from v2, linked
below. v3 mainly addresses the review feedback, especially the
event/restart races reported by Sashiko.

With multiple DMAengine descriptors in one ring, entry reclamation and
descriptor completion need separate boundaries. The series records
IRQ-paired LLP samples, uses a conservative running boundary for both
eDMA and HDMA, and centralizes when a stopped channel needs another
doorbell.

The recovery patches add an opt-in safeguard for eDMA with direction
reset operations. On one integration, sustained multi-channel traffic
could leave a channel stopped with pending entries. Repeated doorbells
did not restart it, while toggling ENGINE_EN did. Doorbell timing
remains the leading suspect: under heavy multi-channel load,
channel-status updates visible to software appear to lag internal
start/stop transitions. That said, the exact trigger is still unknown.
Any insight from Synopsys would be appreciated. Recovery was not entered
in the fio/nvmet_pci_epf tests below.

This series is based on dmaengine/next.


Re-testing with v3
==================

I tested v3 on the following three testbeds:

- eDMA: RK3588 Rock 5B, DWC PCIe v5.60a
        R-Car S4, DWC PCIe v5.20a
- HDMA: SpacemiT K3, DWC PCIe v6.30a [1]

1. fio

   The fio setup uses nvmet_pci_epf with a null_blk-backed namespace,
   runtime=30s, ramp_time=5s. The "Before" values reuse the baseline
   measurements reported with v2. The "After" values are three
   consecutive v3 runs.

   NOTE: The fio tests use nvmet_pci_epf, which does not keep the DMA
         engine continuously busy. A workload that rarely lets the
         engine stop would show the benefit of dynamic appends more
         directly.

   - eDMA (RK3588)

     NOTE: The eDMA Before results include the separate regression
           described in [2].

     Summary by group (BW delta %)
       all          n=26 mean=+1135.8 median=+122.1 min= +39.2 max=+5358.8
       read         n=14 mean=+2006.2 median=+903.7 min= +51.6 max=+5358.8
       write        n=11 mean=+105.6 median=+111.3 min= +39.2 max=+176.8
       qd32         n=16 mean=+1783.3 median=+174.6 min= +72.1 max=+5358.8
       q1           n= 9 mean= +79.5 median= +58.2 min= +39.2 max=+202.6
       small 4K     n= 6 mean= +99.4 median= +78.3 min= +39.2 max=+176.8
       large >=128K n=20 mean=+1446.7 median=+126.8 min= +47.8 max=+5358.8

     Before mean -> After mean (MiB/s)
       Case                         Before             After              Delta
       ---------------------------  -----------------  -----------------  ------
       Rnd read     4KB q1  1j          19.2 (sd 7.5)      29.2 (sd 7.2)   +51.6%
       Rnd read     4KB q32 1j          88.7 (sd 2.1)    152.7 (sd 58.7)   +72.1%
       Rnd read     4KB q32 4j          88.7 (sd 1.3)    163.7 (sd 78.0)   +84.5%
       Rnd read   128KB q1  1j       420.0 (sd 134.6)   685.0 (sd 123.2)   +63.1%
       Rnd read   128KB q32 1j        142.0 (sd 37.7)   2547.7 (sd 40.7)  +1694.1%
       Rnd read   128KB q32 4j         63.7 (sd 10.6)   3027.0 (sd 27.6)  +4654.5%
       Rnd read   512KB q1  1j        572.0 (sd 35.8)    943.0 (sd 19.5)   +64.9%
       Rnd read   512KB q32 1j         66.8 (sd 10.8)   3021.0 (sd 25.1)  +4422.5%
       Rnd read   512KB q32 4j         55.4 (sd 12.0)   3026.0 (sd 28.1)  +5358.8%
       Rnd write    4KB q1  1j          20.7 (sd 7.0)      28.9 (sd 2.2)   +39.2%
       Rnd write    4KB q32 1j          42.5 (sd 0.9)    115.7 (sd 19.1)  +172.4%
       Rnd write    4KB q32 4j          41.7 (sd 1.6)    115.3 (sd 19.3)  +176.8%
       Rnd write  128KB q1  1j        330.0 (sd 90.1)   520.0 (sd 105.5)   +57.6%
       Rnd write  128KB q32 1j       624.0 (sd 111.5)   1318.3 (sd 63.8)  +111.3%
       Rnd write  128KB q32 4j        659.3 (sd 61.8)   1304.7 (sd 67.0)   +97.9%
       Seq read   128KB q1  1j        260.7 (sd 25.8)   788.7 (sd 142.0)  +202.6%
       Seq read   128KB q32 1j        149.7 (sd 30.9)   2551.7 (sd 96.7)  +1604.9%
       Seq read   512KB q1  1j        578.0 (sd 32.2)    914.3 (sd 10.1)   +58.2%
       Seq read   512KB q32 1j         65.0 (sd 10.6)   3025.3 (sd 22.0)  +4554.4%
       Seq read     1MB q32 1j         57.3 (sd 18.8)   3037.3 (sd 23.8)  +5200.8%
       Seq write  128KB q1  1j        272.3 (sd 62.0)   626.7 (sd 159.9)  +130.1%
       Seq write  128KB q32 1j       597.0 (sd 105.7)   1318.0 (sd 64.1)  +120.8%
       Seq write  512KB q1  1j        476.7 (sd 26.7)    704.7 (sd 23.0)   +47.8%
       Seq write  512KB q32 1j        710.7 (sd 44.0)   1305.7 (sd 59.3)   +83.7%
       Seq write    1MB q32 1j       546.0 (sd 100.4)   1220.3 (sd 57.7)  +123.5%
       Rnd rdwr  4K..1MB q8  4j       247.3 (sd 16.3)    947.7 (sd 84.5)  +283.2%

   - HDMA (SpacemiT K3)

     Summary by group (BW delta %)
       all          n=26 mean= +89.8 median=+103.3 min= -30.3 max=+182.9
       read         n=14 mean= +80.4 median= +79.2 min= -30.3 max=+182.9
       write        n=11 mean= +97.3 median=+138.1 min= -25.0 max=+151.5
       qd32         n=16 mean=+117.3 median=+117.3 min= +67.8 max=+182.9
       q1           n= 9 mean= +35.5 median=  +9.6 min= -30.3 max=+151.5
       small 4K     n= 6 mean= +95.5 median=+117.3 min= -17.4 max=+182.9
       large >=128K n=20 mean= +88.0 median=+102.0 min= -30.3 max=+151.5

     Before mean -> After mean (MiB/s)
       Case                         Before             After              Delta
       ---------------------------  -----------------  -----------------  ------
       Rnd read     4KB q1  1j          52.5 (sd 3.5)     43.4 (sd 17.4)   -17.4%
       Rnd read     4KB q32 1j        108.1 (sd 90.9)    305.7 (sd 30.9)  +182.9%
       Rnd read     4KB q32 4j        117.0 (sd 84.9)    308.3 (sd 30.6)  +163.5%
       Rnd read   128KB q1  1j       835.7 (sd 139.6)    582.3 (sd 84.1)   -30.3%
       Rnd read   128KB q32 1j        802.7 (sd 67.7)   1619.3 (sd 31.0)  +101.7%
       Rnd read   128KB q32 4j       931.3 (sd 262.1)   1628.0 (sd 45.9)   +74.8%
       Rnd read   512KB q1  1j       411.0 (sd 144.0)   831.3 (sd 187.5)  +102.3%
       Rnd read   512KB q32 1j       969.0 (sd 210.7)   1626.3 (sd 44.7)   +67.8%
       Rnd read   512KB q32 4j       889.7 (sd 298.0)   1634.0 (sd 52.8)   +83.7%
       Rnd write    4KB q1  1j         46.0 (sd 15.5)     50.4 (sd 13.6)    +9.6%
       Rnd write    4KB q32 1j         117.7 (sd 4.0)     250.7 (sd 0.6)  +113.0%
       Rnd write    4KB q32 4j         113.0 (sd 5.3)     250.3 (sd 0.6)  +121.5%
       Rnd write  128KB q1  1j       606.7 (sd 149.0)    520.0 (sd 65.5)   -14.3%
       Rnd write  128KB q32 1j       533.6 (sd 512.3)    1270.7 (sd 2.5)  +138.1%
       Rnd write  128KB q32 4j       526.0 (sd 514.9)    1271.0 (sd 1.0)  +141.7%
       Seq read   128KB q1  1j       626.3 (sd 247.5)    811.7 (sd 45.9)   +29.6%
       Seq read   128KB q32 1j        783.3 (sd 51.1)    1600.0 (sd 4.0)  +104.3%
       Seq read   512KB q1  1j       464.0 (sd 191.5)    992.3 (sd 20.0)  +113.9%
       Seq read   512KB q32 1j       918.3 (sd 241.8)    1600.7 (sd 1.2)   +74.3%
       Seq read     1MB q32 1j       918.7 (sd 290.5)    1603.0 (sd 1.0)   +74.5%
       Seq write  128KB q1  1j        611.0 (sd 79.8)    458.0 (sd 15.7)   -25.0%
       Seq write  128KB q32 1j       521.8 (sd 515.3)    1270.0 (sd 2.0)  +143.4%
       Seq write  512KB q1  1j       328.3 (sd 268.7)    825.7 (sd 35.9)  +151.5%
       Seq write  512KB q32 1j       519.6 (sd 516.6)    1271.3 (sd 1.2)  +144.7%
       Seq write    1MB q32 1j       515.1 (sd 517.8)    1268.3 (sd 1.5)  +146.2%
       Rnd rdwr  4K..1MB q8  4j       355.3 (sd 64.7)     846.3 (sd 2.1)  +138.2%

2. pci_endpoint_test

   READ_TEST and WRITE_TEST passed with v3 on all three testbeds.

3. R-Car S4 (PCIe Gen4 x2, DWC PCIe controller v5.20a, eDMA) stress

   The non-upstream NTB transport/netdev saturated four HW channels in
   each direction concurrently from multiple QPs. With v3, it still
   reached EP->RC 18.7 Gbit/s and RC->EP 15.7 Gbit/s with iperf3 -ub0,
   while keeping the DMA controller almost continuously busy.

[1] K3 was tested on an Ubuntu kernel with the prerequisite patches
    backported (+ some tweaks on top), not directly on the upstream
    base. The "Before" and "After" kernels differ only by this series.

[2] The current base includes commit 35de39e4511f ("dmaengine: dw-edma:
    Defer channel IRQ handling to workqueue"), which defers channel IRQ
    handling to an unbound workqueue. Under CPU pressure, some workloads
    can see delayed completion processing and idle gaps between
    descriptors. Dynamic appends largely hide those gaps by keeping the
    engine fed.

    A BH workqueue would improve the nvmet_pci_epf workload, but it is
    not a complete replacement because BH workqueues are per-CPU.
    Retaining cross-channel CPU distribution would require the driver to
    choose target CPUs and account for housekeeping masks and CPU
    hotplug. That is too much complexity for a quick fix, so I have not
    posted a separate change.

    This partly explains the unusually large eDMA gain in these tests.

Best regards,
Koichiro
---
Changes in v3:
  - Main changes:
    * Serialize IRQ event capture and ABORT handling with channel restart,
      so deferred events cannot cross into a later hardware run. (Sashiko)
    * Record each descriptor's physical LL range and validate it before
      consuming IRQ-paired progress. Keep ring accounting valid across
      termination, abort, and full resynchronization. (Frank, Sashiko)
    * Rework stopped-tail and STOP/PAUSE handling: re-sample LLP before
      restart, add one bounded eDMA recheck, and drain published entries
      before completing a request. (Frank, Sashiko)
    * Move LL interrupt placement into the common core and use the same
      four-entry interval for eDMA and HDMA. (Frank)
    * Restrict recovery to providers with usable direction-reset
      operations and serialize it with IRQ/ABORT handling and teardown.
      Rebuild all exposed LL contexts and flush remote LL writes before
      re-enabling the engine. (Sashiko)
  - Many other smaller fixes, refinements, and patch reorganizations
    came from the v2 review, especially Sashiko's feedback. Each patch
    has its own changelog below the --- separator, so the details are
    not repeated here.

Changes in v2:
  - v2 is a substantial rework; per-patch changelogs contain the details:
    * Rebased onto dmaengine/next.
    * Moved the remaining v1 fixes and state serialization changes into
      the independent groundwork series, now merged in the base.
    * Reworked ring progress around IRQ-paired LLP samples, conservative
      running boundaries, and stopped-tail reconciliation.
    * Reworked STOP/PAUSE handling and added full ring resynchronization
      plus optional direction recovery before enabling dynamic
      submission.
    * Updated trace support for the reworked paths and added engine
      recovery tracing.

v2: https://lore.kernel.org/r/20260723084150.521366-1-den@valinux.co.jp/
v1: https://lore.kernel.org/r/20260615154111.2174161-1-den@valinux.co.jp/


Frank Li (5):
  dmaengine: dw-edma: Add dw_edma_core_ll_cur_idx() to get current LL
    entry index
  dmaengine: dw-edma: Make DMA link list work as a circular buffer
  dmaengine: dw-edma: Move callback result helper before LL helpers
  dmaengine: dw-edma: Dynamically append requests while running
  dmaengine: dw-edma: Add trace support

Koichiro Den (19):
  dmaengine: dw-edma: Add dw_edma_core_ll_clear() to clear LL
    control-word
  dmaengine: dw-edma: Factor out linked-list transfer start
  dmaengine: dw-edma: Dispatch DONE interrupts by channel request
  dmaengine: dw-edma: Centralize LL doorbell decisions
  dmaengine: dw-edma: Prepare LL progress event handling
  dmaengine: dw-edma: Prepare deferred IRQ reporting for LL events
  dmaengine: dw-edma: Prepare LL kicks for event serialization
  dmaengine: dw-edma: Serialize LL event capture with channel kicks
  dmaengine: dw-edma: Keep channels stopped while ABORT is pending
  dmaengine: dw-edma: Reclaim issued descriptors from IRQ-paired LL
    progress
  dmaengine: dw-edma: Add LL interrupt placement policy
  dmaengine: dw-edma: Recheck stopped LL channels before restart
  dmaengine: dw-edma: Use HDMA watermarks as progress events
  dmaengine: dw-edma: Recover stopped channels from tx_status()
  dmaengine: dw-edma: Make the LL ring reset a full channel resync
  dmaengine: dw-edma: Drain LL entries for STOP and PAUSE
  dmaengine: dw-edma: Add engine reset and enable operations
  dmaengine: dw-edma: Add engine recovery infrastructure
  dmaengine: dw-edma: Detect and recover a stalled eDMA engine

 drivers/dma/dw-edma/Makefile          |    2 +
 drivers/dma/dw-edma/dw-edma-core.c    | 1557 ++++++++++++++++++++++---
 drivers/dma/dw-edma/dw-edma-core.h    |  163 ++-
 drivers/dma/dw-edma/dw-edma-trace.c   |    4 +
 drivers/dma/dw-edma/dw-edma-trace.h   |  169 +++
 drivers/dma/dw-edma/dw-edma-v0-core.c |  201 +++-
 drivers/dma/dw-edma/dw-hdma-v0-core.c |  164 ++-
 drivers/dma/dw-edma/dw-hdma-v0-regs.h |    1 +
 8 files changed, 1994 insertions(+), 267 deletions(-)
 create mode 100644 drivers/dma/dw-edma/dw-edma-trace.c
 create mode 100644 drivers/dma/dw-edma/dw-edma-trace.h

base-commit: 0613e7934ee233d726af8d8c89f251a1c4df738d
-- 
2.51.0


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

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

Thread overview: 40+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-27 17:02 [PATCH v3 00/24] dmaengine: dw-edma: Support dynamic LL appends Koichiro Den
2026-07-27 17:03 ` [PATCH v3 01/24] dmaengine: dw-edma: Add dw_edma_core_ll_cur_idx() to get current LL entry index Koichiro Den
2026-07-27 17:17   ` sashiko-bot
2026-07-27 17:03 ` [PATCH v3 02/24] dmaengine: dw-edma: Add dw_edma_core_ll_clear() to clear LL control-word Koichiro Den
2026-07-27 17:03 ` [PATCH v3 03/24] dmaengine: dw-edma: Factor out linked-list transfer start Koichiro Den
2026-07-27 17:03 ` [PATCH v3 04/24] dmaengine: dw-edma: Make DMA link list work as a circular buffer Koichiro Den
2026-07-27 17:24   ` sashiko-bot
2026-07-27 17:03 ` [PATCH v3 05/24] dmaengine: dw-edma: Move callback result helper before LL helpers Koichiro Den
2026-07-27 17:03 ` [PATCH v3 06/24] dmaengine: dw-edma: Dispatch DONE interrupts by channel request Koichiro Den
2026-07-27 17:13   ` sashiko-bot
2026-07-27 19:11   ` Frank Li
2026-07-27 17:03 ` [PATCH v3 07/24] dmaengine: dw-edma: Centralize LL doorbell decisions Koichiro Den
2026-07-27 17:23   ` sashiko-bot
2026-07-27 19:14     ` Frank Li
2026-07-27 17:03 ` [PATCH v3 08/24] dmaengine: dw-edma: Prepare LL progress event handling Koichiro Den
2026-07-27 19:47   ` Frank Li
2026-07-27 20:09   ` Frank Li
2026-07-27 17:03 ` [PATCH v3 09/24] dmaengine: dw-edma: Prepare deferred IRQ reporting for LL events Koichiro Den
2026-07-27 20:12   ` Frank Li
2026-07-27 17:03 ` [PATCH v3 10/24] dmaengine: dw-edma: Prepare LL kicks for event serialization Koichiro Den
2026-07-27 17:03 ` [PATCH v3 11/24] dmaengine: dw-edma: Serialize LL event capture with channel kicks Koichiro Den
2026-07-27 17:03 ` [PATCH v3 12/24] dmaengine: dw-edma: Keep channels stopped while ABORT is pending Koichiro Den
2026-07-27 17:19   ` sashiko-bot
2026-07-27 17:03 ` [PATCH v3 13/24] dmaengine: dw-edma: Reclaim issued descriptors from IRQ-paired LL progress Koichiro Den
2026-07-27 17:03 ` [PATCH v3 14/24] dmaengine: dw-edma: Add LL interrupt placement policy Koichiro Den
2026-07-27 17:21   ` sashiko-bot
2026-07-27 17:03 ` [PATCH v3 15/24] dmaengine: dw-edma: Recheck stopped LL channels before restart Koichiro Den
2026-07-27 17:21   ` sashiko-bot
2026-07-27 17:03 ` [PATCH v3 16/24] dmaengine: dw-edma: Use HDMA watermarks as progress events Koichiro Den
2026-07-27 17:03 ` [PATCH v3 17/24] dmaengine: dw-edma: Recover stopped channels from tx_status() Koichiro Den
2026-07-27 17:03 ` [PATCH v3 18/24] dmaengine: dw-edma: Make the LL ring reset a full channel resync Koichiro Den
2026-07-27 17:24   ` sashiko-bot
2026-07-27 17:03 ` [PATCH v3 19/24] dmaengine: dw-edma: Drain LL entries for STOP and PAUSE Koichiro Den
2026-07-27 17:30   ` sashiko-bot
2026-07-27 17:03 ` [PATCH v3 20/24] dmaengine: dw-edma: Dynamically append requests while running Koichiro Den
2026-07-27 17:03 ` [PATCH v3 21/24] dmaengine: dw-edma: Add engine reset and enable operations Koichiro Den
2026-07-27 17:03 ` [PATCH v3 22/24] dmaengine: dw-edma: Add engine recovery infrastructure Koichiro Den
2026-07-27 17:03 ` [PATCH v3 23/24] dmaengine: dw-edma: Detect and recover a stalled eDMA engine Koichiro Den
2026-07-27 17:37   ` sashiko-bot
2026-07-27 17:03 ` [PATCH v3 24/24] dmaengine: dw-edma: Add trace support Koichiro Den

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