ipa_remove() takes a runtime PM reference before accessing IPA hardware during teardown. If a concurrent modem start or stop keeps ipa_modem_stop() busy across both attempts, the callback intentionally returns without releasing the remaining resources because proceeding with teardown could crash. That return also skips the matching pm_runtime_put_noidle(), leaving the callback's usage-count reference held. Drop only this runtime PM reference before returning. pm_runtime_put_noidle() does not request an idle transition, so the hardware and resources retained on this exceptional path remain untouched while the usage count stays balanced. This issue was found by a static analysis checker and confirmed by manual source review. Fixes: 923a6b698447 ("net: ipa: get clock in ipa_probe()") Assisted-by: unnamed:gpt-5.5 typestate Signed-off-by: Ruoyu Wang Reviewed-by: Alex Elder --- Changes in v2: - Simplify the teardown comment as requested. - Add the Assisted-by tag. v1: https://lore.kernel.org/r/20260814134047.1387177-1-ruoyuw560@gmail.com/ --- drivers/net/ipa/ipa_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c index 788dd99af2a4dc..8d82fd5bb24b97 100644 --- a/drivers/net/ipa/ipa_main.c +++ b/drivers/net/ipa/ipa_main.c @@ -969,12 +969,12 @@ static void ipa_remove(struct platform_device *pdev) } if (ret) { /* - * Not cleaning up here properly might also yield a - * crash later on. As the device is still unregistered - * in this case, this might even yield a crash later on. + * Continuing teardown after failing to stop the modem + * could crash, so leave the remaining resources allocated. */ dev_err(dev, "Failed to stop modem (%pe), leaking resources\n", ERR_PTR(ret)); + pm_runtime_put_noidle(dev); return; } -- 2.51.0