From: Johan Hovold johan+linaro@kernel.org
stable inclusion from stable-v5.10.142 commit 8984ca41de168a14df8af8d09e6688e03252dcb6 category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I6CSFH
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
commit d2ac7bef95c9ead307801ccb6cb6dfbeb14247bf upstream.
Generic PHYs must be powered-off before they can be tore down.
Similarly, suspending legacy PHYs after having powered them off makes no sense.
Fix the dwc3_core_exit() (e.g. called during suspend) and open-coded dwc3_probe() error-path sequences that got this wrong.
Note that this makes dwc3_core_exit() match the dwc3_core_init() error path with respect to powering off the PHYs.
Fixes: 03c1fd622f72 ("usb: dwc3: core: add phy cleanup for probe error handling") Fixes: c499ff71ff2a ("usb: dwc3: core: re-factor init and exit paths") Cc: stable@vger.kernel.org # 4.8 Reviewed-by: Andrew Halaney ahalaney@redhat.com Reviewed-by: Matthias Kaehlcke mka@chromium.org Reviewed-by: Manivannan Sadhasivam manivannan.sadhasivam@linaro.org Signed-off-by: Johan Hovold johan+linaro@kernel.org Link: https://lore.kernel.org/r/20220804151001.23612-2-johan+linaro@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org [ johan: adjust context to 5.15 ] Signed-off-by: Johan Hovold johan+linaro@kernel.org Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Signed-off-by: Jialin Zhang zhangjialin11@huawei.com Reviewed-by: Zheng Zengkai zhengzengkai@huawei.com --- drivers/usb/dwc3/core.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 572cf34459aa..5aae7504f78a 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -728,15 +728,16 @@ static void dwc3_core_exit(struct dwc3 *dwc) { dwc3_event_buffers_cleanup(dwc);
+ usb_phy_set_suspend(dwc->usb2_phy, 1); + usb_phy_set_suspend(dwc->usb3_phy, 1); + phy_power_off(dwc->usb2_generic_phy); + phy_power_off(dwc->usb3_generic_phy); + usb_phy_shutdown(dwc->usb2_phy); usb_phy_shutdown(dwc->usb3_phy); phy_exit(dwc->usb2_generic_phy); phy_exit(dwc->usb3_generic_phy);
- usb_phy_set_suspend(dwc->usb2_phy, 1); - usb_phy_set_suspend(dwc->usb3_phy, 1); - phy_power_off(dwc->usb2_generic_phy); - phy_power_off(dwc->usb3_generic_phy); clk_bulk_disable_unprepare(dwc->num_clks, dwc->clks); reset_control_assert(dwc->reset); } @@ -1606,16 +1607,16 @@ static int dwc3_probe(struct platform_device *pdev) dwc3_debugfs_exit(dwc); dwc3_event_buffers_cleanup(dwc);
- usb_phy_shutdown(dwc->usb2_phy); - usb_phy_shutdown(dwc->usb3_phy); - phy_exit(dwc->usb2_generic_phy); - phy_exit(dwc->usb3_generic_phy); - usb_phy_set_suspend(dwc->usb2_phy, 1); usb_phy_set_suspend(dwc->usb3_phy, 1); phy_power_off(dwc->usb2_generic_phy); phy_power_off(dwc->usb3_generic_phy);
+ usb_phy_shutdown(dwc->usb2_phy); + usb_phy_shutdown(dwc->usb3_phy); + phy_exit(dwc->usb2_generic_phy); + phy_exit(dwc->usb3_generic_phy); + dwc3_ulpi_exit(dwc);
err4: