From: Sasha Levin <sashal@kernel.org>
To: patches@lists.linux.dev, stable@vger.kernel.org
Cc: Jiawen Liu <1298662399@qq.com>, Mark Brown <broonie@kernel.org>,
Sasha Levin <sashal@kernel.org>,
olteanv@gmail.com, linux-spi@vger.kernel.org,
imx@lists.linux.dev, linux-kernel@vger.kernel.org
Subject: [PATCH AUTOSEL 6.18] spi: fsl-dspi: clean up after failed suspend and resume
Date: Mon, 19 Oct 2026 09:51:57 -0400 [thread overview]
Message-ID: <20261019135441.1420968-426-sashal@kernel.org> (raw)
In-Reply-To: <20261019135441.1420968-1-sashal@kernel.org>
From: Jiawen Liu <1298662399@qq.com>
[ Upstream commit 2543355f3da56a297e3803ccb5d29f4dce5f18f1 ]
dspi_suspend() disabled the IRQ before spi_controller_suspend(),
but ignored a suspend failure and kept tearing the device down.
Restore the IRQ and return the error if suspend fails.
dspi_resume() also left the clock prepared if controller resume or
hardware init failed. Route those failures through clock cleanup.
Signed-off-by: Jiawen Liu <1298662399@qq.com>
Link: https://patch.msgid.link/tencent_427FA55E3D59112524886E9C931CA0F92F06@qq.com
Signed-off-by: Mark Brown <broonie@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
LLM Generated explanations, may be completely bogus:
I compared the pre-image to v6.18.53: the buggy suspend/resume path is
there unchanged, so this is a standalone fix for this tree.
## PHASE 1: COMMIT MESSAGE FORENSICS
**Step 1.1: PARSE THE SUBJECT LINE**
- Record: `[spi: fsl-dspi:] [clean up] [restore IRQ / clocks after
failed suspend and resume]`
- Subsystem is Freescale DSPI. The verb is “clean up”, but the body
describes ignored errors and missing rollback.
**Step 1.2: PARSE ALL COMMIT MESSAGE TAGS**
- Record:
- `Signed-off-by: Jiawen Liu <1298662399@qq.com>` (author)
- `Link: https://patch.msgid.link/tencent_427FA55E3D59112524886E9C931C
A0F92F06@qq.com`
- `Signed-off-by: Mark Brown <broonie@kernel.org>` (SPI maintainer)
- No `Fixes:`, `Reported-by:`, `Tested-by:`, `Reviewed-by:`, `Acked-
by:`, or `Cc: stable` (absence of those last two is expected for
this review)
- Pipeline-added `Signed-off-by: Sasha Levin` / `[ Upstream commit
2543355f3da5... ]` ignored per instructions
**Step 1.3: ANALYZE THE COMMIT BODY TEXT**
- Record: **Bug:** `dspi_suspend()` calls `disable_irq()` then
`spi_controller_suspend()` but ignores a non-zero return and still
disables the clock and selects the sleep pin state. **Symptom:** on a
failed controller suspend the IRQ stays off, clocks are gated, pins go
to sleep, and suspend is reported as success. **Resume bug:**
`clk_prepare_enable()` is not undone if `spi_controller_resume()` or
`dspi_init()` fails. **Root cause:** missing error checks and missing
rollback. No version range in the message.
**Step 1.4: DETECT HIDDEN BUG FIXES**
- Record: Yes. “Clean up” is error-path recovery: re-enable IRQ and
return the error on suspend failure; `clk_disable_unprepare()` on
resume failure. That is a leak/imbalance fix, not style.
## PHASE 2: DIFF ANALYSIS
**Step 2.1: INVENTORY THE CHANGES**
- Record: `drivers/spi/spi-fsl-dspi.c` only; **+18 / −3**. Functions:
`dspi_suspend()`, `dspi_resume()`. Single-file surgical PM error-path
fix.
**Step 2.2: UNDERSTAND THE CODE FLOW CHANGE**
- Record:
- **suspend before:** disable IRQ → ignore `spi_controller_suspend()`
→ always `clk_disable_unprepare()` → sleep pinctrl → return 0.
- **suspend after:** disable IRQ → if `spi_controller_suspend()`
fails, `enable_irq()` and return `ret` (clocks/pinctrl untouched).
- **resume before:** enable clock → ignore `spi_controller_resume()` →
on `dspi_init()` failure return with clock still prepared.
- **resume after:** those failures go to `disable_clk`
(`clk_disable_unprepare()` + return `ret`). IRQ is still enabled
only on the success path.
**Step 2.3: IDENTIFY THE BUG MECHANISM**
- Record: **Error-path / resource-leak / IRQ imbalance.**
`spi_controller_suspend()` can return `-EBUSY` from `spi_stop_queue()`
after a 5s wait (`drivers/spi/spi.c`). Continuing then gates the clock
under a live controller and leaves the IRQ disabled. Resume can leak a
prepared clock.
**Step 2.4: ASSESS THE FIX QUALITY**
- Record: Minimal and obviously correct; matches other SPI drivers that
already check these returns. Regression risk is low: only error paths
change. Idle suspend still returns 0 after stop-queue succeeds. Pre-
existing IRQ-before-stop-queue ordering is not introduced here
(Sashiko noted it as pre-existing). Resume still does not undo
`spi_controller_resume()` on later `dspi_init()` failure;
`dspi_init()` only fails on invalid `trans_mode` after a successful
probe, so that path is essentially dead.
## PHASE 3: GIT HISTORY INVESTIGATION
**Step 3.1: BLAME THE CHANGED LINES**
- Record: On v6.18.53, suspend/resume blame is `c5412ec5f68773`
(“Reinitialize DSPI regs after resuming for S32G”, 2025-05-22), which
kept the ignore-error pattern. That pattern already existed before
S32G (`git show c5412ec5f68773^`). Original driver `349ad66c0ab0b`
(Vybrid VF610) already ignored `spi_master_suspend()` and always
disabled the clock. Bug is old, not post-6.18.
**Step 3.2: FOLLOW THE FIXES: TAG**
- Record: No `Fixes:` tag. Not applicable beyond that.
**Step 3.3: CHECK FILE HISTORY FOR RELATED CHANGES**
- Record: Related: `3d87b613d6a3c` (“Fix external abort on interrupt in
resume or exit paths”) added `disable_irq()` in suspend because a
shared IRQ after clocks-off caused an external abort on Vybrid. That
makes restoring the IRQ on suspend failure required. `9bd77a9ce31dd`
only fixed a NULL drvdata in PM. This patch is standalone; later
autosel `b6d8099e44987` only switches PM macros.
**Step 3.4: CHECK THE AUTHOR'S OTHER COMMITS**
- Record: Jiawen Liu is not the SPI maintainer. Same series on this
tree: `spi: atcspi200`, `spi: bcmbca-hsspi`, `spi: bcm-qspi`, `spi:
bcm63xx-hsspi`, `spi: bcm63xx`, plus `spi: nxp-fspi` probe RPM. Each
driver is independent. Mark Brown applied the series.
**Step 3.5: CHECK FOR DEPENDENT/PREREQUISITE COMMITS**
- Record: No new helpers. Uses `spi_controller_suspend`/`resume`,
`enable_irq`/`disable_irq`, `clk_disable_unprepare` already in 6.18.
Standalone. Series 3/4 does not need 1/4 or 2/4 for this file.
## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH
**Step 4.1: FIND THE ORIGINAL PATCH DISCUSSION**
- Record: `b4 dig -c 2543355f3da5` → https://patch.msgid.link/tencent_42
7FA55E3D59112524886E9C931CA0F92F06@qq.com
- Series: v1 only, `[PATCH 3/4]`. Mark Brown applied all four to
`broonie/spi.git for-7.3`. No NAK on this patch. Sashiko flagged two
**pre-existing** ordering issues (IRQ before stop-queue; resume queue
before `dspi_init()`), not regressions from this diff. No reviewer
`Cc: stable`. Direct lore fetch returned 403; thread recovered via `b4
dig -m`.
**Step 4.2: CHECK WHO REVIEWED THE PATCH**
- Record: `b4 dig -w`: To Mark Brown; Cc linux-spi, linux-kernel, linux-
arm-kernel, imx@, NXP (olteanv, han.xu, haibo.chen). No human
Reviewed-by on this patch. Maintainer applied it.
**Step 4.3: SEARCH FOR THE BUG REPORT**
- Record: No Reported-by / bugzilla / syzbot. Bug is from code
inspection of ignored returns.
**Step 4.4: CHECK FOR RELATED PATCHES AND SERIES**
- Record: 1/4 atcspi200, 2/4 bcmbca-hsspi, 3/4 this, 4/4 nxp-fspi
(different bug: probe RPM). This hunk does not depend on the others.
Frank Li replied only to 4/4.
**Step 4.5: CHECK STABLE MAILING LIST HISTORY**
- Record: lore.kernel.org/stable search via WebFetch returned 403.
UNVERIFIED whether stable@ discussed this SHA. No in-tree evidence it
was rejected.
## PHASE 5: CODE SEMANTIC ANALYSIS
**Step 5.1: IDENTIFY KEY FUNCTIONS**
- Record: `dspi_suspend()`, `dspi_resume()`. Callees of interest:
`spi_controller_suspend()`, `spi_controller_resume()`, `dspi_init()`.
**Step 5.2: TRACE CALLERS**
- Record: Only `SIMPLE_DEV_PM_OPS(dspi_pm, dspi_suspend, dspi_resume)`
on v6.18.53 → system-sleep PM for this platform device. Not a syscall
hot path; triggered by suspend/resume on i.MX / Vybrid / LS1021A / S32
/ ColdFire DSPI.
**Step 5.3: TRACE CALLEES**
- Record: `spi_controller_suspend()` → `spi_stop_queue()` (up to 500 ×
~10ms, then `-EBUSY`) then `__spi_mark_suspended()`.
`dspi_transfer_one_message()` waits on `dspi->xfer_done` when
`dspi->irq` is set; completion is from `dspi_interrupt()`. DMA mode
waits on DMA completions, not that IRQ.
**Step 5.4: FOLLOW THE CALL CHAIN**
- Record: Userspace/system suspend → driver PM → `dspi_suspend()`.
Reachable whenever this hardware is present and `CONFIG_PM_SLEEP`. In-
flight IRQ-mode transfer at suspend can make `spi_stop_queue()` fail;
that is the interesting path.
**Step 5.5: SEARCH FOR SIMILAR PATTERNS**
- Record: Many SPI drivers already check `spi_controller_suspend()`
(omap2-mcspi, atmel, qup, rockchip, stm32, …). Same author fixed the
ignored-return pattern in several Broadcom SPI drivers. Systematic,
not one-off.
## PHASE 6: CROSS-REFERENCING AGAINST THE LOCAL TREE
**Step 6.1: DOES THE BUGGY CODE EXIST IN THIS TREE?**
- Record: Local tree is **6.18.53** (`git describe HEAD` →
`v6.18.53-5049-g0f0bdc2b0dffb`, `VERSION=6 PATCHLEVEL=18
SUBLEVEL=53`). At **v6.18.53**, `dspi_suspend()` still ignores the
suspend return and `dspi_resume()` still returns from `dspi_init()`
failure without `clk_disable_unprepare()`. Candidate `1248ec26ed99f`
is **not** an ancestor of `v6.18.53`. Bug present.
**Step 6.2: CHECK FOR BACKPORT COMPLICATIONS**
- Record: Pre-image on v6.18.53 matches the patch (including `#ifdef
CONFIG_PM_SLEEP` / `SIMPLE_DEV_PM_OPS`). Expected apply: **clean**.
`git apply --check` on current autosel HEAD fails only because the
candidate is already sitting on this working branch.
**Step 6.3: CHECK IF RELATED FIXES ARE ALREADY HERE**
- Record: `3d87b613d6a3c` (IRQ disable in suspend) **is** in v6.18.53.
No other fix for ignored `spi_controller_suspend()` on this file.
## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT
**Step 7.1: IDENTIFY THE SUBSYSTEM AND ITS CRITICALITY**
- Record: `drivers/spi/spi-fsl-dspi.c`. **IMPORTANT** (common
NXP/Freescale SPI; not core mm/vfs). `SPI_FSL_DSPI` depends on
`ARCH_MXC || ARCH_NXP || M5441x || COMPILE_TEST`. Kconfig: S32, VF610,
LS1021A, ColdFire.
**Step 7.2: ASSESS SUBSYSTEM ACTIVITY**
- Record: File still gets platform and DMA work (S32G series in 2025).
PM error handling itself is old and stale.
## PHASE 8: IMPACT AND RISK ASSESSMENT
**Step 8.1: DETERMINE WHO IS AFFECTED**
- Record: Driver-specific: boards with Freescale DSPI that suspend.
Embedded/i.MX/Layerscape/S32 population, not all Linux systems.
**Step 8.2: DETERMINE THE TRIGGER CONDITIONS**
- Record: System suspend while `spi_stop_queue()` cannot drain
(busy/queued messages for ~5s). IRQ-mode in-flight transfer is a
realistic trigger because `disable_irq()` runs first and
`dspi_transfer_one_message()` uses
`wait_for_completion(&dspi->xfer_done)`. Unprivileged users do not
call this directly; a suspend with SPI activity can. Resume clock
leak: `spi_controller_resume()` `-EBUSY` or `dspi_init()` `-EINVAL`
(latter essentially unreachable after probe).
**Step 8.3: DETERMINE THE FAILURE MODE SEVERITY**
- Record: Failed suspend that still gates clocks: possible MMIO abort /
hang (this driver already hit “external abort on non-linefetch” when
the IRQ ran after clocks off — `3d87b613d6a3c`). IRQ left disabled
while the device is still active: SPI completions never fire → hung
transfers. Resume clock leak: extra power / unbalanced clk prepare.
**Severity: HIGH** on the suspend path (hang / abort), **MEDIUM** on
the resume leak.
**Step 8.4: CALCULATE RISK-BENEFIT RATIO**
- Record: **Benefit:** high for DSPI suspend users — fail suspend
instead of disabling clocks/IRQ incorrectly. **Risk:** low — 21 lines,
error paths only, no API/struct change. If stop-queue fails, aborting
suspend is the intended PM policy.
## PHASE 9: FINAL SYNTHESIS
**Step 9.1: COMPILE THE EVIDENCE**
FOR:
- Real ignored-error bug: teardown after failed
`spi_controller_suspend()`.
- IRQ not restored → hung SPI (completion in `dspi_interrupt()`).
- Clock gated while the controller may still be busy → abort/hang; same
class as the already-stable `3d87b613d6a3c` abort fix.
- Resume path clock leak on error.
- Small, local, obviously correct; SPI maintainer applied it.
- Buggy code is in v6.18.53; no extra prerequisites.
- Same class of SPI PM error-path fixes already common in-tree.
AGAINST:
- No user/syzbot report.
- Worded as “clean up”; failure is an error path, not every suspend.
- `dspi_init()` resume failure is almost unreachable.
- Sashiko pre-existing ordering notes (not introduced here).
- Incomplete undo of `spi_controller_resume()` if `dspi_init()` failed
(dead in practice).
UNRESOLVED:
- lore.kernel.org HTTP 403; stable@ discussion not independently fetched
(thread was recovered with b4).
**Step 9.2: APPLY THE STABLE RULES CHECKLIST**
1. Obviously correct and tested? **PASS** — mechanical error-return
handling; applied by Mark Brown.
2. Fixes a real bug that affects users? **PASS** — IRQ/clock teardown on
failed suspend; clk leak on resume.
3. Important issue? **PASS** — hang / possible bus abort, not a style
nit.
4. Small and contained? **PASS** — +18/−3, one file.
5. No new features or APIs? **PASS**.
6. Can apply to the local tree? **PASS** — v6.18.53 pre-image matches.
**Step 9.3: CHECK FOR EXCEPTION CATEGORIES**
- Record: Not a device-ID/quirk/DT/build/doc exception. Qualifies as a
normal bugfix.
**Step 9.4: DECISION**
This should be backported to **this 6.18.53 tree**. The important part
is suspend: do not disable clocks and leave the IRQ off when
`spi_controller_suspend()` fails. That is a real stability bug on a
production NXP SPI controller, small enough for stable, and it applies
cleanly here.
### What the commit solves for stable users
On Freescale DSPI, suspend currently disables the IRQ, then ignores
`spi_controller_suspend()`. If the message queue does not stop
(`-EBUSY`), the driver still turns off the clock and puts pins to sleep
while reporting success. The IRQ stays disabled. That can hang in-flight
transfers (`wait_for_completion` never completes) or MMIO-abort if the
hardware is still live. Resume can also leave `clk_prepare_enable()`
unbalanced. The patch stops teardown on suspend failure and unwinds the
clock on resume failure.
### Risk vs benefit
Benefit is preventing a broken/hung SPI device and possible abort after
a failed controller suspend. Risk is confined to those error returns;
successful idle suspend is unchanged.
### Concerns
No extra commits are required. Do not confuse autosel already having
this SHA with “already selected for 6.18.y”; `v6.18.53` still has the
bug.
Verification:
- [Phase 1] Subject/body/tags from `git log -1` / `git show
1248ec26ed99f`: no Fixes/Reported-by; Link msgid; SOB Jiawen Liu +
Mark Brown
- [Phase 2] Diff: +18/−3 in `dspi_suspend`/`dspi_resume` only
- [Phase 3] `git blame` on v6.18.53: `c5412ec5f68773`; ignore-error PM
since `349ad66c0ab0b`; `3d87b613d6a3c` in this tree
- [Phase 3] `git merge-base --is-ancestor 1248ec26ed99f v6.18.53` → no;
ancestor of HEAD (autosel) → yes
- [Phase 3] Author series: several independent SPI PM error-path patches
- [Phase 4] `b4 dig -c 2543355f3da5`: patch 3/4 v1, lore msgid, applied
to broonie for-7.3; Sashiko pre-existing notes only; no NAK
- [Phase 4] WebFetch lore/stable: 403 — UNVERIFIED stable@ thread
- [Phase 5] `spi_controller_suspend` → `spi_stop_queue` `-EBUSY`; DSPI
IRQ path `wait_for_completion` / `dspi_interrupt`; PM ops only callers
- [Phase 6] `git describe HEAD` / Makefile: 6.18.53; v6.18.53 file
matches patch pre-image
- [Phase 7] `SPI_FSL_DSPI` on ARCH_MXC/NXP
- [Phase 8] Failure: hung SPI / possible external abort; severity HIGH
on suspend error path
**YES**
drivers/spi/spi-fsl-dspi.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/drivers/spi/spi-fsl-dspi.c b/drivers/spi/spi-fsl-dspi.c
index 83ea296597e94..1283a193b6fcc 100644
--- a/drivers/spi/spi-fsl-dspi.c
+++ b/drivers/spi/spi-fsl-dspi.c
@@ -1464,10 +1464,18 @@ static int dspi_init(struct fsl_dspi *dspi)
static int dspi_suspend(struct device *dev)
{
struct fsl_dspi *dspi = dev_get_drvdata(dev);
+ int ret;
if (dspi->irq)
disable_irq(dspi->irq);
- spi_controller_suspend(dspi->ctlr);
+
+ ret = spi_controller_suspend(dspi->ctlr);
+ if (ret) {
+ if (dspi->irq)
+ enable_irq(dspi->irq);
+ return ret;
+ }
+
clk_disable_unprepare(dspi->clk);
pinctrl_pm_select_sleep_state(dev);
@@ -1485,12 +1493,15 @@ static int dspi_resume(struct device *dev)
ret = clk_prepare_enable(dspi->clk);
if (ret)
return ret;
- spi_controller_resume(dspi->ctlr);
+
+ ret = spi_controller_resume(dspi->ctlr);
+ if (ret)
+ goto disable_clk;
ret = dspi_init(dspi);
if (ret) {
dev_err(dev, "failed to initialize dspi during resume\n");
- return ret;
+ goto disable_clk;
}
dspi_set_mtf(dspi);
@@ -1499,6 +1510,10 @@ static int dspi_resume(struct device *dev)
enable_irq(dspi->irq);
return 0;
+
+disable_clk:
+ clk_disable_unprepare(dspi->clk);
+ return ret;
}
#endif /* CONFIG_PM_SLEEP */
--
2.53.0
next prev parent reply other threads:[~2026-10-19 14:04 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20261019135441.1420968-1-sashal@kernel.org>
2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-6.12] spi: nxp-fspi: disable runtime PM on probe failures Sasha Levin
2026-10-19 13:49 ` [PATCH AUTOSEL 6.18-5.10] clk: imx: imx8qxp: add missing MODULE_DEVICE_TABLE() Sasha Levin
2026-10-19 13:51 ` [PATCH AUTOSEL 6.18-5.10] firmware: imx: scu: manage mailbox channels and global handle Sasha Levin
2026-10-19 15:12 ` sashiko-bot
2026-10-19 13:51 ` Sasha Levin [this message]
2026-10-19 15:19 ` [PATCH AUTOSEL 6.18] spi: fsl-dspi: clean up after failed suspend and resume sashiko-bot
2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-5.10] clk: imx: imx8qxp-lpcg: add missing MODULE_DEVICE_TABLE() Sasha Levin
2026-10-19 13:52 ` [PATCH AUTOSEL 6.18-6.12] i2c: imx-lpi2c: properly unwind resources on probe failure Sasha Levin
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=20261019135441.1420968-426-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=1298662399@qq.com \
--cc=broonie@kernel.org \
--cc=imx@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-spi@vger.kernel.org \
--cc=olteanv@gmail.com \
--cc=patches@lists.linux.dev \
--cc=stable@vger.kernel.org \
/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