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
Unified · Split
| @@ -881,7 +881,7 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl) · 880 unmodified lines | |||
| 881 | } | 881 | } |
| 882 | EXPORT_SYMBOL_GPL(mhi_pm_suspend); | 882 | EXPORT_SYMBOL_GPL(mhi_pm_suspend); |
| 883 | 883 | ||
| 884 | int mhi_pm_resume(struct mhi_controller *mhi_cntrl) | 884 | static int __mhi_pm_resume(struct mhi_controller *mhi_cntrl, bool force) |
| 885 | { | 885 | { |
| 886 | struct mhi_chan *itr, *tmp; | 886 | struct mhi_chan *itr, *tmp; |
| 887 | struct device *dev = &mhi_cntrl->mhi_dev->dev; | 887 | struct device *dev = &mhi_cntrl->mhi_dev->dev; |
| @@ -898,8 +898,12 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl) · 10 unmodified lines | |||
| 898 | if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) | 898 | if (MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state)) |
| 899 | return -EIO; | 899 | return -EIO; |
| 900 | 900 | ||
| 901 | if (mhi_get_mhi_state(mhi_cntrl) != MHI_STATE_M3) | 901 | if (mhi_get_mhi_state(mhi_cntrl) != MHI_STATE_M3) { |
| 902 | return -EINVAL; | 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 | } | ||
| 903 | 907 | ||
| 904 | /* Notify clients about exiting LPM */ | 908 | /* Notify clients about exiting LPM */ |
| 905 | list_for_each_entry_safe(itr, tmp, &mhi_cntrl->lpm_chans, node) { | 909 | 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 | |||
| 940 | 944 | ||
| 941 | return 0; | 945 | return 0; |
| 942 | } | 946 | } |
| 947 | |||
| 948 | int mhi_pm_resume(struct mhi_controller *mhi_cntrl) | ||
| 949 | { | ||
| 950 | return __mhi_pm_resume(mhi_cntrl, false); | ||
| 951 | } | ||
| 943 | EXPORT_SYMBOL_GPL(mhi_pm_resume); | 952 | EXPORT_SYMBOL_GPL(mhi_pm_resume); |
| 944 | 953 | ||
| 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 | |||
| 945 | int __mhi_device_get_sync(struct mhi_controller *mhi_cntrl) | 960 | int __mhi_device_get_sync(struct mhi_controller *mhi_cntrl) |
| 946 | { | 961 | { |
| 947 | int ret; | 962 | int ret; |
| @@ -533,7 +533,11 @@ static int ath11k_mhi_set_state(struct ath11k_pci *ab_pci, · 532 unmodified lines | |||
| 533 | ret = mhi_pm_suspend(ab_pci->mhi_ctrl); | 533 | ret = mhi_pm_suspend(ab_pci->mhi_ctrl); |
| 534 | break; | 534 | break; |
| 535 | case ATH11K_MHI_RESUME: | 535 | 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); | ||
| 537 | break; | 541 | break; |
| 538 | case ATH11K_MHI_TRIGGER_RDDM: | 542 | case ATH11K_MHI_TRIGGER_RDDM: |
| 539 | ret = mhi_force_rddm_mode(ab_pci->mhi_ctrl); | 543 | ret = mhi_force_rddm_mode(ab_pci->mhi_ctrl); |
| @@ -663,6 +663,19 @@ int mhi_pm_suspend(struct mhi_controller *mhi_cntrl); · 662 unmodified lines | |||
| 663 | */ | 663 | */ |
| 664 | int mhi_pm_resume(struct mhi_controller *mhi_cntrl); | 664 | int mhi_pm_resume(struct mhi_controller *mhi_cntrl); |
| 665 | 665 | ||
| 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 | |||
| 666 | /** | 679 | /** |
| 667 | * mhi_download_rddm_image - Download ramdump image from device for | 680 | * mhi_download_rddm_image - Download ramdump image from device for |
| 668 | * debugging purpose. | 681 | * debugging purpose. |