[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <20250731-ti-dma-timeout-v1-3-33321d2b7406@bootlin.com>
Date: Thu, 31 Jul 2025 18:41:31 +0200
From: Miquel Raynal <miquel.raynal@...tlin.com>
To: Peter Ujfalusi <peter.ujfalusi@...il.com>,
Vinod Koul <vkoul@...nel.org>, Grygorii Strashko <grygorii.strashko@...com>
Cc: Thomas Petazzoni <thomas.petazzoni@...tlin.com>,
Peter Ujfalusi <peter.ujfalusi@...com>, dmaengine@...r.kernel.org,
linux-kernel@...r.kernel.org, Miquel Raynal <miquel.raynal@...tlin.com>
Subject: [PATCH 3/3] dmaengine: ti: k3-udma: Simplify the completion worker
The function does nothing in the !uc->desc condition.
No need to go through the entire delay guessing logic if the descriptor
is already done when we first check.
Invert the "no descriptor" and "descriptor done" conditions. This
greatly simplifies the function by dropping two indentation levels and
improves the readability.
Signed-off-by: Miquel Raynal <miquel.raynal@...tlin.com>
---
drivers/dma/ti/k3-udma.c | 86 ++++++++++++++++++++----------------------------
1 file changed, 36 insertions(+), 50 deletions(-)
diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
index 11232b306475edd5e1ed75d938bbf49ed9c2aabd..fb323df15a1b6693d917750f18f907e63bb38c53 100644
--- a/drivers/dma/ti/k3-udma.c
+++ b/drivers/dma/ti/k3-udma.c
@@ -1087,69 +1087,55 @@ static void udma_check_tx_completion(struct work_struct *work)
{
struct udma_chan *uc = container_of(work, typeof(*uc),
tx_drain.work.work);
- bool desc_done = true;
+ struct udma_desc *d = uc->desc;
+ bool desc_done;
u32 residue_diff;
ktime_t time_diff;
unsigned long delay;
unsigned long flags;
+ if (!d)
+ return;
+
while (1) {
spin_lock_irqsave(&uc->vc.lock, flags);
- if (uc->desc) {
- /* Get previous residue and time stamp */
- residue_diff = uc->tx_drain.residue;
- time_diff = uc->tx_drain.tstamp;
- /*
- * Get current residue and time stamp or see if
- * transfer is complete
- */
- desc_done = udma_is_desc_really_done(uc, uc->desc);
- }
-
- if (!desc_done) {
- /*
- * Find the time delta and residue delta w.r.t
- * previous poll
- */
- time_diff = ktime_sub(uc->tx_drain.tstamp,
- time_diff) + 1;
- residue_diff -= uc->tx_drain.residue;
- /*
- * Try to guess when we should check next time by
- * calculating rate at which data is being drained at
- * the peer device. Slow devices might have not yet
- * started, showing no progress. Use an arbitrary delay
- * in this case.
- */
- if (residue_diff) {
- delay = (time_diff / residue_diff) *
- uc->tx_drain.residue;
- if (delay < 1000)
- delay = 1000;
- } else {
- delay = 100000;
- }
-
- spin_unlock_irqrestore(&uc->vc.lock, flags);
-
- usleep_range(ktime_to_us(delay),
- ktime_to_us(delay) + 10);
- continue;
- }
-
- if (uc->desc) {
- struct udma_desc *d = uc->desc;
-
- udma_decrement_byte_counters(uc, d->residue);
- udma_start(uc);
- vchan_cookie_complete(&d->vd);
+ /* Get previous residue and time stamp */
+ residue_diff = uc->tx_drain.residue;
+ time_diff = uc->tx_drain.tstamp;
+ /* Get current residue and time stamp or see if transfer is complete */
+ desc_done = udma_is_desc_really_done(uc, uc->desc);
+ if (desc_done)
break;
+
+ /* Find the time delta and residue delta w.r.t previous poll */
+ time_diff = ktime_sub(uc->tx_drain.tstamp, time_diff) + 1;
+ residue_diff -= uc->tx_drain.residue;
+ /*
+ * Try to guess when we should check next time by
+ * calculating rate at which data is being drained at
+ * the peer device. Slow devices might have not yet
+ * started, showing no progress. Use an arbitrary delay
+ * in this case.
+ */
+ if (residue_diff) {
+ delay = (time_diff / residue_diff) * uc->tx_drain.residue;
+ if (delay < 1000)
+ delay = 1000;
+ } else {
+ delay = 100000;
}
- break;
+ spin_unlock_irqrestore(&uc->vc.lock, flags);
+
+ usleep_range(ktime_to_us(delay),
+ ktime_to_us(delay) + 10);
}
+ udma_decrement_byte_counters(uc, d->residue);
+ udma_start(uc);
+ vchan_cookie_complete(&d->vd);
+
spin_unlock_irqrestore(&uc->vc.lock, flags);
}
--
2.50.1
Powered by blists - more mailing lists