Skip to content

Commit

Permalink
bus: mhi: core: Add support for forced PM resume
Browse files Browse the repository at this point in the history
For whatever reason, some devices like QCA6390, WCN6855 using ath11k
are not in M3 state during PM resume, but still functional. The
mhi_pm_resume should then not fail in those cases, and let the higher
level device specific stack continue resuming process.

Add an API mhi_pm_resume_force(), to force resuming irrespective of the
current MHI state. This fixes a regression with non functional ath11k WiFi
after suspend/resume cycle on some machines.

Bug report: https://bugzilla.kernel.org/show_bug.cgi?id=214179

Link: https://lore.kernel.org/regressions/[email protected]/
Fixes: 020d3b2 ("bus: mhi: Early MHI resume failure in non M3 state")
Cc: [email protected] #5.13
Reported-by: Kalle Valo <[email protected]>
Reported-by: Pengyu Ma <[email protected]>
Tested-by: Kalle Valo <[email protected]>
Acked-by: Kalle Valo <[email protected]>
Signed-off-by: Loic Poulain <[email protected]>
[mani: Switched to API, added bug report, reported-by tags and CCed stable]
Signed-off-by: Manivannan Sadhasivam <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
Loic Poulain authored and gregkh committed Dec 9, 2021
1 parent 7c602f5 commit cab2d3f
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 4 deletions.
21 changes: 18 additions & 3 deletions drivers/bus/mhi/core/pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
static int __mhi_pm_resume(struct mhi_controller *mhi_cntrl, bool force)
{
struct mhi_chan *itr, *tmp;
struct device *dev = &mhi_cntrl->mhi_dev->dev;
Expand All @@ -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) {
Expand Down Expand Up @@ -940,8 +944,19 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl)

return 0;
}

int mhi_pm_resume(struct mhi_controller *mhi_cntrl)
{
return __mhi_pm_resume(mhi_cntrl, false);
}
EXPORT_SYMBOL_GPL(mhi_pm_resume);

int mhi_pm_resume_force(struct mhi_controller *mhi_cntrl)
{
return __mhi_pm_resume(mhi_cntrl, true);
}
EXPORT_SYMBOL_GPL(mhi_pm_resume_force);

int __mhi_device_get_sync(struct mhi_controller *mhi_cntrl)
{
int ret;
Expand Down
6 changes: 5 additions & 1 deletion drivers/net/wireless/ath/ath11k/mhi.c
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,11 @@ 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);
/* Do force MHI resume as some devices like QCA6390, WCN6855
* are not in M3 state but they are functional. So just ignore
* the MHI state while resuming.
*/
ret = mhi_pm_resume_force(ab_pci->mhi_ctrl);
break;
case ATH11K_MHI_TRIGGER_RDDM:
ret = mhi_force_rddm_mode(ab_pci->mhi_ctrl);
Expand Down
13 changes: 13 additions & 0 deletions include/linux/mhi.h
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,19 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl);
*/
int mhi_pm_resume(struct mhi_controller *mhi_cntrl);

/**
* mhi_pm_resume_force - Force resume MHI from suspended state
* @mhi_cntrl: MHI controller
*
* Resume the device irrespective of its MHI state. As per the MHI spec, devices
* has to be in M3 state during resume. But some devices seem to be in a
* different MHI state other than M3 but they continue working fine if allowed.
* This API is intented to be used for such devices.
*
* Return: 0 if the resume succeeds, a negative error code otherwise
*/
int mhi_pm_resume_force(struct mhi_controller *mhi_cntrl);

/**
* mhi_download_rddm_image - Download ramdump image from device for
* debugging purpose.
Expand Down

0 comments on commit cab2d3f

Please sign in to comment.