From 697cf90155d78225d967836dcdb2291468c3e60d Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Fri, 24 Sep 2021 11:14:03 +0200 Subject: [PATCH] bus: mhi: Add support for forced resume For whatever reason, some devices like ath11k are not in M3 state when resuming, but still functional. The mhi_pm_resume should then not fail in that case, and let the higher level device specific stack continue resuming process. Add a new parameter to mhi_pm_resume, to try resuming, whatever the current MHI state is. This fixes a regression with non functional ath11k WiFi after suspend/resume cycle on some machines. Fixes: 020d3b26c07a ("bus: mhi: Early MHI resume failure in non M3 state") Signed-off-by: Loic Poulain --- drivers/bus/mhi/core/pm.c | 10 +++++++--- drivers/bus/mhi/pci_generic.c | 2 +- drivers/net/wireless/ath/ath11k/mhi.c | 2 +- include/linux/mhi.h | 3 ++- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c index bbf6cd0..ef0e698 100644 --- a/drivers/bus/mhi/core/pm.c +++ b/drivers/bus/mhi/core/pm.c @@ -881,7 +881,7 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl) } EXPORT_SYMBOL_GPL(mhi_pm_suspend); -int mhi_pm_resume(struct mhi_controller *mhi_cntrl) +int mhi_pm_resume(struct mhi_controller *mhi_cntrl, bool force) { struct mhi_chan *itr, *tmp; struct device *dev = &mhi_cntrl->mhi_dev->dev; @@ -898,8 +898,12 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl) if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) return -EIO; - if (mhi_get_mhi_state(mhi_cntrl) != MHI_STATE_M3) - return -EINVAL; + if (mhi_get_mhi_state(mhi_cntrl) != MHI_STATE_M3) { + dev_warn(dev, "Resuming from non M3 state (%s)\n", + TO_MHI_STATE_STR(mhi_get_mhi_state(mhi_cntrl))); + if (!force) + return -EINVAL; + } /* Notify clients about exiting LPM */ list_for_each_entry_safe(itr, tmp, &mhi_cntrl->lpm_chans, node) { diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c index b33b9d7..dba4b7d 100644 --- a/drivers/bus/mhi/pci_generic.c +++ b/drivers/bus/mhi/pci_generic.c @@ -924,7 +924,7 @@ static int __maybe_unused mhi_pci_runtime_resume(struct device *dev) return 0; /* Nothing to do at MHI level */ /* Exit M3, transition to M0 state */ - err = mhi_pm_resume(mhi_cntrl); + err = mhi_pm_resume(mhi_cntrl, false); if (err) { dev_err(&pdev->dev, "failed to resume device: %d\n", err); goto err_recovery; diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c index 75cc2d8..f913439 100644 --- a/drivers/net/wireless/ath/ath11k/mhi.c +++ b/drivers/net/wireless/ath/ath11k/mhi.c @@ -532,7 +532,7 @@ static int ath11k_mhi_set_state(struct ath11k_pci *ab_pci, ret = mhi_pm_suspend(ab_pci->mhi_ctrl); break; case ATH11K_MHI_RESUME: - ret = mhi_pm_resume(ab_pci->mhi_ctrl); + ret = mhi_pm_resume(ab_pci->mhi_ctrl, true); break; case ATH11K_MHI_TRIGGER_RDDM: ret = mhi_force_rddm_mode(ab_pci->mhi_ctrl); diff --git a/include/linux/mhi.h b/include/linux/mhi.h index c493a80..f73b270 100644 --- a/include/linux/mhi.h +++ b/include/linux/mhi.h @@ -658,8 +658,9 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl); /** * mhi_pm_resume - Resume MHI from suspended state * @mhi_cntrl: MHI controller + * @force: Force resuming to M0, whatever the current state */ -int mhi_pm_resume(struct mhi_controller *mhi_cntrl); +int mhi_pm_resume(struct mhi_controller *mhi_cntrl, bool force); /** * mhi_download_rddm_image - Download ramdump image from device for -- 2.7.4