From: Frank Li <Frank.li@oss.nxp.com>
To: Koichiro Den <den@valinux.co.jp>
Cc: "Vinod Koul" <vkoul@kernel.org>, "Frank Li" <Frank.Li@kernel.org>,
"Manivannan Sadhasivam" <mani@kernel.org>,
"Gustavo Pimentel" <Gustavo.Pimentel@synopsys.com>,
"Kees Cook" <kees@kernel.org>,
"Krzysztof Wilczyński" <kwilczynski@kernel.org>,
"Kishon Vijay Abraham I" <kishon@kernel.org>,
"Bjorn Helgaas" <bhelgaas@google.com>,
"Christoph Hellwig" <hch@lst.de>,
"Serge Semin" <fancer.lancer@gmail.com>,
"Cai Huoqing" <cai.huoqing@linux.dev>,
"Niklas Cassel" <cassel@kernel.org>,
"Devendra K Verma" <devendra.verma@amd.com>,
dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v5 13/24] dmaengine: dw-edma: Reclaim issued descriptors from IRQ-paired LL progress
Date: Wed, 12 Aug 2026 16:54:15 -0400 [thread overview]
Message-ID: <anzdd9kAxBHvuzpo@lizhi-Precision-Tower-5810> (raw)
In-Reply-To: <20260812155721.2807506-14-den@valinux.co.jp>
On Thu, Aug 13, 2026 at 12:57:10AM +0900, Koichiro Den wrote:
> Dynamic append can place entries from several descriptors in one LL
> ring. Track the consumed boundary in ll_done, reuse entries behind it,
> and complete descriptors in issue order as done_burst advances.
>
> Normalize each IRQ-paired LLP sample to the exclusive boundary used by
> ll_done. A stopped sample points to the next entry. Keep a running
> sample one entry behind the raw LLP so an entry is not recycled before
> payload completion is established. For the eDMA-compatible interrupt
> interface, treat DONE as a stopped boundary only when channel status is
> complete and transfer size is zero.
>
> Record the first outstanding physical LL entry in each descriptor and
> verify that it matches ll_done before consuming that descriptor. On a
> mismatch, warn and resynchronize only if the sampled boundary has
> reached the descriptor; otherwise stop without completing it.
>
> Reclaiming entries as they are consumed also lets a descriptor larger
> than the ring advance. Keep one data entry free so a physical index
> remains unambiguous in the active producer window. Clear any published
> ring state on termination or abort before starting another transfer.
>
> LL progress now has its own completion path, so fold the temporary
> lock-held DONE helper back into its only caller.
>
> Suggested-by: Frank Li <Frank.Li@nxp.com>
> Signed-off-by: Koichiro Den <den@valinux.co.jp>
> ---
> Changes in v5:
> - Adjust context after moving the issue_pending() snapshot discard to
> patch 11. dw_edma_ll_snapshot_discard() is no longer re-added here.
> - Fold dw_edma_ll_clean_pending() into
> dw_edma_ll_consume_progress(), removing the one-line wrapper
> (pure refactoring).
>
> drivers/dma/dw-edma/dw-edma-core.c | 273 +++++++++++++++++++++-----
> drivers/dma/dw-edma/dw-edma-core.h | 4 +
> drivers/dma/dw-edma/dw-edma-v0-core.c | 6 +
> 3 files changed, 238 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
> index 1deaf2d0da91..363993c64c44 100644
> --- a/drivers/dma/dw-edma/dw-edma-core.c
> +++ b/drivers/dma/dw-edma/dw-edma-core.c
> @@ -53,13 +53,6 @@ dw_edma_alloc_desc(struct dw_edma_chan *chan, size_t nburst)
> {
> struct dw_edma_desc *desc;
>
> - /*
> - * For now, a descriptor that does not fit would stall the channel
> - * forever: reject it up front.
> - */
> - if (!chan->non_ll && nburst > chan->ll_max - 1)
> - return NULL;
> -
> desc = kzalloc_flex(*desc, burst, nburst, GFP_NOWAIT);
> if (unlikely(!desc))
> return NULL;
> @@ -79,6 +72,7 @@ static void dw_edma_ll_snapshot_discard_locked(struct dw_edma_chan *chan)
> {
> lockdep_assert_held(dw_edma_event_lock(chan));
>
> + chan->ll_irq.idx = -1;
> chan->ll_irq.event = DW_EDMA_LL_EVENT_NONE;
> }
>
> @@ -128,6 +122,7 @@ dw_edma_ll_snapshot_take(struct dw_edma_chan *chan,
> if (dw_edma_abort_latch_locked(chan))
> return false;
>
> + /* Consume each snapshot once, even if its boundary is later rejected. */
> *snapshot = chan->ll_irq;
> dw_edma_ll_snapshot_discard_locked(chan);
>
> @@ -215,7 +210,13 @@ static u32 dw_edma_core_get_used_num(struct dw_edma_chan *chan)
>
> static u32 dw_edma_core_get_free_num(struct dw_edma_chan *chan)
> {
> - /* Keep one data entry free so equal indices mean an empty ring. */
> + /*
> + * ll_done is the consumer boundary, so only the distance from ll_done
> + * to ll_head is occupied. Descriptor completion is tracked separately
> + * with done_burst.
> + *
> + * Keep one data entry free so equal indices mean an empty ring.
> + */
> return chan->ll_max - 1 - dw_edma_core_get_used_num(chan);
> }
>
> @@ -224,6 +225,25 @@ static bool dw_edma_ll_pending(struct dw_edma_chan *chan)
> return chan->ll_head != chan->ll_done;
> }
>
> +static u32 dw_edma_core_ch_transfer_size(struct dw_edma_chan *chan)
> +{
> + if (!chan->dw->core->ch_transfer_size)
> + return U32_MAX;
> +
> + return chan->dw->core->ch_transfer_size(chan);
> +}
> +
> +static bool dw_edma_ll_done_is_stopped(struct dw_edma_chan *chan)
> +{
> + /*
> + * Native HDMA reports STOP separately. The eDMA-compatible interrupt
> + * interface uses DONE for both progress and stop, so confirm a stopped
> + * boundary with channel status and transfer size.
> + */
> + return dw_edma_core_ch_status(chan) == DMA_COMPLETE &&
> + dw_edma_core_ch_transfer_size(chan) == 0;
> +}
> +
> static void dw_edma_core_ll_start(struct dw_edma_desc *desc)
> {
> struct dw_edma_chan *chan = desc->chan;
> @@ -231,6 +251,9 @@ static void dw_edma_core_ll_start(struct dw_edma_desc *desc)
> u32 free;
>
> free = dw_edma_core_get_free_num(chan);
> + if (free && desc->start_burst == desc->done_burst)
> + desc->ll_start = chan->ll_head;
> +
should always set ll_start = chan->ll_head, always record current fit into
which ll index.
> for (i = desc->start_burst; i < desc->nburst && free; i++, free--) {
> /*
> * Refresh the link element before filling the last data slot so
> @@ -252,7 +275,6 @@ static void dw_edma_core_ll_start(struct dw_edma_desc *desc)
> }
> }
>
> - desc->done_burst = desc->start_burst;
> desc->start_burst = i;
> }
>
> @@ -352,6 +374,127 @@ static void dw_edma_finish_termination(struct dw_edma_chan *chan)
> chan->status = EDMA_ST_IDLE;
> }
>
> +/*
> + * Must be called with vc.lock held. Consume an LL progress boundary,
> + * advance ll_done and complete descriptors covered by the consumed range.
> + * Return true if ll_done advanced.
> + */
> +static bool dw_edma_ll_consume_progress(struct dw_edma_chan *chan, int idx)
> +{
> + struct virt_dma_desc *vd, *_vd;
> + bool advanced = false;
> + u32 done, gap;
> +
> + /* Ignore invalid, duplicate or stale progress. */
> + if (idx < 0 || (u32)idx >= chan->ll_max)
> + return false;
> +
> + done = dw_edma_core_get_ll_dist(chan, chan->ll_done, idx);
> + if (!done || done > dw_edma_core_get_used_num(chan))
> + return false;
> +
> + list_for_each_entry_safe(vd, _vd, &chan->vc.desc_issued, node) {
> + struct dw_edma_desc *desc = vd2dw_edma_desc(vd);
> + u32 consumed;
> +
> + if (!done)
> + break;
> +
> + if (WARN_ON_ONCE(desc->done_burst > desc->start_burst ||
> + desc->start_burst > desc->nburst))
> + return advanced;
> +
> + /*
> + * start_burst is the next burst to append. done_burst counts
> + * bursts already consumed by hardware.
> + */
> + consumed = desc->start_burst - desc->done_burst;
> + if (!consumed)
> + break;
> +
> + /*
> + * ll_start ties the descriptor counters to the physical ring.
> + * If accounting lost entries before this descriptor, skip them
> + * only after the sampled boundary has reached ll_start.
> + */
> + if (WARN_ON_ONCE(desc->ll_start != chan->ll_done)) {
> + gap = dw_edma_core_get_ll_dist(chan, chan->ll_done,
> + desc->ll_start);
> + if (gap > done)
> + return advanced;
> +
> + chan->ll_done = desc->ll_start;
> + done -= gap;
> + advanced = true;
> + if (!done)
> + break;
> + }
> +
> + consumed = min(done, consumed);
> + desc->done_burst += consumed;
> + desc->ll_start = (desc->ll_start + consumed) % chan->ll_max;
It'd better update ll_start when fill ll from desc. Here should only
update ll_done.
chan->ll_done = (chan->ll_done + consumed) % chan->ll_max.
> + chan->ll_done = desc->ll_start;
> + done -= consumed;
> + advanced = true;
> +
> + /*
> + * Descriptors are published and retired in strict list order. A
> + * later descriptor cannot complete until this one is fully consumed.
> + */
> + if (desc->done_burst != desc->nburst)
> + break;
> +
> + /* Hardware has consumed this descriptor's LL entries. */
> + dw_hdma_set_callback_result(vd, DMA_TRANS_NOERROR);
> + list_del(&vd->node);
> + vchan_cookie_complete(vd);
> + }
> +
> + WARN_ON_ONCE(done);
> +
> + return advanced;
> +}
> +
> +static int
> +dw_edma_ll_recycle_idx(struct dw_edma_chan *chan, int idx,
> + enum dw_edma_ll_event event)
> +{
> + if (idx < 0 || (u32)idx > chan->ll_max)
> + return -EINVAL;
> +
> + /*
> + * Convert the raw LLP index to the exclusive boundary used by ll_done.
> + * For both eDMA and HDMA, once the engine has stopped, LLP points to
> + * the next element. ll_max is the link element, hence the following
> + * data boundary is 0.
> + */
> + if (event == DW_EDMA_LL_EVENT_STOP)
> + return idx == chan->ll_max ? 0 : idx;
regardless state. we can always treat link element as 0. ll_max have not
include link entry.
in calculate distance between two point A, B. (B - A) % ll_max.
It is the same when A or B is ll_max or 0.
> +
> + /*
> + * Moving a running index one entry back cannot represent index 0
> + * without wrapping it to ll_max - 1. That could falsely consume a full
> + * producer window, so wait for another sample or STOP.
> + */
> + if (!idx)
> + return -EINVAL;
> +
> + /*
> + * A running eDMA LLP can move ahead of payload completion, so keep the
> + * boundary one entry behind it.
> + *
> + * DWC PCIe Controller Databook 6.10a-lca06, Section 7.2.1, Table 7-3
> + * describes an HDMA watermark LLP as an inclusive LLE recycling
> + * boundary, which would normally translate to idx + 1. During testing
> + * on a DWC HDMA 6.30a integration, using that boundary for DMAengine
> + * completion let clients release DMA mappings while hardware still
> + * accessed them, causing IOMMU faults. Keep the boundary one entry
> + * behind the raw LLP for HDMA as well. Stopped samples continue to use
> + * the next-entry boundary above.
> + */
> + return idx == chan->ll_max ? chan->ll_max - 1 : idx - 1;
LLP should point current DMA working LL, always stop at which controller bit
have not set yet.
If your logic always treat idx as unfinished, you needn't idx - 1 here.
[ll_done, idx)
> +}
> +
> static void dw_edma_core_ll_sync(struct dw_edma_chan *chan)
> {
> /*
> @@ -834,31 +977,30 @@ dw_edma_device_prep_interleaved_dma(struct dma_chan *dchan,
> return dw_edma_device_transfer(&xfer, dw_edma_device_get_config(dchan, NULL));
> }
>
> -/* Must be called with vc.lock held. */
> -static void dw_edma_done_interrupt_locked(struct dw_edma_chan *chan)
> +static void dw_edma_done_interrupt(struct dw_edma_chan *chan)
> {
> struct dw_edma_desc *desc;
> struct virt_dma_desc *vd;
> + unsigned long flags;
>
> - lockdep_assert_held(&chan->vc.lock);
> -
> - if (chan->status == EDMA_ST_PAUSE)
> + spin_lock_irqsave(&chan->vc.lock, flags);
> + if (chan->status == EDMA_ST_PAUSE) {
> + spin_unlock_irqrestore(&chan->vc.lock, flags);
> return;
> + }
>
> switch (chan->request) {
> case EDMA_REQ_NONE:
> case EDMA_REQ_PAUSE:
> vd = vchan_next_desc(&chan->vc);
> - if (!vd)
> - break;
> -
> - desc = vd2dw_edma_desc(vd);
> - if (desc->start_burst >= desc->nburst) {
> - dw_hdma_set_callback_result(vd, DMA_TRANS_NOERROR);
> - list_del(&vd->node);
> - vchan_cookie_complete(vd);
> - if (!chan->non_ll)
> - chan->ll_done = chan->ll_head;
> + if (vd) {
> + desc = vd2dw_edma_desc(vd);
> + if (desc->start_burst >= desc->nburst) {
> + dw_hdma_set_callback_result(vd,
> + DMA_TRANS_NOERROR);
> + list_del(&vd->node);
> + vchan_cookie_complete(vd);
> + }
> }
>
> if (chan->request == EDMA_REQ_PAUSE) {
> @@ -871,25 +1013,12 @@ static void dw_edma_done_interrupt_locked(struct dw_edma_chan *chan)
> break;
>
> case EDMA_REQ_STOP:
> - vd = vchan_next_desc(&chan->vc);
> - if (!vd)
> - break;
> -
> dw_edma_finish_termination(chan);
> break;
>
> default:
> break;
> }
> - dw_edma_core_ch_maybe_doorbell(chan);
> -}
> -
> -static void dw_edma_done_interrupt(struct dw_edma_chan *chan)
> -{
> - unsigned long flags;
> -
> - spin_lock_irqsave(&chan->vc.lock, flags);
> - dw_edma_done_interrupt_locked(chan);
> spin_unlock_irqrestore(&chan->vc.lock, flags);
> }
>
> @@ -902,7 +1031,37 @@ static void dw_edma_ll_interrupt(struct dw_edma_chan *chan)
> if (!dw_edma_ll_snapshot_take(chan, &snapshot))
> return;
>
> - dw_edma_done_interrupt_locked(chan);
> + if (chan->status == EDMA_ST_PAUSE)
> + return;
> +
> + dw_edma_ll_consume_progress(chan, snapshot.idx);
> +
> + if (snapshot.event == DW_EDMA_LL_EVENT_PROGRESS &&
> + chan->request != EDMA_REQ_NONE)
> + goto out;
> +
> + switch (chan->request) {
> + case EDMA_REQ_NONE:
> + dw_edma_start_transfer(chan);
> + chan->status = dw_edma_ll_pending(chan) ?
> + EDMA_ST_BUSY : EDMA_ST_IDLE;
> + break;
> +
> + case EDMA_REQ_PAUSE:
> + dw_edma_set_request(chan, EDMA_REQ_NONE);
> + chan->status = EDMA_ST_PAUSE;
> + break;
> +
> + case EDMA_REQ_STOP:
> + dw_edma_finish_termination(chan);
> + break;
> +
> + default:
> + break;
> + }
> +
> +out:
> + dw_edma_core_ch_maybe_doorbell(chan);
> }
>
> static bool dw_edma_abort_interrupt(struct dw_edma_chan *chan)
> @@ -965,21 +1124,44 @@ static void dw_edma_queue_irq_work(struct dw_edma_chan *chan,
> static void dw_edma_record_irq(struct dw_edma_chan *chan, unsigned int events)
> {
> struct dw_edma_ll_snapshot snapshot = {
> - .event = events & DW_EDMA_IRQ_STOP ?
> - DW_EDMA_LL_EVENT_STOP : DW_EDMA_LL_EVENT_PROGRESS,
> + .idx = -1,
> + .event = DW_EDMA_LL_EVENT_NONE,
> };
> unsigned int pending = 0;
>
> lockdep_assert_held(dw_edma_event_lock(chan));
>
> + /*
> + * Classify the LL event before normalizing its LLP sample to the
> + * exclusive consumer boundary. Keep STOP even without a valid
> + * boundary so deferred handling still sees that the run ended.
> + */
> + if (!chan->non_ll &&
> + (events & (DW_EDMA_IRQ_DONE | DW_EDMA_IRQ_PROGRESS |
> + DW_EDMA_IRQ_STOP))) {
> + if ((events & DW_EDMA_IRQ_STOP) ||
> + ((events & DW_EDMA_IRQ_DONE) &&
> + dw_edma_ll_done_is_stopped(chan)))
> + snapshot.event = DW_EDMA_LL_EVENT_STOP;
> + else
> + snapshot.event = DW_EDMA_LL_EVENT_PROGRESS;
> +
> + snapshot.idx = dw_edma_ll_recycle_idx(chan,
> + dw_edma_core_ll_cur_idx(chan),
> + snapshot.event);
> + if (snapshot.idx < 0 &&
> + snapshot.event != DW_EDMA_LL_EVENT_STOP)
> + snapshot.event = DW_EDMA_LL_EVENT_NONE;
> + }
> +
> if ((events & DW_EDMA_IRQ_ABORT) && chan->abort_pending)
> pending |= DW_EDMA_DEFERRED_ABORT;
>
> - if (chan->non_ll) {
> - if (events & (DW_EDMA_IRQ_DONE | DW_EDMA_IRQ_STOP))
> - pending |= DW_EDMA_DEFERRED_DONE;
> - } else if (events & (DW_EDMA_IRQ_DONE | DW_EDMA_IRQ_PROGRESS |
> - DW_EDMA_IRQ_STOP)) {
> + if (chan->non_ll &&
> + (events & (DW_EDMA_IRQ_DONE | DW_EDMA_IRQ_STOP)))
> + pending |= DW_EDMA_DEFERRED_DONE;
> +
> + if (snapshot.event != DW_EDMA_LL_EVENT_NONE) {
> /* STOP is final for this run; do not replace it with progress. */
> if (chan->ll_irq.event != DW_EDMA_LL_EVENT_STOP ||
> snapshot.event == DW_EDMA_LL_EVENT_STOP)
> @@ -1227,6 +1409,7 @@ static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc)
> chan->irq_mode = dw_edma_get_default_irq_mode(chan);
> INIT_WORK(&chan->irq_work, dw_edma_irq_work);
> atomic_set(&chan->irq_pending, 0);
> + chan->ll_irq.idx = -1;
> chan->ll_irq.event = DW_EDMA_LL_EVENT_NONE;
> chan->abort_pending = false;
>
> diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h
> index d709aa274300..27cab6ca5e67 100644
> --- a/drivers/dma/dw-edma/dw-edma-core.h
> +++ b/drivers/dma/dw-edma/dw-edma-core.h
> @@ -71,6 +71,7 @@ struct dw_edma_desc {
>
> u32 alloc_sz;
>
> + u32 ll_start; /* First outstanding LL entry */
> size_t done_burst;
> size_t start_burst;
> size_t nburst;
> @@ -78,6 +79,7 @@ struct dw_edma_desc {
> };
>
> struct dw_edma_ll_snapshot {
> + int idx;
> enum dw_edma_ll_event event;
> };
>
> @@ -113,6 +115,7 @@ struct dw_edma_chan {
> * LL event recorded by the hard IRQ handler. The event lock
> * serializes its capture with a new hardware run; vc.lock serializes
> * its consumption with LL state.
> + * Valid indices use the exclusive boundary convention of ll_done.
> */
> struct dw_edma_ll_snapshot ll_irq;
> /* ABORT is terminal and remains pending across LL state changes. */
> @@ -189,6 +192,7 @@ struct dw_edma_core_ops {
> enum dma_status (*ch_status)(struct dw_edma_chan *chan);
> /* Called with dw_edma_event_lock(chan) held. */
> bool (*ch_abort_int_pending)(struct dw_edma_chan *chan);
> + u32 (*ch_transfer_size)(struct dw_edma_chan *chan);
> irqreturn_t (*handle_int)(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir,
> dw_edma_handler_t handler);
> void (*non_ll_start)(struct dw_edma_chan *chan, struct dw_edma_burst *child);
> diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
> index 20dff21a0603..b9d6205157b3 100644
> --- a/drivers/dma/dw-edma/dw-edma-v0-core.c
> +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
> @@ -318,6 +318,11 @@ static enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)
> return DMA_ERROR;
> }
>
> +static u32 dw_edma_v0_core_ch_transfer_size(struct dw_edma_chan *chan)
> +{
> + return GET_CH_32(chan->dw, chan->dir, chan->id, transfer_size);
> +}
> +
> static bool dw_edma_v0_core_ch_abort_int_pending(struct dw_edma_chan *chan)
> {
> u32 sts = GET_RW_32(chan->dw, chan->dir, int_status);
> @@ -677,6 +682,7 @@ static const struct dw_edma_core_ops dw_edma_v0_core = {
> .ch_count = dw_edma_v0_core_ch_count,
> .ch_status = dw_edma_v0_core_ch_status,
> .ch_abort_int_pending = dw_edma_v0_core_ch_abort_int_pending,
> + .ch_transfer_size = dw_edma_v0_core_ch_transfer_size,
> .handle_int = dw_edma_v0_core_handle_int,
> .ll_data = dw_edma_v0_core_ll_data,
> .ll_link = dw_edma_v0_core_ll_link,
> --
> 2.51.0
>
next prev parent reply other threads:[~2026-08-12 20:54 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-12 15:56 [PATCH v5 00/24] dmaengine: dw-edma: Support dynamic LL appends Koichiro Den
2026-08-12 15:56 ` [PATCH v5 01/24] dmaengine: dw-edma: Add dw_edma_core_ll_cur_idx() to get current LL entry index Koichiro Den
2026-08-12 18:50 ` Frank Li
2026-08-12 15:56 ` [PATCH v5 02/24] dmaengine: dw-edma: Add dw_edma_core_ll_clear() to clear LL control-word Koichiro Den
2026-08-12 15:57 ` [PATCH v5 03/24] dmaengine: dw-edma: Factor out linked-list transfer start Koichiro Den
2026-08-12 15:57 ` [PATCH v5 04/24] dmaengine: dw-edma: Make DMA link list work as a circular buffer Koichiro Den
2026-08-12 16:14 ` sashiko-bot
2026-08-13 8:31 ` Koichiro Den
2026-08-12 15:57 ` [PATCH v5 05/24] dmaengine: dw-edma: Move callback result helper before LL helpers Koichiro Den
2026-08-12 15:57 ` [PATCH v5 06/24] dmaengine: dw-edma: Dispatch DONE interrupts by channel request Koichiro Den
2026-08-12 15:57 ` [PATCH v5 07/24] dmaengine: dw-edma: Centralize LL doorbell decisions Koichiro Den
2026-08-12 15:57 ` [PATCH v5 08/24] dmaengine: dw-edma: Prepare LL progress event handling Koichiro Den
2026-08-12 15:57 ` [PATCH v5 09/24] dmaengine: dw-edma: Prepare deferred IRQ reporting for LL events Koichiro Den
2026-08-12 15:57 ` [PATCH v5 10/24] dmaengine: dw-edma: Prepare LL kicks for event serialization Koichiro Den
2026-08-12 15:57 ` [PATCH v5 11/24] dmaengine: dw-edma: Serialize LL event capture with channel kicks Koichiro Den
2026-08-12 15:57 ` [PATCH v5 12/24] dmaengine: dw-edma: Keep channels stopped while ABORT is pending Koichiro Den
2026-08-12 15:57 ` [PATCH v5 13/24] dmaengine: dw-edma: Reclaim issued descriptors from IRQ-paired LL progress Koichiro Den
2026-08-12 20:54 ` Frank Li [this message]
2026-08-14 8:48 ` Koichiro Den
2026-08-14 15:47 ` Frank Li
2026-08-15 14:36 ` Koichiro Den
2026-08-21 20:17 ` Frank Li
2026-08-22 14:26 ` Koichiro Den
2026-08-12 15:57 ` [PATCH v5 14/24] dmaengine: dw-edma: Add LL interrupt placement policy Koichiro Den
2026-08-12 15:57 ` [PATCH v5 15/24] dmaengine: dw-edma: Recheck stopped LL channels before restart Koichiro Den
2026-08-12 16:33 ` sashiko-bot
2026-08-12 15:57 ` [PATCH v5 16/24] dmaengine: dw-edma: Use HDMA watermarks as progress events Koichiro Den
2026-08-12 15:57 ` [PATCH v5 17/24] dmaengine: dw-edma: Recover stopped channels from tx_status() Koichiro Den
2026-08-12 15:57 ` [PATCH v5 18/24] dmaengine: dw-edma: Make the LL ring reset a full channel resync Koichiro Den
2026-08-12 15:57 ` [PATCH v5 19/24] dmaengine: dw-edma: Drain LL entries for STOP and PAUSE Koichiro Den
2026-08-12 16:29 ` sashiko-bot
2026-08-12 15:57 ` [PATCH v5 20/24] dmaengine: dw-edma: Dynamically append requests while running Koichiro Den
2026-08-12 15:57 ` [PATCH v5 21/24] dmaengine: dw-edma: Add engine reset and enable operations Koichiro Den
2026-08-12 15:57 ` [PATCH v5 22/24] dmaengine: dw-edma: Add engine recovery infrastructure Koichiro Den
2026-08-12 15:57 ` [PATCH v5 23/24] dmaengine: dw-edma: Detect and recover a stalled eDMA engine Koichiro Den
2026-08-12 15:57 ` [PATCH v5 24/24] dmaengine: dw-edma: Add trace support Koichiro Den
2026-08-12 21:05 ` [PATCH v5 00/24] dmaengine: dw-edma: Support dynamic LL appends Frank Li
2026-08-13 1:04 ` Koichiro Den
2026-08-13 16:39 ` Koichiro Den
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=anzdd9kAxBHvuzpo@lizhi-Precision-Tower-5810 \
--to=frank.li@oss.nxp.com \
--cc=Frank.Li@kernel.org \
--cc=Gustavo.Pimentel@synopsys.com \
--cc=bhelgaas@google.com \
--cc=cai.huoqing@linux.dev \
--cc=cassel@kernel.org \
--cc=den@valinux.co.jp \
--cc=devendra.verma@amd.com \
--cc=dmaengine@vger.kernel.org \
--cc=fancer.lancer@gmail.com \
--cc=hch@lst.de \
--cc=kees@kernel.org \
--cc=kishon@kernel.org \
--cc=kwilczynski@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mani@kernel.org \
--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