From: Miquel Raynal <miquel.raynal@bootlin.com>
To: James Hilliard <james.hilliard1@gmail.com>
Cc: Richard Weinberger <richard@nod.at>,
Vignesh Raghavendra <vigneshr@ti.com>,
Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>,
Chen-Yu Tsai <wens@kernel.org>,
Jernej Skrabec <jernej.skrabec@gmail.com>,
Samuel Holland <samuel@sholland.org>,
Maxime Ripard <mripard@kernel.org>,
Richard Genoud <richard.genoud@bootlin.com>,
Masahiro Yamada <yamada.masahiro@socionext.com>,
Boris Brezillon <bbrezillon@kernel.org>,
Brian Norris <computersforpeace@gmail.com>,
linux-mtd@lists.infradead.org, devicetree@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org,
stable@vger.kernel.org
Subject: Re: [PATCH v6 01/18] mtd: rawnand: sunxi: drain interrupts before reusing the completion
Date: Mon, 12 Oct 2026 21:06:28 +0200 [thread overview]
Message-ID: <877bjmzqkr.fsf@bootlin.com> (raw)
In-Reply-To: <CADvTj4pmtGZ4c04q+5AE3trrfshToD7BPtF-8kPxPRZ25hOTRw@mail.gmail.com> (James Hilliard's message of "Mon, 12 Oct 2026 12:26:00 -0600")
On 12/10/2026 at 12:26:00 -06, James Hilliard <james.hilliard1@gmail.com> wrote:
> On Mon, Oct 12, 2026 at 12:02 PM Miquel Raynal
> <miquel.raynal@bootlin.com> wrote:
>>
>> Hi James,
>>
>> On 14/09/2026 at 15:09:47 -06, James Hilliard <james.hilliard1@gmail.com> wrote:
>>
>> > A timed-out wait can return while the interrupt handler is still using
>> > the previous operation's interrupt status and enable mask. Starting the
>> > next wait calls init_completion() on the same object, which can reset its
>> > waitqueue lock while the old handler calls complete(). The old handler
>> > can also complete the new wait or restore an obsolete interrupt mask.
>> >
>> > Initialize the completion once in probe and use reinit_completion() for
>> > each interrupt-driven wait. On timeout, disable and synchronize the IRQ
>> > before masking controller interrupts and acknowledging the waited-for
>> > events. Draining the handler first also prevents a partial-event handler
>> > from rewriting the enable mask after it has been cleared. Flush these
>> > register writes before re-enabling the IRQ line, leaving the controller's
>> > interrupt sources masked.
>> >
>> > For successful waits, move complete() after the handler's register updates
>> > so that the next operation cannot race with those updates. Keep polling
>> > unchanged and leave controller and DMA abort handling to the existing
>> > callers.
>> >
>> > Fixes: 1fef62c1423b ("mtd: nand: add sunxi NAND flash controller support")
>> > Cc: stable@vger.kernel.org
>> > Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
>> > ---
>>
>> So from the commit log I understand that you are fixing a race. The
>> problem seems legitimate.
>>
>> > drivers/mtd/nand/raw/sunxi_nand.c | 26 ++++++++++++++++++++------
>> > 1 file changed, 20 insertions(+), 6 deletions(-)
>> >
>>
>> ...
>>
>> > @@ -414,12 +416,13 @@ 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;
>> > }
>> >
>> > @@ -435,16 +438,19 @@ 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);
>>
>> The whole change around (re)init_completion looks relevant (here and in the handler).
>>
>> >
>> > writel(events, nfc->regs + NFC_REG_INT);
>> > ret = wait_for_completion_timeout(&nfc->complete,
>> > msecs_to_jiffies(timeout_ms));
>> > - if (!ret)
>> > + if (!ret) {
>> > + /* Drain the handler before it can restore an old IRQ mask. */
>> > + disable_irq(nfc->irq);
>>
>> disable_irq() for serializing accesses to a single register?
>
> The intention was to drain an in-flight handler before cleaning up the
> timed-out wait, rather than just serialize the register write.
I guess here you relate to the race explained below.
> disable_irq() provides that synchronization as well as masking the line.
> It is only used on timeout, and this IRQ is requested without
> IRQF_SHARED.
This is clearly debatable, since we can identify the IRQ, that flag
could (should, maybe) have been set. With your approach it would have
been even more impacting. But that's not the point.
> A spinlock could also address this, provided it covers the handler's
> status/enable reads through complete(), together with the waiter's
> cleanup and rearming. Protecting only the register writes would leave
> the handler able to act on an old snapshot.
I'm not sure what you call "only the register writes", you can call
complete() from within the lock if that makes sense for this case,
yes. complete() does not block so it is fine.
...
>> commit log, I now disagree with the first part of:
>>
>> >The old handler can also complete the new wait or restore an obsolete interrupt mask.
>>
>> "complete the new wait"? I don't see how a stale handler completes the
>> next wait given the handler is a hard IRQ and the interrupt enable
>> register is cleared on timeout.
>
> The case I had in mind is an already-running handler on another CPU:
>
> CPU 0: Read st and ien for operation A.
> CPU 1: Time out operation A, mask/acknowledge its interrupts,
> then eventually reinitialize the completion for operation B.
> CPU 0: Call complete() based on the saved st and ien from operation A.
For this to fire, the hard IRQ handler on CPU0 would have to be stopped
between reading st/ien and calling complete() long enough to span:
- A's timeout
- A's cleanup
- B's wait being rearmed
On this hardware, how is this reachable?
> Clearing the device's enable register does not invalidate those local
> values or wait for the running handler to finish. Hard-IRQ context
> prevents this overlap on the same CPU, but not across CPUs.
>
> That distinction was not explicit enough in the commit message. I'm
> open to a different implementation; the requirement I wanted to preserve
> is that the old handler cannot update the mask or signal the completion
> after the waiter has cleaned up and reused it.
Miquèl
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
next prev parent reply other threads:[~2026-10-13 17:54 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-14 21:09 [PATCH v6 00/18] mtd: rawnand: sunxi: support the Allwinner randomized OOB format James Hilliard
2026-09-14 21:09 ` [PATCH v6 01/18] mtd: rawnand: sunxi: drain interrupts before reusing the completion James Hilliard
2026-10-12 18:01 ` Miquel Raynal
2026-10-12 18:26 ` James Hilliard
2026-10-12 19:06 ` Miquel Raynal [this message]
2026-10-12 19:17 ` James Hilliard
2026-10-12 20:53 ` Miquel Raynal
2026-10-12 21:43 ` James Hilliard
2026-09-14 21:09 ` [PATCH v6 02/18] mtd: rawnand: sunxi: use the logical step's OOB length in PIO James Hilliard
2026-09-14 21:09 ` [PATCH v6 03/18] mtd: rawnand: sunxi: propagate page-setup and erased-check errors James Hilliard
2026-09-14 21:09 ` [PATCH v6 04/18] mtd: rawnand: sunxi: stop failed program operations and disable ECC James Hilliard
2026-09-14 21:09 ` [PATCH v6 05/18] mtd: rawnand: sunxi: select the pattern ID for the current ECC step James Hilliard
2026-09-14 21:09 ` [PATCH v6 06/18] mtd: rawnand: sunxi: propagate buffer and column transfer errors James Hilliard
2026-09-14 21:09 ` [PATCH v6 07/18] mtd: rawnand: sunxi: avoid a second program confirm for OOB writes James Hilliard
2026-09-14 21:09 ` [PATCH v6 08/18] mtd: rawnand: sunxi: avoid redundant column changes for extra OOB James Hilliard
2026-09-14 21:09 ` [PATCH v6 09/18] mtd: rawnand: sunxi: use page reads to reposition small-page NAND James Hilliard
2026-09-14 21:09 ` [PATCH v6 10/18] mtd: rawnand: sunxi: bound DMA batches by the user-data register bank James Hilliard
2026-09-14 21:09 ` [PATCH v6 11/18] mtd: rawnand: sunxi: clarify OOB register and step handling James Hilliard
2026-09-14 21:09 ` [PATCH v6 12/18] dt-bindings: mtd: sunxi: Add randomized OOB flag James Hilliard
2026-09-15 16:56 ` Conor Dooley
2026-09-14 21:09 ` [PATCH v6 13/18] mtd: rawnand: sunxi: support randomized OOB formats James Hilliard
2026-09-14 21:10 ` [PATCH v6 14/18] mtd: rawnand: sunxi: select the packed H6/H616 OOB layout James Hilliard
2026-09-14 21:10 ` [PATCH v6 15/18] mtd: rawnand: sunxi: combine contiguous unprotected OOB reads James Hilliard
2026-09-14 21:10 ` [PATCH v6 16/18] mtd: rawnand: sunxi: avoid duplicate chip setup before page commands James Hilliard
2026-09-14 21:10 ` [PATCH v6 17/18] mtd: rawnand: sunxi: reduce user-data length register accesses James Hilliard
2026-09-14 21:10 ` [PATCH v6 18/18] mtd: rawnand: sunxi: reuse ECC status within each DMA read James Hilliard
2026-10-12 8:06 ` [PATCH v6 00/18] mtd: rawnand: sunxi: support the Allwinner randomized OOB format Miquel Raynal
2026-10-12 8:56 ` James Hilliard
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=877bjmzqkr.fsf@bootlin.com \
--to=miquel.raynal@bootlin.com \
--cc=bbrezillon@kernel.org \
--cc=computersforpeace@gmail.com \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=james.hilliard1@gmail.com \
--cc=jernej.skrabec@gmail.com \
--cc=krzk+dt@kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
--cc=linux-sunxi@lists.linux.dev \
--cc=mripard@kernel.org \
--cc=richard.genoud@bootlin.com \
--cc=richard@nod.at \
--cc=robh@kernel.org \
--cc=samuel@sholland.org \
--cc=stable@vger.kernel.org \
--cc=vigneshr@ti.com \
--cc=wens@kernel.org \
--cc=yamada.masahiro@socionext.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox