From patchwork Sat Oct 17 19:46:00 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3662 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from tor.lore.kernel.org (tor.lore.kernel.org [172.105.105.114]) by mxe881.netcup.net (Postfix) with ESMTPS id C063C1C031A for ; Sat, 17 Oct 2026 21:47:18 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 172.105.105.114) smtp.mailfrom=linux-sunxi+bounces-26732-noreply=patchwork.local@lists.linux.dev smtp.helo=tor.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 172.105.105.114 as permitted sender) client-ip=172.105.105.114; envelope-from=linux-sunxi+bounces-26732-noreply=patchwork.local@lists.linux.dev; helo=tor.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by tor.lore.kernel.org (Postfix) with ESMTP id 98C68385ED for ; Sat, 17 Oct 2026 19:46:46 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 07DA9492E23; Sat, 17 Oct 2026 19:46:29 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="oCmpqKCA" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-oi1-f177.google.com (mail-oi1-f177.google.com [209.85.167.177]) (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 4706148877F for ; Sat, 17 Oct 2026 19:46:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.177 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266388; cv=none; b=ObRn7tiVDAzc/fE2cMCZeduAAjvV++BdxUvZwAreKB6akTrN+EqaCI6wkGpgGj72w9QcvYTg6Qh90YnvzXQQtU34znYzgspnE+IKWJrMy5Fen/G6VuASR75cvSNLBs8OLgDpz7D8KRXz0JOW8VzJw7G2Lvy1dzNTW4ZfONUregQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792266388; c=relaxed/simple; bh=ONUCfWg8eM4/OtI3jBJJ3OP+uv5/g7o8HsUMHh6rAVg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ZWC7D1siBdyR0lZOwT5ECktcqSqBCkyBiBJnB+3GP2LkbC72vS2URSa4zVoXpg8HrBh3zx1ZgMANfIrhxVvAsPIcPNOaDcz/kufpUawIRMvSme+9jpe79LMblK3PfdvZ9nTEQbdgLeTzfcv88QLvVEcQZXr+83WVZXrO8IFEIUA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=oCmpqKCA; arc=none smtp.client-ip=209.85.167.177 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-oi1-f177.google.com with SMTP id 5614622812f47-4f699fe49b3so728245b6e.3 for ; Sat, 17 Oct 2026 12:46:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792266380; x=1792871180; darn=lists.linux.dev; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=S+Qvi+dU4vtXa5pndLAyH0EZ9I1y6W0niIp108EHDPk=; b=oCmpqKCAmxwSwJ8yZUC11kENVZoBlXJNXjyTWIeNk5oqPB3HfU/+NcokzxtK4tN1nK NRyupKj0G5UuuwSLqCPesK3pZs/BrwnYUrD+nqp+52/vWGr5xwy/uxfuZ/w8/QG0PPZp CLhjQK6mRma/aIaTeJs0qE2nY9iKshSsrfwdXvKW7uxvD/RMB/MpANu22eUhdwwUE/Vx ctG4qI8TBSB4YRgp2QtAgK70RLeqhcrgqKwXMOMuc2AwDS5belN6xacJf1IBIfuRKC+x PVkVBXz34bi1c3u67l38OSIkBjge1KjVpgVxuscgcSPQpPuzRit1wmvAlCbe2PwuNW2s qDHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792266380; x=1792871180; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :content-type:mime-version:subject:date:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=S+Qvi+dU4vtXa5pndLAyH0EZ9I1y6W0niIp108EHDPk=; b=uBEiZwv2jfF29vOTfC57ayKZPwov6Hs7Pp2eo8wW9hG/K/cU0JnDOZHnAv5cSuD7M3 jg2QHUd7vfRdHmfV5G7wRlmjbaE6gfmB6w2by8pxYY9f5+4CgyEEkquseE15kGNdc8cS nK3r+1WCNGE/1nQVh85newEYevMtwuqo+DGpnPQ4HxzCLm2PJtt36LTYUosbT+7zU7nh uRwXVioZsCh4FT6jtjaRz6Dkc0mrNBcKHL3AilDhUcSHv6749kyhaS90SIiw6ftCd6tZ g4vlAfmp7oBzJjeDioUOPoJRo47viGrc5Gepb8tURABlN5JLL86pqlLG4PIDdH9SpELA HRfw== X-Forwarded-Encrypted: i=1; AKwUvBy+ricOwdRtanO1b5LySMgB4AGfVvOvHtKOr29vXAJ4CmdRmcQzqAAoghyo068w6com0x9a/sFbtL2JZA==@lists.linux.dev X-Gm-Message-State: AFq9FYKZ1T3A7mmVls8bYNh30pwEQhUi9bAfyAYnhubNMK66tumxXIiJ kFAScmYm4QYbHmzSWrm5QvKa/z/rcGJs5k3uz1pj1o0eVGqvofixQ6Oo X-Gm-Gg: AYBFou1MimXDNIZm17WhEqyHPe3lAeyZXgsMtvrMIPyF7E+8fAsC3qeyke+rmJIGI2B tQnSOQstwXLbGRifMuMtq7kDtDqaRG2NsldfxHR9nRazwLaJTzjNq7+kWfZcO+rB/EIzyxPMipu oD6bkVQraOjxU2BH1Y+uQpxzOT0xbPT8K1VEp6y4ZEvvsTDteOfnCdBpg7r1k6rbFSGIJciIhxQ Wh6JCzuI5JvZzTFlJfwgSvO5D+MIiUnJGNOnJHWcm9LHHs2yVK18/0wbe1wWD8e3VziycR8TRT3 ZRRLLRY9JmHrRes44rVYJmBvlx+8RbfvGjOTzpCTwcZCWdQItT3M4hBnfdHY9qD5aEZ8ocZ2QKS 1jS9RfMzxn1ZCZtfDyVWefV3wxQYxpA5Ep75NFCr4N0gI8KfeD1ufW+hONsKJLnT987fd8ERy3/ kixArF+cXrC+gn3LK3kefwT44xR38ZeQK37z+hTVrCmw95veAohDvccuJeve4ibrGxAdIkC/JMW LrklQ1r3uQ5J2QAKYAj2rtGjoSrEUhUiizfBh7YZTt3J7h7gS2tkEH3xQp5AS1NPWRdKuZnJ0R4 xVM0kuthC8uf2nCVqMJI4eIwllG07YGjCfUdTt/r+R4AwQKtg0m0b/eImVw3BQzQylZ0gADuYhJ G4mP5adjyv4MCMSv5Hk4ZRQ== X-Received: by 2002:a05:6808:4f28:b0:4f3:e98f:fa26 with SMTP id 5614622812f47-53cd1cb5c49mr3420662b6e.58.1792266379933; Sat, 17 Oct 2026 12:46:19 -0700 (PDT) Received: from [127.0.1.1] (174-29-1-49.hlrn.qwest.net. [174.29.1.49]) by smtp.gmail.com with ESMTPSA id 5614622812f47-5388dd8b5a2sm4025321b6e.12.2026.10.17.12.46.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 17 Oct 2026 12:46:19 -0700 (PDT) From: James Hilliard Date: Sat, 17 Oct 2026 13:46:00 -0600 Subject: [PATCH v9 05/18] mtd: rawnand: sunxi: drain interrupts before reusing the completion Precedence: bulk X-Mailing-List: linux-sunxi@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-5-b624c09e3ee5@gmail.com> References: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> In-Reply-To: <20261017-submit-sunxi-nand-vendor-oob-layout-v1-v9-0-b624c09e3ee5@gmail.com> To: Miquel Raynal , Richard Weinberger , Vignesh Raghavendra , Sebastian Andrzej Siewior , Clark Williams , Steven Rostedt , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: Chen-Yu Tsai , Jernej Skrabec , Samuel Holland , Maxime Ripard , Richard Genoud , Boris Brezillon , Masahiro Yamada , Brian Norris , linux-mtd@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org, linux-rt-devel@lists.linux.dev, devicetree@vger.kernel.org, James Hilliard , Sashiko X-Mailer: b4 0.15.2 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?= The controller uses one completion for successive interrupt-driven waits. Some transfers wait for both command completion and DMA completion. The handler acknowledges each event and masks it, leaving any outstanding event enabled; it calls complete() when all requested events have arrived. sunxi_nfc_interrupt() currently calls complete() before updating those registers. A successful waiter can wake on another CPU and start the next operation before the old handler acknowledges status or rewrites the mask. Move complete() after those updates so waking the waiter cannot precede the handler's last controller access. A timeout also needs to exclude an unfinished handler. With PREEMPT_RT, the flags-zero IRQ request is forced threaded. Near the timeout boundary, that thread can be preempted after reading status and enable bits while the waiter times out, clears the device mask and rearms the next wait. The saved snapshot can then restore an obsolete remaining-event mask or, if it satisfies the old wait, complete the new wait. Masking the device does not invalidate the running handler's local values. Repeating init_completion() can also reset its waitqueue lock during complete(). This lifetime problem was identified by code inspection during review. Initialize the completion once in probe and use reinit_completion() for each wait. On timeout, call disable_irq() before clearing controller state so existing handling finishes and no new handler can enter during cleanup. The hardware may have finished before the delayed handler runs, or the handler may complete the wait while disable_irq() drains it. Recheck status against the remaining enabled events before clearing either register. Events already acknowledged by the handler no longer appear in that mask; if none remain, the wait has completed. This also handles command and DMA events arriving separately without requiring an already acknowledged status bit to be set again. Then mask and acknowledge the events, read back the mask to flush those writes, and re-enable the IRQ line even if the recheck changed the timeout to success. Keep partial-event handling in the IRQ handler and leave polling and controller/DMA abort handling unchanged. This keeps additional synchronization on the timeout path, without a driver lock in every interrupt and wait. The caller can sleep, this IRQ is not registered as shared, and the handler does not acquire the controller mutex held by the caller. The tradeoff is unbounded cleanup latency and no priority inheritance: a starved IRQ thread can prevent timeout cleanup from returning and block other operations on the controller. This is a handler-lifetime boundary, not an RT recovery-latency guarantee. Fixes: 1fef62c1423b ("mtd: nand: add sunxi NAND flash controller support") Reported-by: Sashiko Closes: https://lore.kernel.org/r/20260909085434.C8F201F00A3A@smtp.kernel.org Signed-off-by: James Hilliard Reviewed-by: Sebastian Andrzej Siewior --- drivers/mtd/nand/raw/sunxi_nand.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 29715d179d22..5b736a4a7fe9 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -401,6 +401,7 @@ struct sunxi_nfc_caps { * @chips: a list containing all the NAND chips attached to this NAND * controller * @complete: a completion object used to wait for NAND controller events + * @irq: NAND controller interrupt * @dmac: the DMA channel attached to the NAND controller * @use_mdma: use an internal MBUS DMA backend * @mdma_desc: H6-style MBUS DMA descriptor @@ -420,6 +421,7 @@ struct sunxi_nfc { unsigned long clk_rate; struct list_head chips; struct completion complete; + int irq; struct dma_chan *dmac; bool use_mdma; struct sunxi_nfc_mdma_desc *mdma_desc; @@ -441,18 +443,20 @@ static irqreturn_t sunxi_nfc_interrupt(int irq, void *dev_id) if (!(ien & st)) return IRQ_NONE; - if ((ien & st) == ien) - complete(&nfc->complete); - + /* Finish updating the interrupt state before waking the next operation. */ writel(st & NFC_INT_MASK, nfc->regs + NFC_REG_ST); writel(~st & ien & NFC_INT_MASK, nfc->regs + NFC_REG_INT); + if ((ien & st) == ien) + complete(&nfc->complete); + return IRQ_HANDLED; } static int sunxi_nfc_wait_events(struct sunxi_nfc *nfc, u32 events, bool use_polling, unsigned int timeout_ms) { + bool irq_disabled = false; int ret; if (events & ~NFC_INT_MASK) @@ -462,16 +466,28 @@ static int sunxi_nfc_wait_events(struct sunxi_nfc *nfc, u32 events, timeout_ms = NFC_DEFAULT_TIMEOUT_MS; if (!use_polling) { - init_completion(&nfc->complete); + reinit_completion(&nfc->complete); writel(events, nfc->regs + NFC_REG_INT); ret = wait_for_completion_timeout(&nfc->complete, msecs_to_jiffies(timeout_ms)); - if (!ret) - ret = -ETIMEDOUT; - else + if (!ret) { + u32 pending, status; + + /* Drain the handler before it can restore an old IRQ mask. */ + disable_irq(nfc->irq); + irq_disabled = true; + /* + * The handler removes acknowledged events from the mask. + * An empty mask means all requested events were acknowledged. + */ + pending = readl(nfc->regs + NFC_REG_INT) & events; + status = readl(nfc->regs + NFC_REG_ST); + ret = (status & pending) == pending ? 0 : -ETIMEDOUT; + } else { ret = 0; + } writel(0, nfc->regs + NFC_REG_INT); } else { @@ -484,6 +500,12 @@ static int sunxi_nfc_wait_events(struct sunxi_nfc *nfc, u32 events, writel(events & NFC_INT_MASK, nfc->regs + NFC_REG_ST); + if (irq_disabled) { + /* Flush the mask and acknowledgment before re-enabling the IRQ. */ + readl(nfc->regs + NFC_REG_INT); + enable_irq(nfc->irq); + } + if (ret) dev_err(nfc->dev, "wait interrupt timedout\n"); @@ -2664,6 +2686,7 @@ static int sunxi_nfc_probe(struct platform_device *pdev) nfc->dev = dev; nand_controller_init(&nfc->controller); INIT_LIST_HEAD(&nfc->chips); + init_completion(&nfc->complete); nfc->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &r); if (IS_ERR(nfc->regs)) @@ -2672,6 +2695,7 @@ static int sunxi_nfc_probe(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); if (irq < 0) return irq; + nfc->irq = irq; nfc->caps = of_device_get_match_data(dev); if (!nfc->caps)