From patchwork Mon Sep 7 15:31:43 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonas Rebmann X-Patchwork-Id: 3214 Return-Path: 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 0F68A1C550F for ; Mon, 7 Sep 2026 17:34:31 +0200 (CEST) Authentication-Results: mxe881; spf=pass (sender IP is 172.234.253.10) smtp.mailfrom=linux-sunxi+bounces-25660-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-25660-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 8E75D3431A for ; Mon, 7 Sep 2026 15:32:15 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id C8C3B4F6466; Mon, 7 Sep 2026 15:32:14 +0000 (UTC) X-Original-To: linux-sunxi@lists.linux.dev Received: from mx1.white.stw.pengutronix.de (mx1.white.stw.pengutronix.de [185.203.200.13]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 74DF2503BC0 for ; Mon, 7 Sep 2026 15:32:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.203.200.13 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788795134; cv=none; b=F/Ov+hOTDRknAIvpSBtieK/i0ZKc6YW1jRQE3ws4fx8zlCX09qzEHZ4H+SZlFYvfJffLLU9vj23Aa94v+0ofjK08KGRzH4HmTrICsOiKF5FskyKbFH8KDAS1kLcccEgSrOwWj690sb+aBymIftzk/JGa3J3ndz54wkCfKUU4hnc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788795134; c=relaxed/simple; bh=wGnRIOLQsskF+M/TXv1ICuPToL+aREGhjmC3EdA93Co=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=F5pS1m9TVBHIF60+ClpRsxHR0+IyBI4wcoCtCEpkIjwI6LAm1TbzU611h4QhvIFzoFbXRHrg5GJL2LG4pIbfWRqSxyWcnB4IL2dNkjCoV0Gn/7DrEkUQQICi+DWu8zIp2ujGMgD/7f/uX/GwgIEC5R7fXlHtRBii4NR4oIjl1jM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de; spf=pass smtp.mailfrom=pengutronix.de; arc=none smtp.client-ip=185.203.200.13 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=pengutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pengutronix.de X-PTX-Original-Recipient: samuel@sholland.org X-PTX-Original-Recipient: linux-sunxi@lists.linux.dev X-PTX-Original-Recipient: o.schinagl@ultimaker.com X-PTX-Original-Recipient: t.schramm@manjaro.org X-PTX-Original-Recipient: broonie@linaro.org X-PTX-Original-Recipient: linux-kernel@vger.kernel.org X-PTX-Original-Recipient: linux-spi@vger.kernel.org X-PTX-Original-Recipient: jernej.skrabec@gmail.com X-PTX-Original-Recipient: mr.nuke.me@gmail.com X-PTX-Original-Recipient: mkl@pengutronix.de X-PTX-Original-Recipient: kernel@pengutronix.de X-PTX-Original-Recipient: jre@pengutronix.de X-PTX-Original-Recipient: mripard@kernel.org X-PTX-Original-Recipient: wens@kernel.org X-PTX-Original-Recipient: broonie@kernel.org X-PTX-Original-Recipient: linux-arm-kernel@lists.infradead.org Received: from drehscheibe.grey.stw.pengutronix.de (drehscheibe.grey.stw.pengutronix.de [IPv6:2a0a:edc0:0:c01:1d::a2]) (Authenticated sender: relay-from-drehscheibe.grey.stw.pengutronix.de) by mx1.white.stw.pengutronix.de (Postfix) with ESMTPSA id 5AFD2202010; Mon, 07 Sep 2026 17:32:04 +0200 (CEST) Received: from dude04.red.stw.pengutronix.de ([2a0a:edc0:0:1101:1d::ac]) by drehscheibe.grey.stw.pengutronix.de with esmtp (Exim 4.96) (envelope-from ) id 1x3bKG-000Ym1-0p; Mon, 07 Sep 2026 17:32:04 +0200 From: Jonas Rebmann Date: Mon, 07 Sep 2026 17:31:43 +0200 Subject: [PATCH v2 4/6] spi: spi-sun4i: sun4i_spi_handler(): fix race condition between transfer completion and RX FIFO interrupt Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20260907-spi-sun4i-fixes-v2-4-7e805662b9bd@pengutronix.de> References: <20260907-spi-sun4i-fixes-v2-0-7e805662b9bd@pengutronix.de> In-Reply-To: <20260907-spi-sun4i-fixes-v2-0-7e805662b9bd@pengutronix.de> To: Mark Brown , Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Alexandru Gagniuc , Olliver Schinagl Cc: linux-spi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, Mark Brown , kernel@pengutronix.de, Marc Kleine-Budde , Jonas Rebmann , Tobias Schramm X-Mailer: b4 0.16-dev X-Developer-Signature: v=1; a=openpgp-sha256; l=3887; i=jre@pengutronix.de; h=from:subject:message-id; bh=QMi2ysI1afuHQu9XDhv19lMvyJMVahR5/aTnItq6LYk=; b=owGbwMvMwCV2ZcYT3onnbjcwnlZLYsiad+NTZfKu09JKKRdPBSkzhd3e8O3zFwWW5oXamS8qt 0/inTujsKOUhUGMi0FWTJElVk1OQcjY/7pZpV0szBxWJpAhDFycAjCRbQsY/tlwMG//Uh0Sc2vW wpCLqxUkGo7zrXFsf8uScGLmgeIJTzcz/A87YOt++i/r7pjDrj7X0qtX9gdUuX4Ne+JUFn1bfcF UXmYA X-Developer-Key: i=jre@pengutronix.de; a=openpgp; fpr=0B7B750D5D3CD21B3B130DE8B61515E135CD49B5 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [3.34 / 15.00]; RBL_SENDERSCORE(2.00)[172.234.253.10:from]; SUSPICIOUS_RECIPS(1.50)[]; MAILLIST(-0.15)[generic]; MIME_GOOD(-0.10)[text/plain]; BAD_REP_POLICIES(0.10)[]; HAS_LIST_UNSUB(-0.01)[]; DBL_BLOCKED_OPENRESOLVER(0.00)[pengutronix.de:email,sea.lore.kernel.org:rdns,sea.lore.kernel.org:helo,manjaro.org:email]; PRECEDENCE_BULK(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; RCPT_COUNT_TWELVE(0.00)[16]; TAGGED_RCPT(0.00)[]; DMARC_NA(0.00)[pengutronix.de]; FORGED_SENDER_MAILLIST(0.00)[]; FROM_HAS_DN(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; FROM_NEQ_ENVFROM(0.00)[jre@pengutronix.de,linux-sunxi@lists.linux.dev]; R_SPF_ALLOW(0.00)[+ip4:172.234.253.10]; FREEMAIL_TO(0.00)[kernel.org,gmail.com,sholland.org,ultimaker.com]; TO_DN_SOME(0.00)[]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[100.90.174.1:received,185.203.200.13:received,2a0a:edc0:0:c01:1d::a2:received]; RCVD_COUNT_FIVE(0.00)[6]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; R_DKIM_NA(0.00)[]; ASN(0.00)[asn:63949, ipnet:172.234.224.0/19, country:SG]; RCVD_TLS_LAST(0.00)[]; TAGGED_FROM(0.00)[bounces-25660-noreply=patchwork.local]; MIME_TRACE(0.00)[0:+]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.234.253.10:from] X-Rspamd-Queue-Id: 0F68A1C550F 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?= From: Marc Kleine-Budde In commit 196737912da5 ("spi: sun4i: Allow transfers larger than FIFO size"), support for transfers larger than the FIFO size was added. This commit moves the draining of the RX-FIFO from sun4i_spi_transfer_one() (after completion of the transfer) to the IRQ handler when the IRQ "transfer complete" is handled. In addition, the IRQ "RX-FIFO 3/4 full" is activated for all transfers. However, this does not take into account that the RX-IRQ for transfers that exceed 3/4 of the FIFO size is still pending after the IRQ "transfer complete" has been processed. All interrupt sources are only deactivated after the wait_for_completion_timeout() in sun4i_spi_transfer_one(). This opens a race window for "RX-FIFO 3/4 full" interrupts to come. The sequence is as follows: | sun4i_spi_transfer_one() | sun4i_spi_fill_fifo() // fill TX-FIFO with 48 bytes | // enable RX-FIFO 3/4 full IRQ | wait_for_completion_timeout(); | | // SPI controller transfers 48 bytes | // SPI controller issues "transfer complete" and "RX-FIFO 3/4 full" IRQ | | // IRQ handler start | sun4i_spi_handler() | // ACK "transfer complete" IRQ | sun4i_spi_drain_fifo(); | complete(); ----. | return IRQ_HANDLED; \ | // IRQ handler end \__ race | / window | // wait_for_completion_timeout() continues / | // disable all IRQ sources ----' Avoid the race condition by disabling all interrupts when handling the "transfer complete" IRQ and before calling complete(). Also move the draining of the RX-FIFO back into sun4i_spi_transfer_one() where it was before commit 196737912da5 ("spi: sun4i: Allow transfers larger than FIFO size"). This has the added benefit of spending a little less time in the IRQ handler. Cc: Tobias Schramm Fixes: 196737912da5 ("spi: sun4i: Allow transfers larger than FIFO size") Signed-off-by: Marc Kleine-Budde Signed-off-by: Jonas Rebmann --- drivers/spi/spi-sun4i.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/drivers/spi/spi-sun4i.c b/drivers/spi/spi-sun4i.c index 8a9dcd3b6b8f..ea8be0170fbf 100644 --- a/drivers/spi/spi-sun4i.c +++ b/drivers/spi/spi-sun4i.c @@ -82,6 +82,8 @@ struct sun4i_spi { struct completion done; + int irq; + const u8 *tx_buf; u8 *rx_buf; int len; @@ -333,6 +335,7 @@ static int sun4i_spi_transfer_one(struct spi_controller *host, start = jiffies; time_left = wait_for_completion_timeout(&sspi->done, msecs_to_jiffies(tx_time)); + end = jiffies; if (!time_left) { dev_warn(&host->dev, @@ -340,12 +343,11 @@ static int sun4i_spi_transfer_one(struct spi_controller *host, dev_name(&spi->dev), tfr->len, tfr->speed_hz, jiffies_to_msecs(end - start), tx_time); ret = -ETIMEDOUT; - goto out; + sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, 0); + synchronize_irq(sspi->irq); } - -out: - sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, 0); + sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH); return ret; } @@ -357,8 +359,7 @@ static irqreturn_t sun4i_spi_handler(int irq, void *dev_id) /* Transfer complete */ if (status & SUN4I_INT_CTL_TC) { - sun4i_spi_write(sspi, SUN4I_INT_STA_REG, SUN4I_INT_CTL_TC); - sun4i_spi_drain_fifo(sspi, SUN4I_FIFO_DEPTH); + sun4i_spi_write(sspi, SUN4I_INT_CTL_REG, 0); complete(&sspi->done); return IRQ_HANDLED; } @@ -456,6 +457,7 @@ static int sun4i_spi_probe(struct platform_device *pdev) return ret; } + sspi->irq = irq; sspi->host = host; host->max_speed_hz = 100 * 1000 * 1000; host->min_speed_hz = 3 * 1000;