ath11k_core_get_rproc() looks up the target remoteproc with rproc_get_by_phandle(), which takes a device reference and a reference on the remoteproc driver's module. The resulting pointer is stored in ab_ahb->tgt_rproc and never released: ath11k_ahb_free_resources() only tears down the firmware resources, and the probe error paths after the lookup jump to err_core_free without dropping the reference either. rproc_shutdown() does not release it, it only drops the power reference. Release the reference when the AHB resources are freed and on the probe error path, so that repeated bind/unbind cycles no longer accumulate remoteproc references and the remoteproc module can be unloaded again. Fixes: ba929d6fe31a ("ath11k: Remove rproc references from common core layer") Cc: stable@vger.kernel.org Assisted-by: DeepSeek-V4.1-Flash and OpenAI Codex Signed-off-by: Wentao Liang --- drivers/net/wireless/ath/ath11k/ahb.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/ahb.c b/drivers/net/wireless/ath/ath11k/ahb.c index 27d01411b6e9..cc93ca22d3ff 100644 --- a/drivers/net/wireless/ath/ath11k/ahb.c +++ b/drivers/net/wireless/ath/ath11k/ahb.c @@ -852,6 +852,16 @@ static int ath11k_core_get_rproc(struct ath11k_base *ab) return 0; } +static void ath11k_core_put_rproc(struct ath11k_base *ab) +{ + struct ath11k_ahb *ab_ahb = ath11k_ahb_priv(ab); + + if (ab_ahb->tgt_rproc) { + rproc_put(ab_ahb->tgt_rproc); + ab_ahb->tgt_rproc = NULL; + } +} + static int ath11k_ahb_setup_msi_resources(struct ath11k_base *ab) { struct platform_device *pdev = ab->pdev; @@ -1262,6 +1272,7 @@ static int ath11k_ahb_probe(struct platform_device *pdev) ath11k_ahb_ce_unmap(ab); err_core_free: + ath11k_core_put_rproc(ab); ath11k_core_free(ab); platform_set_drvdata(pdev, NULL); @@ -1295,6 +1306,7 @@ static void ath11k_ahb_free_resources(struct ath11k_base *ab) ath11k_ce_free_pipes(ab); ath11k_ahb_ce_unmap(ab); + ath11k_core_put_rproc(ab); ath11k_core_free(ab); platform_set_drvdata(pdev, NULL); } -- 2.34.1