From: Mateusz Litwin mateusz.litwin@nokia.com
[ Upstream commit d67396c9d697041b385d70ff2fd59cb07ae167e8 ]
A race condition exists between the read loop and IRQ `complete()` call. An interrupt could call the complete() between the inner loop and reinit_completion(), potentially losing the completion event and causing an unnecessary timeout. Moving reinit_completion() before the loop prevents this. A premature signal will only result in a spurious wakeup and another wait cycle, which is preferable to waiting for a timeout.
Signed-off-by: Mateusz Litwin mateusz.litwin@nokia.com Link: https://patch.msgid.link/20251218-cqspi_indirect_read_improve-v2-1-396079972... Signed-off-by: Mark Brown broonie@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
### Summary
**Pros for backporting:** 1. ✅ Fixes a genuine race condition causing timeouts 2. ✅ Small, surgical fix (< 10 lines changed) 3. ✅ Logic is obviously correct and well-explained 4. ✅ Low risk - worst case is benign spurious wakeup 5. ✅ Reviewed by subsystem maintainer (Mark Brown) 6. ✅ No dependencies on other commits 7. ✅ Driver has been in the kernel since 2020, exists in all active stable trees 8. ✅ From a reputable source (Nokia) dealing with real hardware
**Cons:** - None significant. The absence of explicit Fixes:/Cc: stable tags is expected for commits under manual review.
### Risk vs Benefit
- **Risk**: Very low - the change is simple, localized, and mathematically correct - **Benefit**: Prevents user-visible timeouts during SPI read operations on affected hardware
This commit is an excellent candidate for stable backporting. It fixes a real race condition bug with a small, obvious, and low-risk change. The fix has been reviewed by the SPI maintainer and addresses real hardware issues without introducing new features or significant complexity.
**YES**
drivers/spi/spi-cadence-quadspi.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c index af6d050da1c8..695dbf7142d1 100644 --- a/drivers/spi/spi-cadence-quadspi.c +++ b/drivers/spi/spi-cadence-quadspi.c @@ -769,6 +769,7 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata, readl(reg_base + CQSPI_REG_INDIRECTRD); /* Flush posted write. */
while (remaining > 0) { + ret = 0; if (use_irq && !wait_for_completion_timeout(&cqspi->transfer_complete, msecs_to_jiffies(CQSPI_READ_TIMEOUT_MS))) @@ -781,6 +782,14 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata, if (cqspi->slow_sram) writel(0x0, reg_base + CQSPI_REG_IRQMASK);
+ /* + * Prevent lost interrupt and race condition by reinitializing early. + * A spurious wakeup and another wait cycle can occur here, + * which is preferable to waiting until timeout if interrupt is lost. + */ + if (use_irq) + reinit_completion(&cqspi->transfer_complete); + bytes_to_read = cqspi_get_rd_sram_level(cqspi);
if (ret && bytes_to_read == 0) { @@ -813,7 +822,6 @@ static int cqspi_indirect_read_execute(struct cqspi_flash_pdata *f_pdata, }
if (use_irq && remaining > 0) { - reinit_completion(&cqspi->transfer_complete); if (cqspi->slow_sram) writel(CQSPI_REG_IRQ_WATERMARK, reg_base + CQSPI_REG_IRQMASK); }