mirror of
https://github.com/torvalds/linux.git
synced 2024-11-15 08:31:55 +00:00
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 <chunfeng.yun@mediatek.com> Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
b765a16a11
commit
882fa27f48
@ -696,9 +696,24 @@ static int xhci_mtk_remove(struct platform_device *dev)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
/*
|
||||
* if ip sleep fails, and all clocks are disabled, access register will hang
|
||||
* AHB bus, so stop polling roothubs to avoid regs access on bus suspend.
|
||||
* and no need to check whether ip sleep failed or not; this will cause SPM
|
||||
* to wake up system immediately after system suspend complete if ip sleep
|
||||
* fails, it is what we wanted.
|
||||
*/
|
||||
static int xhci_mtk_suspend(struct device *dev)
|
||||
{
|
||||
struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
|
||||
struct usb_hcd *hcd = mtk->hcd;
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
|
||||
xhci_dbg(xhci, "%s: stop port polling\n", __func__);
|
||||
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
|
||||
del_timer_sync(&hcd->rh_timer);
|
||||
clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
|
||||
del_timer_sync(&xhci->shared_hcd->rh_timer);
|
||||
|
||||
xhci_mtk_host_disable(mtk);
|
||||
xhci_mtk_phy_power_off(mtk);
|
||||
@ -710,11 +725,19 @@ static int xhci_mtk_suspend(struct device *dev)
|
||||
static int xhci_mtk_resume(struct device *dev)
|
||||
{
|
||||
struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
|
||||
struct usb_hcd *hcd = mtk->hcd;
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
|
||||
usb_wakeup_disable(mtk);
|
||||
xhci_mtk_clks_enable(mtk);
|
||||
xhci_mtk_phy_power_on(mtk);
|
||||
xhci_mtk_host_enable(mtk);
|
||||
|
||||
xhci_dbg(xhci, "%s: restart port polling\n", __func__);
|
||||
set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
|
||||
usb_hcd_poll_rh_status(hcd);
|
||||
set_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
|
||||
usb_hcd_poll_rh_status(xhci->shared_hcd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user