Linux-mtd Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] mtd: rawnand: r852: preserve card changes during detection work
@ 2026-11-08 23:27 James Hilliard
  2026-11-08 23:43 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: James Hilliard @ 2026-11-08 23:27 UTC (permalink / raw)
  To: Miquel Raynal, Richard Weinberger, Vignesh Raghavendra,
	Maxim Levitsky
  Cc: linux-mtd, linux-kernel, stable, James Hilliard

r852_update_card_detect() reads and writes the card interrupt enable
register without holding irqlock. A card interrupt can mask detection
interrupts and mark the card unstable between those accesses, only for
the worker to overwrite the mask with its saved value.

The worker also calls this helper before and after registering or
unregistering a card. An interrupt between these calls starts a new
debounce interval, but the second call clears card_unstable and enables
interrupts again before that interval has elapsed. The interrupt can
also change card_detected between the worker's registration checks.

Hold irqlock across the interrupt mask update and leave the mask alone
while the card is unstable. Move the transition to stable state into
the locked card sample, and return that sample for both of the worker's
registration decisions.

Keep registration failure from overwriting a newer interrupt's card
state, so the next delayed work invocation can process that change.

Fixes: 67e054e91924 ("mtd: nand: Add driver for Ricoh xD/SmartMedia reader")
Cc: stable@vger.kernel.org
Closes: https://lore.kernel.org/r/sashiko-outbox-204068@kernel.org/
Closes: https://lore.kernel.org/r/sashiko-outbox-204135@kernel.org/
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
Changes in v2:
- Keep new debounce events pending until the next card-state sample.
- Use one presence sample for the worker's registration decisions.
- Protect the registration-failure update from newer IRQ events.
- Link to v1: https://patch.msgid.link/20261108-submit-r852-card-detect-lock-v1-v1-1-5514e7543209@gmail.com

To: Maxim Levitsky <maximlevitsky@gmail.com>
To: Miquel Raynal <miquel.raynal@bootlin.com>
To: Richard Weinberger <richard@nod.at>
To: Vignesh Raghavendra <vigneshr@ti.com>
Cc: linux-mtd@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
---
 drivers/mtd/nand/raw/r852.c | 35 ++++++++++++++++++++++++++---------
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c
index 92c47d351c27..4c094648673b 100644
--- a/drivers/mtd/nand/raw/r852.c
+++ b/drivers/mtd/nand/raw/r852.c
@@ -557,15 +557,20 @@ static void r852_engine_disable(struct r852_device *dev)
  * Test if card is present
  */
 
