Commit af080c3fd4ddb9d0ca63664f3f4a9150b17f7256
Committed by
Greg Kroah-Hartman
1 parent
fd5b239cd9
usb: xhci: rework root port wake bits if controller isn't allowed to wakeup
commit a1377e5397ab321e21b793ec8cd2b6f12bd3c718 upstream. When system is being suspended, if host device is not allowed to do wakeup, xhci_suspend() needs to clear all root port wake on bits. Otherwise, some platforms may generate spurious wakeup, even if PCI PME# is disabled. The initial commit ff8cbf250b44 ("xhci: clear root port wake on bits"), which also got into stable, turned out to not work correctly and had to be reverted, and is now rewritten. Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Suggested-by: Alan Stern <stern@rowland.harvard.edu> Acked-by: Alan Stern <stern@rowland.harvard.edu> [Mathias Nyman: reword commit message] Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 4 changed files with 52 additions and 4 deletions Side-by-side Diff
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-plat.c
... | ... | @@ -255,7 +255,15 @@ |
255 | 255 | struct usb_hcd *hcd = dev_get_drvdata(dev); |
256 | 256 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); |
257 | 257 | |
258 | - return xhci_suspend(xhci); | |
258 | + /* | |
259 | + * xhci_suspend() needs `do_wakeup` to know whether host is allowed | |
260 | + * to do wakeup during suspend. Since xhci_plat_suspend is currently | |
261 | + * only designed for system suspend, device_may_wakeup() is enough | |
262 | + * to dertermine whether host is allowed to do wakeup. Need to | |
263 | + * reconsider this when xhci_plat_suspend enlarges its scope, e.g., | |
264 | + * also applies to runtime suspend. | |
265 | + */ | |
266 | + return xhci_suspend(xhci, device_may_wakeup(dev)); | |
259 | 267 | } |
260 | 268 | |
261 | 269 | static int xhci_plat_resume(struct device *dev) |
drivers/usb/host/xhci.c
... | ... | @@ -35,6 +35,8 @@ |
35 | 35 | #define DRIVER_AUTHOR "Sarah Sharp" |
36 | 36 | #define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver" |
37 | 37 | |
38 | +#define PORT_WAKE_BITS (PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E) | |
39 | + | |
38 | 40 | /* Some 0.95 hardware can't handle the chain bit on a Link TRB being cleared */ |
39 | 41 | static int link_quirk; |
40 | 42 | module_param(link_quirk, int, S_IRUGO | S_IWUSR); |
41 | 43 | |
... | ... | @@ -850,13 +852,47 @@ |
850 | 852 | xhci_set_cmd_ring_deq(xhci); |
851 | 853 | } |
852 | 854 | |
855 | +static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci) | |
856 | +{ | |
857 | + int port_index; | |
858 | + __le32 __iomem **port_array; | |
859 | + unsigned long flags; | |
860 | + u32 t1, t2; | |
861 | + | |
862 | + spin_lock_irqsave(&xhci->lock, flags); | |
863 | + | |
864 | + /* disble usb3 ports Wake bits*/ | |
865 | + port_index = xhci->num_usb3_ports; | |
866 | + port_array = xhci->usb3_ports; | |
867 | + while (port_index--) { | |
868 | + t1 = readl(port_array[port_index]); | |
869 | + t1 = xhci_port_state_to_neutral(t1); | |
870 | + t2 = t1 & ~PORT_WAKE_BITS; | |
871 | + if (t1 != t2) | |
872 | + writel(t2, port_array[port_index]); | |
873 | + } | |
874 | + | |
875 | + /* disble usb2 ports Wake bits*/ | |
876 | + port_index = xhci->num_usb2_ports; | |
877 | + port_array = xhci->usb2_ports; | |
878 | + while (port_index--) { | |
879 | + t1 = readl(port_array[port_index]); | |
880 | + t1 = xhci_port_state_to_neutral(t1); | |
881 | + t2 = t1 & ~PORT_WAKE_BITS; | |
882 | + if (t1 != t2) | |
883 | + writel(t2, port_array[port_index]); | |
884 | + } | |
885 | + | |
886 | + spin_unlock_irqrestore(&xhci->lock, flags); | |
887 | +} | |
888 | + | |
853 | 889 | /* |
854 | 890 | * Stop HC (not bus-specific) |
855 | 891 | * |
856 | 892 | * This is called when the machine transition into S3/S4 mode. |
857 | 893 | * |
858 | 894 | */ |
859 | -int xhci_suspend(struct xhci_hcd *xhci) | |
895 | +int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup) | |
860 | 896 | { |
861 | 897 | int rc = 0; |
862 | 898 | unsigned int delay = XHCI_MAX_HALT_USEC; |
... | ... | @@ -866,6 +902,10 @@ |
866 | 902 | if (hcd->state != HC_STATE_SUSPENDED || |
867 | 903 | xhci->shared_hcd->state != HC_STATE_SUSPENDED) |
868 | 904 | return -EINVAL; |
905 | + | |
906 | + /* Clear root port wake on bits if wakeup not allowed. */ | |
907 | + if (!do_wakeup) | |
908 | + xhci_disable_port_wake_on_bits(xhci); | |
869 | 909 | |
870 | 910 | /* Don't poll the roothubs on bus suspend. */ |
871 | 911 | xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); |
drivers/usb/host/xhci.h
... | ... | @@ -1764,7 +1764,7 @@ |
1764 | 1764 | int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks); |
1765 | 1765 | |
1766 | 1766 | #ifdef CONFIG_PM |
1767 | -int xhci_suspend(struct xhci_hcd *xhci); | |
1767 | +int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup); | |
1768 | 1768 | int xhci_resume(struct xhci_hcd *xhci, bool hibernated); |
1769 | 1769 | #else |
1770 | 1770 | #define xhci_suspend NULL |