| Message ID | 20260817135723.12807-2-christian.lugnberg@soundtrack.io (mailing list archive) |
|---|---|
| State | New |
| Headers |
Return-Path: <linux-sunxi+bounces-25196-sunxi=pue.re@lists.linux.dev>
X-Original-To: noreply@patchwork.local
Delivered-To: noreply@patchwork.local
Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10])
by mxe881.netcup.net (Postfix) with ESMTPS id 2D9E11C1F79
for <noreply@patchwork.local>; Mon, 17 Aug 2026 17:02:57 +0200 (CEST)
Authentication-Results: mxe881;
dkim=pass header.d=soundtrack.io;
spf=pass (sender IP is 172.234.253.10)
smtp.mailfrom=linux-sunxi+bounces-25196-noreply=patchwork.local@lists.linux.dev
smtp.helo=sea.lore.kernel.org
Received-SPF: pass (mxe881: domain of lists.linux.dev designates
172.234.253.10 as permitted sender) client-ip=172.234.253.10;
envelope-from=linux-sunxi+bounces-25196-noreply=patchwork.local@lists.linux.dev;
helo=sea.lore.kernel.org;
Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org
[100.90.174.1])
by sea.lore.kernel.org (Postfix) with ESMTP id 24E4B316217E
for <noreply@patchwork.local>; Mon, 17 Aug 2026 13:59:27 +0000 (UTC)
Received: from localhost.localdomain (localhost.localdomain [127.0.0.1])
by smtp.subspace.kernel.org (Postfix) with ESMTP id D198844238E;
Mon, 17 Aug 2026 13:57:37 +0000 (UTC)
Authentication-Results: smtp.subspace.kernel.org;
dkim=pass (2048-bit key) header.d=soundtrack.io header.i=@soundtrack.io
header.b="MVnR707J"
X-Original-To: linux-sunxi@lists.linux.dev
Received: from mail-ed1-f49.google.com (mail-ed1-f49.google.com
[209.85.208.49])
(using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits))
(No client certificate requested)
by smtp.subspace.kernel.org (Postfix) with ESMTPS id C6AF944236B
for <linux-sunxi@lists.linux.dev>; Mon, 17 Aug 2026 13:57:35 +0000 (UTC)
Authentication-Results: smtp.subspace.kernel.org;
arc=none smtp.client-ip=209.85.208.49
ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
t=1786975057; cv=none;
b=e+N4rHLM4QFaOSilPDJhfX7gpvjKRQRRzHx6WWJCSWzwpI3hoTkJI7/rMYPGr9wl5D0qjGV27V0/GfMuTNyCEbt7380CD4izYbvPJyf165qQ6JCFn1KdQO5TKz8KmwArcgP0vWqZDIrn8yfMNKBH4Y8/omIOXHJSEGabxQo2qC4=
ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
s=arc-20240116; t=1786975057; c=relaxed/simple;
bh=PZI7MMxmJVNzbmV5bnrz48F2Q3n5UxIGaRjcpiHxuHk=;
h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References:
MIME-Version;
b=SmLgN4f7pzybew1P0xgeuMAk5bA4WNZLyGHoz6qA2SaMCyEzUUPZjuP3M8++ISVSg925uQADcONqQx3ENQK1L5ekKrycwysiHjUkfWqq629SqUcPy3YAI1ujmRnRpphR075BOlRb96+WMQQyhsR3Xo2fNGgCNDxayAldMavpN+o=
ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
dmarc=pass (p=quarantine dis=none) header.from=soundtrack.io;
spf=pass smtp.mailfrom=soundtrack.io;
dkim=pass (2048-bit key) header.d=soundtrack.io header.i=@soundtrack.io
header.b=MVnR707J; arc=none smtp.client-ip=209.85.208.49
Authentication-Results: smtp.subspace.kernel.org;
dmarc=pass (p=quarantine dis=none) header.from=soundtrack.io
Authentication-Results: smtp.subspace.kernel.org;
spf=pass smtp.mailfrom=soundtrack.io
Received: by mail-ed1-f49.google.com with SMTP id
4fb4d7f45d1cf-6a09571dd5cso445568a12.2
for <linux-sunxi@lists.linux.dev>;
Mon, 17 Aug 2026 06:57:35 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=soundtrack.io; s=google; t=1786975054; x=1787579854;
darn=lists.linux.dev;
h=content-transfer-encoding:mime-version:references:in-reply-to
:message-id:date:subject:cc:to:from:from:to:cc:subject:date
:message-id:reply-to:content-type;
bh=WLmqosVfHRUnCpTXG/vmgJdRPIFeEEdEr21ji49UgUg=;
b=MVnR707J1aV3fWedcS/xpbQlw8YfPcFKjKBChCWdk3W3eiYUkxXgQ6454Yrdog0orV
dotANgFsgiQT3PXOunUoyu+2Ji2MuThIVouVMyHvU8O2ftV/q1saD7WDu8uKrz7f4zz5
4Gfi0ykQCtBzt6GGNBtKpLF39xfQYmpgpgSsWeaOLEsZc8OyXxDIj/WU6HXKxvynUM9O
oSpu57mW5/hwjufKjXEWGi+dn1XeOXYxihAoY7XGuV0hTmhje+vcfRQ0AZw0G4Yg6U3/
LPF2FkRo8HLnn8UlZG9DZ7GHgJ3/Z6PHToQEqkkPrw+kJ0Dq2PF/8u6/ez6IMMjvO4PP
ST4Q==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20251104; t=1786975054; x=1787579854;
h=content-transfer-encoding:mime-version:references:in-reply-to
:message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from
:to:cc:subject:date:message-id:reply-to:content-type;
bh=WLmqosVfHRUnCpTXG/vmgJdRPIFeEEdEr21ji49UgUg=;
b=eTMdhWvMdbQAa/+YQi+Pa7/Or0e5YvrjL5X/4pziX6iswzb6ph2fneJP+I4OZE6oSW
i3MnwRvWRO+WF9zEICkdBcFH9yFdIb5VasoG8gFlKscWVTqPrmk7S/EOZMdHJ+fqngsf
MPwaILOV0jgWo2PsIy4iBcTmnDFS88+cKA0uZnnloPPA9FsMa3Y2dY5E1qj03fIT4hB8
SCLdMbt+3vW9JUmvMNCIf7tsT3w5lOVJ7de2X76g1m+p49b09CkIatLtd2eO7n1/OktE
/yqyfrtnnnqSrB7V3XDPi5gYRAZ40Q4OwV/K70V1VXb3V41Hp3vQRPVIivqFX0Hr5wis
bskg==
X-Forwarded-Encrypted: i=1;
AHgh+RrKLKLKZBkuy68oIHxNybSZ0Ag4ytMRMYWzwRqorxc33lghCsTpHbknbwSnSMHFeMYb3hH/nvj5E0n/eQ==@lists.linux.dev
X-Gm-Message-State: AOJu0YxiLsnbzjoSkjFhJpFqK0iu2pY/lbbruY3m1JFzMhgJEl+DlGt9
jVZXUs7sWsW1r8ugJzRm/mvSyPGvGbx8ridakITe9zBZefDhtlGF/Ja7L6nEIZjHnin5RQMWz7+
3KpWU5Pw=
X-Gm-Gg: AR+sD13PqZbJw5uvi1uk0AhY8kDbMoKUzXwt7IpR8wiUkwaRZdDOCSAiwclyB0cMfRf
7pNhgzf2LY5nZRCgnCrV1UPweJ0irx8dZ+QOBxtJ5sZMsH0tHYn1wMFZqGs7lkyjufOR5g1hf+i
ar+XNNlZoHtGxqk60ZC128xm3dENF6W1tefjOXbzMm9EDgTYE7NuuneLKrLBmNTyA4OWhM+h5Mc
yrJeH1Entd3GtF9atFQRTCiRNjHk3v3Waqn8Orpq3SVO00y33CPi3ZrEF9kSj/jJdyUQeZN9RFn
mYRXfSU9cI8zxI9K//vQ0pdRH0yIPK25glGzlo+djdQ6xsI1Ypnlg4H2SnOPPTduWBBYXavKzcX
t9if4Tk8spSGiLOSf6H189u7i9ump2Dx5UUODPsaF24Tm4Wdc6a0gIpEhhTds+4fp196Hq44kjv
qTjMzSor+NaTI92MqfIQ8fE6JD3gA+Xy2g5zedNBhXwgy8N6C9WhDfSxWyeh0c63I6UxL9kK/kl
daeCR3lwluCZy2FhY6+30F2uDKFV4OqoJctVGxd0M6ncGUmUbLJvGHNSY8=
X-Received: by 2002:a05:6402:234b:b0:6a3:68c2:9a9e with SMTP id
4fb4d7f45d1cf-6a38a845a42mr7135042a12.0.1786975054047;
Mon, 17 Aug 2026 06:57:34 -0700 (PDT)
Received: from Mac.localdomain (31-209-40-223.cust.bredband2.com.
[31.209.40.223])
by smtp.gmail.com with ESMTPSA id
4fb4d7f45d1cf-6a3d85319b1sm810238a12.13.2026.08.17.06.57.32
(version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256);
Mon, 17 Aug 2026 06:57:33 -0700 (PDT)
From: Christian Lugnberg <christian.lugnberg@soundtrack.io>
To: vkoul@kernel.org
Cc: Frank.Li@kernel.org,
wens@kernel.org,
jernej.skrabec@gmail.com,
samuel@sholland.org,
dmaengine@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-sunxi@lists.linux.dev,
linux-kernel@vger.kernel.org,
Christian Lugnberg <christian.lugnberg@soundtrack.io>,
stable@vger.kernel.org
Subject: [PATCH v3 1/2] dmaengine: sun6i: fix non-atomic read of DMA position
registers
Date: Mon, 17 Aug 2026 15:51:22 +0200
Message-ID: <20260817135723.12807-2-christian.lugnberg@soundtrack.io>
X-Mailer: git-send-email 2.54.0
In-Reply-To: <20260817135723.12807-1-christian.lugnberg@soundtrack.io>
References: <20260817135723.12807-1-christian.lugnberg@soundtrack.io>
Precedence: bulk
X-Mailing-List: linux-sunxi@lists.linux.dev
List-Id: <linux-sunxi.lists.linux.dev>
List-Subscribe: <mailto:linux-sunxi+subscribe@lists.linux.dev>
List-Unsubscribe: <mailto:linux-sunxi+unsubscribe@lists.linux.dev>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-Rspamd-Server: rspamd-worker-8404
X-Spamd-Result: default: False [0.84 / 15.00];
BAYES_HAM(-5.50)[99.99%];
RBL_SENDERSCORE(2.00)[172.234.253.10:from];
DMARC_POLICY_QUARANTINE(1.50)[soundtrack.io : SPF not aligned (relaxed),
No valid DKIM,quarantine];
SUSPICIOUS_RECIPS(1.50)[];
MID_CONTAINS_FROM(1.00)[];
R_MISSING_CHARSET(0.50)[];
MAILLIST(-0.15)[generic];
BAD_REP_POLICIES(0.10)[];
MIME_GOOD(-0.10)[text/plain];
HAS_LIST_UNSUB(-0.01)[];
FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,vger.kernel.org,lists.infradead.org,lists.linux.dev,soundtrack.io];
FROM_HAS_DN(0.00)[];
PRECEDENCE_BULK(0.00)[];
TAGGED_RCPT(0.00)[];
DBL_BLOCKED_OPENRESOLVER(0.00)[sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo];
RCVD_COUNT_FIVE(0.00)[6];
FROM_NEQ_ENVFROM(0.00)[christian.lugnberg@soundtrack.io,linux-sunxi@lists.linux.dev];
RCPT_COUNT_SEVEN(0.00)[11];
FORGED_RECIPIENTS_MAILLIST(0.00)[];
R_SPF_ALLOW(0.00)[+ip4:172.234.253.10];
TO_DN_SOME(0.00)[];
FORGED_SENDER_MAILLIST(0.00)[];
MIME_TRACE(0.00)[0:+];
ASN(0.00)[asn:63949, ipnet:172.234.224.0/19, country:SG];
RCVD_TLS_LAST(0.00)[];
ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1];
TAGGED_FROM(0.00)[bounces-25196-noreply=patchwork.local];
RCVD_VIA_SMTP_AUTH(0.00)[]
X-Rspamd-Queue-Id: 2D9E11C1F79
X-MORS-Enabled: yes
X-MORS-DOMAIN: patchwork.local
X-MORS-HOSTING: hosting172546
X-MORS-USER: hosting172546
X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?=
|
| Series |
dmaengine: sun6i: Fix two bugs in the DMA status path
|
|
Commit Message
Christian Lugnberg
Aug. 17, 2026, 1:51 p.m. UTC
sun6i_get_chan_size() reads DMA_CHAN_LLI_ADDR and DMA_CHAN_CUR_CNT in two
separate readl() calls with no synchronisation between them:
pos = readl(pchan->base + DMA_CHAN_LLI_ADDR);
bytes = readl(pchan->base + DMA_CHAN_CUR_CNT);
DMA_CHAN_LLI_ADDR holds the physical address of the *next* descriptor the
engine will load once the current one completes. DMA_CHAN_CUR_CNT holds the
remaining byte count for the *current* descriptor. If the DMA engine
advances to the next LLI entry between the two reads, pos becomes stale: it
still points to what was the next descriptor at the time of the first read,
but that descriptor is now the current one and CUR_CNT reflects its initial
(full) byte count. The subsequent virtual-chain walk starts one entry too
early and accumulates an extra full period's worth of bytes into the
residue estimate.
Fix this by re-reading DMA_CHAN_LLI_ADDR after DMA_CHAN_CUR_CNT and
retrying if the value changed. This double-read pattern guarantees that
both registers were sampled during the same descriptor interval. The cost
is at most one extra readl() pair per call in the racy case, which occurs
only at descriptor boundaries (~every 2 ms) and is negligible.
Fixes: a90e173f3faf ("dmaengine: sun6i: Add cyclic capability")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Christian Lugnberg <christian.lugnberg@soundtrack.io>
---
drivers/dma/sun6i-dma.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
Comments
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: Pre-existing issues: - [High] The `sun6i_dma_tx_status` function reads and caches `vchan->phy` into a local `pchan` variable before acquiring the `vchan->vc.lock`. If the DMA transfer completes concurrently and the tasklet reassigns this physical channel to another virtual channel, `tx_status` uses the stale `pchan` pointer to calculate the DMA residue. This results in accessing another channel's hardware registers and descriptor lists. -- --- Patch [1]: [PATCH v3 1/2] dmaengine: sun6i: fix non-atomic read of DMA position registers --- commit bea51abd69d8527a2183678d78b9d1b2e28b24a1 Author: Christian Lugnberg <christian.lugnberg@soundtrack.io> dmaengine: sun6i: fix non-atomic read of DMA position registers sun6i_get_chan_size() reads DMA_CHAN_LLI_ADDR and DMA_CHAN_CUR_CNT in two separate readl() calls with no synchronisation between them. The subsequent virtual-chain walk starts one entry too early and accumulates an extra full period's worth of bytes into the residue estimate. Fix this by re-reading DMA_CHAN_LLI_ADDR after DMA_CHAN_CUR_CNT and retrying if the value changed. > diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c > index a9a254dbf8cb9..eb060ba2d4738 100644 > --- a/drivers/dma/sun6i-dma.c > +++ b/drivers/dma/sun6i-dma.c > @@ -354,8 +354,10 @@ static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan) > size_t bytes; > dma_addr_t pos; > > - pos = readl(pchan->base + DMA_CHAN_LLI_ADDR); > - bytes = readl(pchan->base + DMA_CHAN_CUR_CNT); > + do { > + pos = readl(pchan->base + DMA_CHAN_LLI_ADDR); > + bytes = readl(pchan->base + DMA_CHAN_CUR_CNT); > + } while (pos != readl(pchan->base + DMA_CHAN_LLI_ADDR)); [Severity: High] This is a pre-existing issue, but since sun6i_get_chan_size() uses the pchan pointer to read hardware registers, can it be called with a stale pchan pointer from sun6i_dma_tx_status()? In sun6i_dma_tx_status(), pchan is cached outside the lock: drivers/dma/sun6i-dma.c:sun6i_dma_tx_status() { struct sun6i_pchan *pchan = vchan->phy; ... spin_lock_irqsave(&vchan->vc.lock, flags); ... } else { bytes = sun6i_get_chan_size(pchan); } ... } If the transfer finishes and the tasklet reassigns this physical channel to another virtual channel concurrently, sun6i_dma_tx_status() could use the stale pchan. This would lead to calculating the residue using another channel's hardware state and descriptor lists. Should vchan->phy be re-read inside the lock? > > if (pos == LLI_LAST_ITEM) > return bytes;
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c index f47a326dd7ff..04fe1f5042e9 100644 --- a/drivers/dma/sun6i-dma.c +++ b/drivers/dma/sun6i-dma.c @@ -354,8 +354,10 @@ static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan) size_t bytes; dma_addr_t pos; - pos = readl(pchan->base + DMA_CHAN_LLI_ADDR); - bytes = readl(pchan->base + DMA_CHAN_CUR_CNT); + do { + pos = readl(pchan->base + DMA_CHAN_LLI_ADDR); + bytes = readl(pchan->base + DMA_CHAN_CUR_CNT); + } while (pos != readl(pchan->base + DMA_CHAN_LLI_ADDR)); if (pos == LLI_LAST_ITEM) return bytes;