History

bus: mhi: core: Add support for forced PM resume

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

Loic Poulain committed 4 years ago

Commit cab2d3f1 parent 7c602f53 files · +36 −4Browse files

Unified · Split

3 files
  1. drivers/bus/mhi/core/pm.c +18 −3
  2. drivers/net/wireless/ath/ath11k/mhi.c +5 −1
  3. include/linux/mhi.h +13 −0
drivers/bus/mhi/core/pm.c+18−3
@@ -881,7 +881,7 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl) · 880 unmodified lines
881881 }
882882 EXPORT_SYMBOL_GPL(mhi_pm_suspend);
883883
884−int mhi_pm_resume(struct mhi_controller *mhi_cntrl)
884+static int __mhi_pm_resume(struct mhi_controller *mhi_cntrl, bool force)
885885 {
886886 struct mhi_chan *itr, *tmp;
887887 struct device *dev = &mhi_cntrl->mhi_dev->dev;
@@ -898,8 +898,12 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl) · 10 unmodified lines
898898 if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state))
899899 return -EIO;
900900
901− if (mhi_get_mhi_state(mhi_cntrl) != MHI_STATE_M3)
902− return -EINVAL;
901+ if (mhi_get_mhi_state(mhi_cntrl) != MHI_STATE_M3) {
902+ dev_warn(dev, "Resuming from non M3 state (%s)\n",
903+ TO_MHI_STATE_STR(mhi_get_mhi_state(mhi_cntrl)));
904+ if (!force)
905+ return -EINVAL;
906+ }
903907
904908 /* Notify clients about exiting LPM */
905909 list_for_each_entry_safe(itr, tmp, &mhi_cntrl->lpm_chans, node) {
@@ -940,8 +944,19 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl) · 34 unmodified lines
940944
941945 return 0;
942946 }
947+
948+int mhi_pm_resume(struct mhi_controller *mhi_cntrl)
949+{
950+ return __mhi_pm_resume(mhi_cntrl, false);
951+}
943952 EXPORT_SYMBOL_GPL(mhi_pm_resume);
944953
954+int mhi_pm_resume_force(struct mhi_controller *mhi_cntrl)
955+{
956+ return __mhi_pm_resume(mhi_cntrl, true);
957+}
958+EXPORT_SYMBOL_GPL(mhi_pm_resume_force);
959+
945960 int __mhi_device_get_sync(struct mhi_controller *mhi_cntrl)
946961 {
947962 int ret;
drivers/net/wireless/ath/ath11k/mhi.c+5−1
@@ -533,7 +533,11 @@ static int ath11k_mhi_set_state(struct ath11k_pci *ab_pci, · 532 unmodified lines
533533 ret = mhi_pm_suspend(ab_pci->mhi_ctrl);
534534 break;
535535 case ATH11K_MHI_RESUME:
536− ret = mhi_pm_resume(ab_pci->mhi_ctrl);
536+ /* Do force MHI resume as some devices like QCA6390, WCN6855
537+ * are not in M3 state but they are functional. So just ignore
538+ * the MHI state while resuming.
539+ */
540+ ret = mhi_pm_resume_force(ab_pci->mhi_ctrl);
537541 break;
538542 case ATH11K_MHI_TRIGGER_RDDM:
539543 ret = mhi_force_rddm_mode(ab_pci->mhi_ctrl);
include/linux/mhi.h+13−0
@@ -663,6 +663,19 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl); · 662 unmodified lines
663663 */
664664 int mhi_pm_resume(struct mhi_controller *mhi_cntrl);
665665
666+/**
667+ * mhi_pm_resume_force - Force resume MHI from suspended state
668+ * @mhi_cntrl: MHI controller
669+ *
670+ * Resume the device irrespective of its MHI state. As per the MHI spec, devices
671+ * has to be in M3 state during resume. But some devices seem to be in a
672+ * different MHI state other than M3 but they continue working fine if allowed.
673+ * This API is intented to be used for such devices.
674+ *
675+ * Return: 0 if the resume succeeds, a negative error code otherwise
676+ */
677+int mhi_pm_resume_force(struct mhi_controller *mhi_cntrl);
678+
666679 /**
667680 * mhi_download_rddm_image - Download ramdump image from device for
668681 * debugging purpose.