Skip to content

Commit 882fa27

Browse files
Chunfeng Yungregkh
authored andcommitted
usb: xhci-mtk: fix AHB bus hang up caused by roothubs polling
when ip fails to enter sleep mode, register access protection will be disabled, at the same time if all clocks are disabled, access register will hang up AHB bus. the common case causes ip sleep failure is that after all ports enter U3 but before ip enters sleep mode, a port receives a resume signal('K'). this will happens when such as clicks mouse to try to do remote-wakeup to stop system enter suspend. so stop polling root hubs to avoid access xHCI register on bus suspend, and restart it when bus resumes. Signed-off-by: Chunfeng Yun <[email protected]> Signed-off-by: Mathias Nyman <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent b765a16 commit 882fa27

File tree

1 file changed

+23
-0
lines changed

1 file changed

+23
-0
lines changed

drivers/usb/host/xhci-mtk.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,9 +696,24 @@ static int xhci_mtk_remove(struct platform_device *dev)
696696
}
697697

698698
#ifdef CONFIG_PM_SLEEP
699+
/*
700+
* if ip sleep fails, and all clocks are disabled, access register will hang
701+
* AHB bus, so stop polling roothubs to avoid regs access on bus suspend.
702+
* and no need to check whether ip sleep failed or not; this will cause SPM
703+
* to wake up system immediately after system suspend complete if ip sleep
704+
* fails, it is what we wanted.
705+
*/
699706
static int xhci_mtk_suspend(struct device *dev)
700707
{
701708
struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
709+
struct usb_hcd *hcd = mtk->hcd;
710+
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
711+
712+
xhci_dbg(xhci, "%s: stop port polling\n", __func__);
713+
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
714+
del_timer_sync(&hcd->rh_timer);
715+
clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
716+
del_timer_sync(&xhci->shared_hcd->rh_timer);
702717

703718
xhci_mtk_host_disable(mtk);
704719
xhci_mtk_phy_power_off(mtk);
@@ -710,11 +725,19 @@ static int xhci_mtk_suspend(struct device *dev)
710725
static int xhci_mtk_resume(struct device *dev)
711726
{
712727
struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
728+
struct usb_hcd *hcd = mtk->hcd;
729+
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
713730

714731
usb_wakeup_disable(mtk);
715732
xhci_mtk_clks_enable(mtk);
716733
xhci_mtk_phy_power_on(mtk);
717734
xhci_mtk_host_enable(mtk);
735+
736+
xhci_dbg(xhci, "%s: restart port polling\n", __func__);
737+
set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
738+
usb_hcd_poll_rh_status(hcd);
739+
set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
740+
usb_hcd_poll_rh_status(xhci->shared_hcd);
718741
return 0;
719742
}
720743

0 commit comments

Comments
 (0)