-static void r852_card_update_present(struct r852_device *dev)
+static bool r852_card_update_present(struct r852_device *dev)
 {
 	unsigned long flags;
 	uint8_t reg;
+	bool present;
 
 	spin_lock_irqsave(&dev->irqlock, flags);
 	reg = r852_read_reg(dev, R852_CARD_STA);
-	dev->card_detected = !!(reg & R852_CARD_STA_PRESENT);
+	present = !!(reg & R852_CARD_STA_PRESENT);
+	dev->card_detected = present;
+	dev->card_unstable = 0;
 	spin_unlock_irqrestore(&dev->irqlock, flags);
+
+	return present;
 }
 
 /*
@@ -574,8 +579,14 @@ static void r852_card_update_present(struct r852_device *dev)
  */
 static void r852_update_card_detect(struct r852_device *dev)
 {
-	int card_detect_reg = r852_read_reg(dev, R852_CARD_IRQ_ENABLE);
-	dev->card_unstable = 0;
+	unsigned long flags;
+	int card_detect_reg;
+
+	spin_lock_irqsave(&dev->irqlock, flags);
+	if (dev->card_unstable)
+		goto out;
+
+	card_detect_reg = r852_read_reg(dev, R852_CARD_IRQ_ENABLE);
 
 	card_detect_reg &= ~(R852_CARD_IRQ_REMOVE | R852_CARD_IRQ_INSERT);
 	card_detect_reg |= R852_CARD_IRQ_GENABLE;
@@ -584,6 +595,8 @@ static void r852_update_card_detect(struct r852_device *dev)
 		R852_CARD_IRQ_REMOVE : R852_CARD_IRQ_INSERT;
 
 	r852_write_reg(dev, R852_CARD_IRQ_ENABLE, card_detect_reg);
+out:
+	spin_unlock_irqrestore(&dev->irqlock, flags);
 }
 
 static ssize_t media_type_show(struct device *sys_dev,
@@ -632,6 +645,7 @@ static void r852_update_media_status(struct r852_device *dev)
 static int r852_register_nand_device(struct r852_device *dev)
 {
 	struct mtd_info *mtd = nand_to_mtd(dev->chip);
+	unsigned long flags;
 
 	WARN_ON(dev->card_registered);
 
@@ -657,7 +671,10 @@ static int r852_register_nand_device(struct r852_device *dev)
 	nand_cleanup(dev->chip);
 error1:
 	/* Force card redetect */
-	dev->card_detected = 0;
+	spin_lock_irqsave(&dev->irqlock, flags);
+	if (!dev->card_unstable)
+		dev->card_detected = 0;
+	spin_unlock_irqrestore(&dev->irqlock, flags);
 	return -1;
 }
 
@@ -684,20 +701,20 @@ static void r852_card_detect_work(struct work_struct *work)
 {
 	struct r852_device *dev =
 		container_of(work, struct r852_device, card_detect_work.work);
+	bool present;
 
-	r852_card_update_present(dev);
+	present = r852_card_update_present(dev);
 	r852_update_card_detect(dev);
-	dev->card_unstable = 0;
 
 	/* False alarm */
-	if (dev->card_detected == dev->card_registered)
+	if (present == dev->card_registered)
 		goto exit;
 
 	/* Read media properties */
 	r852_update_media_status(dev);
 
 	/* Register the card */
-	if (dev->card_detected)
+	if (present)
 		r852_register_nand_device(dev);
 	else
 		r852_unregister_nand_device(dev);

---
base-commit: 30daaf3e7897b4a8d9b72e5b0c86dd6e2a4d7d85
change-id: 20261108-submit-r852-card-detect-lock-v1-713bf5cd926b

Best regards,
--  
James Hilliard <james.hilliard1@gmail.com>


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v2] mtd: rawnand: r852: preserve card changes during detection work
  2026-11-08 23:27 [PATCH v2] mtd: rawnand: r852: preserve card changes during detection work James Hilliard
@ 2026-11-08 23:43 ` sashiko-bot
  0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-11-08 23:43 UTC (permalink / raw)
  To: James Hilliard, Miquel Raynal, Richard Weinberger,
	Vignesh Raghavendra, Maxim Levitsky
  Cc: linux-mtd

Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Medium] mtd: rawnand: r852: inconsistent card state in
  r852_update_media_status()
--

commit 047b9555fe843aa22fb04dabbc400ccd2117fd0a
Author: James Hilliard <james.hilliard1@gmail.com>

mtd: rawnand: r852: preserve card changes during detection work

This commit serializes card-detect interrupt mask updates under irqlock
and samples card presence once in r852_card_detect_work() to avoid losing
concurrent card state transitions.

> diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c
> index 92c47d351c278..4c094648673b4 100644
> --- a/drivers/mtd/nand/raw/r852.c
> +++ b/drivers/mtd/nand/raw/r852.c
[ ... ]
> @@ -684,20 +701,20 @@ static void r852_card_detect_work(struct work_struct *work)
>  {
>  	struct r852_device *dev =
>  		container_of(work, struct r852_device, card_detect_work.work);
> +	bool present;
>  
> -	r852_card_update_present(dev);
> +	present = r852_card_update_present(dev);
>  	r852_update_card_detect(dev);
> -	dev->card_unstable = 0;
>  
>  	/* False alarm */
> -	if (dev->card_detected == dev->card_registered)
> +	if (present == dev->card_registered)
>  		goto exit;
>  
>  	/* Read media properties */
>  	r852_update_media_status(dev);
>  
>  	/* Register the card */
> -	if (dev->card_detected)
> +	if (present)
>  		r852_register_nand_device(dev);
>  	else
>  		r852_unregister_nand_device(dev);

[Severity: Medium]
Can r852_update_media_status() observe a different card state than
r852_card_detect_work() when an interrupt fires after
r852_update_card_detect() unmasks card interrupts?

kworker                                   <hardirq>
r852_card_detect_work()
  present = r852_card_update_present(dev)
    /* present == true */
  r852_update_card_detect(dev)
                                          r852_irq()
                                            dev->card_detected = 0
                                            dev->card_unstable = 1
  r852_update_media_status(dev)
    if (!dev->card_detected)
      return;  <-- skips reading media status
  if (present)
    r852_register_nand_device(dev)

Because r852_update_media_status() still checks dev->card_detected while
r852_card_detect_work() branches on present, a removal interrupt during
insertion causes r852_update_media_status() to return early without
updating dev->readonly or dev->sm.  r852_register_nand_device() then runs
with stale media properties, enables the hardware engine via
r852_engine_enable(), and fails in sm_register_device() without disabling
the engine on the error1 path; the subsequent delayed work sees
present == dev->card_registered (0 == 0) and exits early, leaving the
engine enabled with no card present.

Conversely, if an insertion interrupt fires while handling a removal
(present == false), r852_update_media_status() sees dev->card_detected set
and reads R852_CARD_STA and R852_DMA_CAP while dev->card_unstable is set
right before r852_unregister_nand_device() runs.  Passing present to
r852_update_media_status() (or only calling it when present is true) would
keep both steps consistent.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261108-submit-r852-card-detect-lock-v1-v2-1-e3251bc3680a@gmail.com?part=1

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-11-08 23:43 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-08 23:27 [PATCH v2] mtd: rawnand: r852: preserve card changes during detection work James Hilliard
2026-11-08 23:43 ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox