[PATCH] mtd: rawnand: r852: lock card-detection interrupt updates
sashiko-bot at kernel.org
sashiko-bot at kernel.org
Sun Nov 8 14:50:33 PST 2026
Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Medium] mtd: rawnand: r852: r852_update_card_detect() still clobbers
unstable state
It also noticed 1 related pre-existing issue this patch does not
introduce:
- [Critical] mtd: rawnand: r852: double unmap in r852_dma_done() [1]
--
commit 8cd576bef40790bcf94d0e276f1f7477d504eeef
Author: James Hilliard <james.hilliard1 at gmail.com>
mtd: rawnand: r852: lock card-detection interrupt updates
This commit takes dev->irqlock in r852_update_card_detect() when updating
R852_CARD_IRQ_ENABLE and clearing dev->card_unstable, and removes the
unlocked assignment to dev->card_unstable in r852_card_detect_work().
> diff --git a/drivers/mtd/nand/raw/r852.c b/drivers/mtd/nand/raw/r852.c
> index 92c47d351c278..3ff4294a80dcd 100644
> --- a/drivers/mtd/nand/raw/r852.c
> +++ b/drivers/mtd/nand/raw/r852.c
> @@ -574,7 +574,11 @@ 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);
> + unsigned long flags;
> + int card_detect_reg;
> +
> + spin_lock_irqsave(&dev->irqlock, flags);
> + card_detect_reg = r852_read_reg(dev, R852_CARD_IRQ_ENABLE);
> dev->card_unstable = 0;
>
> card_detect_reg &= ~(R852_CARD_IRQ_REMOVE | R852_CARD_IRQ_INSERT);
> @@ -584,6 +588,7 @@ 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);
> + spin_unlock_irqrestore(&dev->irqlock, flags);
> }
[Severity: Critical]
This problem wasn't introduced by this patch, but nothing serializes [1]
r852_dma_done() when a DMA timeout in r852_do_dma() races with the completion
interrupt in r852_irq():
drivers/mtd/nand/raw/r852.c:r852_do_dma() {
...
error = r852_dma_wait(dev);
if (error) {
r852_dma_done(dev, error);
return;
}
...
}
drivers/mtd/nand/raw/r852.c:r852_dma_done() {
...
if (dev->phys_dma_addr && dev->phys_dma_addr != dev->phys_bounce_buffer)
dma_unmap_single(&dev->pci_dev->dev, dev->phys_dma_addr,
R852_DMA_LEN,
dev->dma_dir ? DMA_FROM_DEVICE : DMA_TO_DEVICE);
}
CPU0 CPU1
r852_do_dma() r852_irq()
r852_dma_wait(dev)
/* times out */ spin_lock_irqsave(&dev->irqlock, ...)
r852_dma_done(dev, error) r852_dma_done(dev, 0)
if (dev->phys_dma_addr) if (dev->phys_dma_addr)
dma_unmap_single(...) dma_unmap_single(...) <-- double unmap
r852_do_dma() calls r852_dma_done() without holding dev->irqlock, and
r852_dma_done() does not clear dev->phys_dma_addr after unmapping. Can both
paths unmap dev->phys_dma_addr and corrupt DMA API / SWIOTLB state?
[ ... ]
> @@ -687,7 +692,6 @@ static void r852_card_detect_work(struct work_struct *work)
>
> r852_card_update_present(dev);
> r852_update_card_detect(dev);
> - dev->card_unstable = 0;
>
> /* False alarm */
> if (dev->card_detected == dev->card_registered)
[Severity: Medium]
Can the second r852_update_card_detect() call at the end of
r852_card_detect_work() still overwrite dev->card_unstable and re-enable
card-detection interrupts after an interrupt has fired?
drivers/mtd/nand/raw/r852.c:r852_card_detect_work() {
...
r852_card_update_present(dev);
r852_update_card_detect(dev);
/* False alarm */
if (dev->card_detected == dev->card_registered)
goto exit;
/* Read media properties */
r852_update_media_status(dev);
/* Register the card */
if (dev->card_detected)
r852_register_nand_device(dev);
else
r852_unregister_nand_device(dev);
exit:
r852_update_card_detect(dev);
}
kworker <hardirq>
r852_card_detect_work()
r852_update_card_detect(dev)
/* enables card IRQs */
... r852_irq()
r852_disable_irqs(dev)
dev->card_unstable = 1
queue_delayed_work(..., 100ms)
r852_update_card_detect(dev)
dev->card_unstable = 0 <-- clobbers unstable state and re-enables IRQs
The first r852_update_card_detect() call unmasks card interrupts before the
worker registers or unregisters the NAND device. If a card interrupt fires
during that window, r852_irq() masks interrupts, sets dev->card_unstable = 1
and queues card_detect_work for the 100ms debounce delay, only for the exit
call to clear dev->card_unstable and unmask card interrupts while the card is
still settling.
Also, because card interrupts are already unmasked at the first call,
r852_irq() can change dev->card_detected between the unlocked checks
(dev->card_detected == dev->card_registered and if (dev->card_detected)),
which can call r852_register_nand_device() when dev->card_registered is
already set and hit WARN_ON(dev->card_registered).
[1] https://sashiko.dev/#/bug/linux-69af48df-28fa-4234-8f16-07c609427395
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261108-submit-r852-card-detect-lock-v1-v1-1-5514e7543209@gmail.com?part=1
More information about the linux-mtd
mailing list