|
@@ -35,6 +35,8 @@
|
|
#define DRIVER_AUTHOR "Sarah Sharp"
|
|
#define DRIVER_AUTHOR "Sarah Sharp"
|
|
#define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver"
|
|
#define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver"
|
|
|
|
|
|
|
|
+#define PORT_WAKE_BITS (PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E)
|
|
|
|
+
|
|
/* Some 0.95 hardware can't handle the chain bit on a Link TRB being cleared */
|
|
/* Some 0.95 hardware can't handle the chain bit on a Link TRB being cleared */
|
|
static int link_quirk;
|
|
static int link_quirk;
|
|
module_param(link_quirk, int, S_IRUGO | S_IWUSR);
|
|
module_param(link_quirk, int, S_IRUGO | S_IWUSR);
|
|
@@ -851,13 +853,47 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
|
|
xhci_set_cmd_ring_deq(xhci);
|
|
xhci_set_cmd_ring_deq(xhci);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void xhci_disable_port_wake_on_bits(struct xhci_hcd *xhci)
|
|
|
|
+{
|
|
|
|
+ int port_index;
|
|
|
|
+ __le32 __iomem **port_array;
|
|
|
|
+ unsigned long flags;
|
|
|
|
+ u32 t1, t2;
|
|
|
|
+
|
|
|
|
+ spin_lock_irqsave(&xhci->lock, flags);
|
|
|
|
+
|
|
|
|
+ /* disble usb3 ports Wake bits*/
|
|
|
|
+ port_index = xhci->num_usb3_ports;
|
|
|
|
+ port_array = xhci->usb3_ports;
|
|
|
|
+ while (port_index--) {
|
|
|
|
+ t1 = readl(port_array[port_index]);
|
|
|
|
+ t1 = xhci_port_state_to_neutral(t1);
|
|
|
|
+ t2 = t1 & ~PORT_WAKE_BITS;
|
|
|
|
+ if (t1 != t2)
|
|
|
|
+ writel(t2, port_array[port_index]);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* disble usb2 ports Wake bits*/
|
|
|
|
+ port_index = xhci->num_usb2_ports;
|
|
|
|
+ port_array = xhci->usb2_ports;
|
|
|
|
+ while (port_index--) {
|
|
|
|
+ t1 = readl(port_array[port_index]);
|
|
|
|
+ t1 = xhci_port_state_to_neutral(t1);
|
|
|
|
+ t2 = t1 & ~PORT_WAKE_BITS;
|
|
|
|
+ if (t1 != t2)
|
|
|
|
+ writel(t2, port_array[port_index]);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ spin_unlock_irqrestore(&xhci->lock, flags);
|
|
|
|
+}
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Stop HC (not bus-specific)
|
|
* Stop HC (not bus-specific)
|
|
*
|
|
*
|
|
* This is called when the machine transition into S3/S4 mode.
|
|
* This is called when the machine transition into S3/S4 mode.
|
|
*
|
|
*
|
|
*/
|
|
*/
|
|
-int xhci_suspend(struct xhci_hcd *xhci)
|
|
|
|
|
|
+int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
|
|
{
|
|
{
|
|
int rc = 0;
|
|
int rc = 0;
|
|
unsigned int delay = XHCI_MAX_HALT_USEC;
|
|
unsigned int delay = XHCI_MAX_HALT_USEC;
|
|
@@ -868,6 +904,10 @@ int xhci_suspend(struct xhci_hcd *xhci)
|
|
xhci->shared_hcd->state != HC_STATE_SUSPENDED)
|
|
xhci->shared_hcd->state != HC_STATE_SUSPENDED)
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
+ /* Clear root port wake on bits if wakeup not allowed. */
|
|
|
|
+ if (!do_wakeup)
|
|
|
|
+ xhci_disable_port_wake_on_bits(xhci);
|
|
|
|
+
|
|
/* Don't poll the roothubs on bus suspend. */
|
|
/* Don't poll the roothubs on bus suspend. */
|
|
xhci_dbg(xhci, "%s: stopping port polling.\n", __func__);
|
|
xhci_dbg(xhci, "%s: stopping port polling.\n", __func__);
|
|
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
|
|
clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
|