From patchwork Fri Oct 16 03:45:19 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Hilliard X-Patchwork-Id: 3634 Return-Path: X-Original-To: noreply@patchwork.local Delivered-To: noreply@patchwork.local Received: from sin.lore.kernel.org (sin.lore.kernel.org [104.64.211.4]) by mxe881.netcup.net (Postfix) with ESMTPS id 7A0541C2044 for ; Fri, 16 Oct 2026 05:46:20 +0200 (CEST) Authentication-Results: mxe881; dkim=pass header.d=gmail.com; spf=pass (sender IP is 104.64.211.4) smtp.mailfrom=linux-sunxi+bounces-26679-noreply=patchwork.local@lists.linux.dev smtp.helo=sin.lore.kernel.org Received-SPF: pass (mxe881: domain of lists.linux.dev designates 104.64.211.4 as permitted sender) client-ip=104.64.211.4; envelope-from=linux-sunxi+bounces-26679-noreply=patchwork.local@lists.linux.dev; helo=sin.lore.kernel.org; Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org [100.90.174.1]) by sin.lore.kernel.org (Postfix) with ESMTP id 7B3F92944B for ; Fri, 16 Oct 2026 03:45:47 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8EAB92931D1; Fri, 16 Oct 2026 03:45:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="kNDeZj4W" X-Original-To: linux-sunxi@lists.linux.dev Received: from mail-ot1-f42.google.com (mail-ot1-f42.google.com [209.85.210.42]) (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 353EF39B4AF for ; Fri, 16 Oct 2026 03:45:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.42 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122336; cv=none; b=MGCYGxfwj+KajF4mhvu17xRhwrszhuDN7LxEvejxMP/j2o3yOkDfEJ7GVwXjppnAUJ03BVQPycPfrv+jC4OPvJ7EICsXjxdYBeTfmiDErY9gjNijiKnwQdvmZ09Y/EOsuHMBv3yfyWpuE+tqj0GgClNg4XzqJaRk60ctbESUpcY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1792122336; c=relaxed/simple; bh=rEuLYDr43bv01Uvpdc+7lvdWEzGSSi8n2u7CVCX1ggM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=cMa6ba74z10UGA2mpiUDPeVt1IHrG6Y2agni+NOe3N2kgirLZhul9UXiXPP6r+CudnfGh8FF29bUhXRjN2OFqpR1io8bDdD/K9MBqyMFegukGZex6TyMHuoKFiGeWN/XJD1arrGcMztk/XtkgbPAzXsYE5ovTT20GXh2K9FLL00= 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=kNDeZj4W; arc=none smtp.client-ip=209.85.210.42 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-ot1-f42.google.com with SMTP id 46e09a7af769-823e4047037so4571154a34.2 for ; Thu, 15 Oct 2026 20:45:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1792122333; x=1792727133; 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=piZMAcnvcZQBNALlEjasAqt9FGU3IFC9Bc/Ax/PGx1o=; b=kNDeZj4W86sVQky2jPxnJPGFzgx48LJyzOKK6lbJWJqnNPpRb689ttpDHJNDDoh0B2 JJn0pt1DG3QdH0JHZTTHpzuIhWRy84VVF/1rBKuXQ9iOYoL9iffE2waLNN3eN82YB8yc TjrnoGgmxKj5NM3Vd7HvqXC9xQRHNLBeGy4VpLZQnRv/IubfRBFdscANvt7zyngTJdU4 FYLo0YT3spnUnaFvkIDjUkPQsdy0z+8ijCbfDQds0l466GLGfgSBvijC+PfpV7cjVjAR eF3NswwXFeAjmKiUviZi4I8CyLxGF96XLZw+zLq9OQXTrhUzHFFX3lKCmccg+4wTZ2As XoJw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1792122333; x=1792727133; 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=piZMAcnvcZQBNALlEjasAqt9FGU3IFC9Bc/Ax/PGx1o=; b=pmOFQC8XjhpVSua0B2ZTYdLwGqdUNwNsRJY8mt9i8VFYyGquBGMgdMM9YPVd+4yAA4 7qbI6cgqmGZozRTseclmyRBY9cnvHb4KJDvtMKe50hKhmFBHcuU6n6/AeFvrBl+WUIJC IPC1ztqGpjlMy2U7I2pXbBhXTEGMhw4GjIC2f3+QuBWIvSg14E2hNRlVVw4Sv5zleS3A uXsXQ4COm156TBNmZ/p58LvrBUzUMUX5bZKc8blK5uoYDBnt948ELyT9uPw9JWUJxTpA Qh22De1nfCC8M20LfkVAXhL3wI0RRZ862NE2PzIZ8JGFqls+OhUgMIsRjNaNt+VK5uEo 1k9A== X-Forwarded-Encrypted: i=1; AKwUvBxwlKhNOiPpXUo40x9KDqO9MGuFrNRywckuClaNSvFufBIDjcWutREPOcD1srN8jILFts+UPTCt62T/QQ==@lists.linux.dev X-Gm-Message-State: AFq9FYIf689jieMNG0WRAjfa0OdIZeAOYWU//T+uDxSEV1d993JVi60Q xnanA+D0fC5cWrJJzeTR6cApFIjiKAGLTFVGJNZ59OcLHRNFIdVP82fy X-Gm-Gg: AYBFou2TUV2T1naOzLFQRiZ4OwpIIfBIaxXiidozL3wnMSzq4z2pxD9u97x1APUkDd+ Yce1n6NBhSo9laMP/yhIyVy9jsNhIW3Z3cu/SZYFamuGCynDM5k4k77AmuPiTfDMsqdAKZmqmHb WMhpkdvNwAznPuQ8qDIT6AwrNXM/DqPREVyyyCsn6w9YO3H45ZG8wjsedSxoi4a6G87P8fjzUcR /Fhn7iBKiaEx8fhp3wcN4zKd2rHEPNaK92z52Q0uZvVNdQTe/Ey5l8rVP+Ou1BSyzOm2xuPq/f9 RTYVd+BNPQhn7DqWHmqQEJbi45h9IUzNtVqmErigj591LkIbi/hBXxkabfONwTZbzfnpOxWOuyC VjwJMclNwmO1Wpt6R3HCvvxmmIeWjR/8XvzIX5nS3Cheu2Greflp01nEApV2AazSGlf5bFMptRa CagTg8TM3y9LLKPlmw6/7aThOTlPxaM7H86ytxRJN+SFxrOQuZJC5vrSXGO7lWVGpavgw4WzMV5 CEhg97Gd6Dn/yoIc7QbJ2xG5AvseN/2Fw025XDOh59Eri7mLIGz8qdPwf+ur6s8irxuXw98Ayfb dtuM40rZ3dm4/G+fpYes+iQ4Xu3JFPsBqZaXSO71oIB6ptIy3aNvpJBHbXmGG2kj1qLS75yPQzg OigQ+v5ImY+smjk8XhUy/EpNGHDxepKUd X-Received: by 2002:a05:6830:270d:b0:80c:d34f:5f63 with SMTP id 46e09a7af769-8309814be28mr19957456a34.28.1792122332994; Thu, 15 Oct 2026 20:45:32 -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 46e09a7af769-8429b57870fsm834402a34.0.2026.10.15.20.45.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 15 Oct 2026 20:45:32 -0700 (PDT) From: James Hilliard Date: Thu, 15 Oct 2026 21:45:19 -0600 Subject: [PATCH v8 04/17] 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: <20261015-submit-sunxi-nand-vendor-oob-layout-v1-v8-4-8ba4881fbee8@gmail.com> References: <20261015-submit-sunxi-nand-vendor-oob-layout-v1-v8-0-8ba4881fbee8@gmail.com> In-Reply-To: <20261015-submit-sunxi-nand-vendor-oob-layout-v1-v8-0-8ba4881fbee8@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 X-Mailer: b4 0.15.2 X-Rspamd-Server: rspamd-worker-8404 X-Spamd-Result: default: False [-1.16 / 15.00]; BAYES_HAM(-5.50)[100.00%]; RBL_SENDERSCORE(2.00)[104.64.211.4:from]; SUSPICIOUS_RECIPS(1.50)[]; DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed), No valid DKIM,none]; MAILLIST(-0.15)[generic]; BAD_REP_POLICIES(0.10)[]; MIME_GOOD(-0.10)[text/plain]; HAS_LIST_UNSUB(-0.01)[]; FORGED_SENDER_MAILLIST(0.00)[]; ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1]; FROM_HAS_DN(0.00)[]; RCPT_COUNT_TWELVE(0.00)[24]; PRECEDENCE_BULK(0.00)[]; FREEMAIL_CC(0.00)[kernel.org,gmail.com,sholland.org,bootlin.com,socionext.com,lists.infradead.org,lists.linux.dev,vger.kernel.org]; TAGGED_RCPT(0.00)[dt]; DBL_BLOCKED_OPENRESOLVER(0.00)[sin.lore.kernel.org:rdns,sin.lore.kernel.org:helo]; RCVD_COUNT_FIVE(0.00)[6]; ASN(0.00)[asn:63949, ipnet:104.64.192.0/19, country:SG]; TO_DN_SOME(0.00)[]; R_SPF_ALLOW(0.00)[+ip4:104.64.211.4:c]; RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[100.90.174.1:received,174.29.1.49:received,209.85.210.42:received]; RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[104.64.211.4:from]; FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev]; FREEMAIL_FROM(0.00)[gmail.com]; MIME_TRACE(0.00)[0:+]; TAGGED_FROM(0.00)[bounces-26679-noreply=patchwork.local]; FORGED_RECIPIENTS_MAILLIST(0.00)[]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_TLS_LAST(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[] X-Rspamd-Queue-Id: 7A0541C2044 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") Signed-off-by: James Hilliard --- drivers/mtd/nand/raw/sunxi_nand.c | 35 ++++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/mtd/nand/raw/sunxi_nand.c b/drivers/mtd/nand/raw/sunxi_nand.c index 6c0d3e2d2be2..f7ddd4116bf4 100644 --- a/drivers/mtd/nand/raw/sunxi_nand.c +++ b/drivers/mtd/nand/raw/sunxi_nand.c @@ -393,6 +393,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 @@ -412,6 +413,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; @@ -433,18 +435,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) @@ -454,16 +458,25 @@ 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. */ + 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 { @@ -476,6 +489,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"); @@ -2650,6 +2669,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)) @@ -2658,6 +2678,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)