lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<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

Powered by Openwall GNU/*/Linux Powered by OpenVZ