diff options
Diffstat (limited to 'drivers/usb/host/xhci-hub.c')
-rw-r--r-- | drivers/usb/host/xhci-hub.c | 66 |
1 files changed, 49 insertions, 17 deletions
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 12eea73d9f20..94aca1b5ac8a 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c | |||
@@ -876,7 +876,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, | |||
876 | status |= USB_PORT_STAT_SUSPEND; | 876 | status |= USB_PORT_STAT_SUSPEND; |
877 | } | 877 | } |
878 | if ((raw_port_status & PORT_PLS_MASK) == XDEV_RESUME && | 878 | if ((raw_port_status & PORT_PLS_MASK) == XDEV_RESUME && |
879 | !DEV_SUPERSPEED_ANY(raw_port_status)) { | 879 | !DEV_SUPERSPEED_ANY(raw_port_status) && hcd->speed < HCD_USB3) { |
880 | if ((raw_port_status & PORT_RESET) || | 880 | if ((raw_port_status & PORT_RESET) || |
881 | !(raw_port_status & PORT_PE)) | 881 | !(raw_port_status & PORT_PE)) |
882 | return 0xffffffff; | 882 | return 0xffffffff; |
@@ -921,7 +921,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, | |||
921 | time_left = wait_for_completion_timeout( | 921 | time_left = wait_for_completion_timeout( |
922 | &bus_state->rexit_done[wIndex], | 922 | &bus_state->rexit_done[wIndex], |
923 | msecs_to_jiffies( | 923 | msecs_to_jiffies( |
924 | XHCI_MAX_REXIT_TIMEOUT)); | 924 | XHCI_MAX_REXIT_TIMEOUT_MS)); |
925 | spin_lock_irqsave(&xhci->lock, flags); | 925 | spin_lock_irqsave(&xhci->lock, flags); |
926 | 926 | ||
927 | if (time_left) { | 927 | if (time_left) { |
@@ -935,7 +935,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd, | |||
935 | } else { | 935 | } else { |
936 | int port_status = readl(port->addr); | 936 | int port_status = readl(port->addr); |
937 | xhci_warn(xhci, "Port resume took longer than %i msec, port status = 0x%x\n", | 937 | xhci_warn(xhci, "Port resume took longer than %i msec, port status = 0x%x\n", |
938 | XHCI_MAX_REXIT_TIMEOUT, | 938 | XHCI_MAX_REXIT_TIMEOUT_MS, |
939 | port_status); | 939 | port_status); |
940 | status |= USB_PORT_STAT_SUSPEND; | 940 | status |= USB_PORT_STAT_SUSPEND; |
941 | clear_bit(wIndex, &bus_state->rexit_ports); | 941 | clear_bit(wIndex, &bus_state->rexit_ports); |
@@ -1474,15 +1474,18 @@ int xhci_bus_suspend(struct usb_hcd *hcd) | |||
1474 | unsigned long flags; | 1474 | unsigned long flags; |
1475 | struct xhci_hub *rhub; | 1475 | struct xhci_hub *rhub; |
1476 | struct xhci_port **ports; | 1476 | struct xhci_port **ports; |
1477 | u32 portsc_buf[USB_MAXCHILDREN]; | ||
1478 | bool wake_enabled; | ||
1477 | 1479 | ||
1478 | rhub = xhci_get_rhub(hcd); | 1480 | rhub = xhci_get_rhub(hcd); |
1479 | ports = rhub->ports; | 1481 | ports = rhub->ports; |
1480 | max_ports = rhub->num_ports; | 1482 | max_ports = rhub->num_ports; |
1481 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 1483 | bus_state = &xhci->bus_state[hcd_index(hcd)]; |
1484 | wake_enabled = hcd->self.root_hub->do_remote_wakeup; | ||
1482 | 1485 | ||
1483 | spin_lock_irqsave(&xhci->lock, flags); | 1486 | spin_lock_irqsave(&xhci->lock, flags); |
1484 | 1487 | ||
1485 | if (hcd->self.root_hub->do_remote_wakeup) { | 1488 | if (wake_enabled) { |
1486 | if (bus_state->resuming_ports || /* USB2 */ | 1489 | if (bus_state->resuming_ports || /* USB2 */ |
1487 | bus_state->port_remote_wakeup) { /* USB3 */ | 1490 | bus_state->port_remote_wakeup) { /* USB3 */ |
1488 | spin_unlock_irqrestore(&xhci->lock, flags); | 1491 | spin_unlock_irqrestore(&xhci->lock, flags); |
@@ -1490,26 +1493,36 @@ int xhci_bus_suspend(struct usb_hcd *hcd) | |||
1490 | return -EBUSY; | 1493 | return -EBUSY; |
1491 | } | 1494 | } |
1492 | } | 1495 | } |
1493 | 1496 | /* | |
1494 | port_index = max_ports; | 1497 | * Prepare ports for suspend, but don't write anything before all ports |
1498 | * are checked and we know bus suspend can proceed | ||
1499 | */ | ||
1495 | bus_state->bus_suspended = 0; | 1500 | bus_state->bus_suspended = 0; |
1501 | port_index = max_ports; | ||
1496 | while (port_index--) { | 1502 | while (port_index--) { |
1497 | /* suspend the port if the port is not suspended */ | ||
1498 | u32 t1, t2; | 1503 | u32 t1, t2; |
1499 | int slot_id; | ||
1500 | 1504 | ||
1501 | t1 = readl(ports[port_index]->addr); | 1505 | t1 = readl(ports[port_index]->addr); |
1502 | t2 = xhci_port_state_to_neutral(t1); | 1506 | t2 = xhci_port_state_to_neutral(t1); |
1507 | portsc_buf[port_index] = 0; | ||
1503 | 1508 | ||
1504 | if ((t1 & PORT_PE) && !(t1 & PORT_PLS_MASK)) { | 1509 | /* Bail out if a USB3 port has a new device in link training */ |
1505 | xhci_dbg(xhci, "port %d not suspended\n", port_index); | 1510 | if ((t1 & PORT_PLS_MASK) == XDEV_POLLING) { |
1506 | slot_id = xhci_find_slot_id_by_port(hcd, xhci, | 1511 | bus_state->bus_suspended = 0; |
1507 | port_index + 1); | 1512 | spin_unlock_irqrestore(&xhci->lock, flags); |
1508 | if (slot_id) { | 1513 | xhci_dbg(xhci, "Bus suspend bailout, port in polling\n"); |
1514 | return -EBUSY; | ||
1515 | } | ||
1516 | |||
1517 | /* suspend ports in U0, or bail out for new connect changes */ | ||
1518 | if ((t1 & PORT_PE) && (t1 & PORT_PLS_MASK) == XDEV_U0) { | ||
1519 | if ((t1 & PORT_CSC) && wake_enabled) { | ||
1520 | bus_state->bus_suspended = 0; | ||
1509 | spin_unlock_irqrestore(&xhci->lock, flags); | 1521 | spin_unlock_irqrestore(&xhci->lock, flags); |
1510 | xhci_stop_device(xhci, slot_id, 1); | 1522 | xhci_dbg(xhci, "Bus suspend bailout, port connect change\n"); |
1511 | spin_lock_irqsave(&xhci->lock, flags); | 1523 | return -EBUSY; |
1512 | } | 1524 | } |
1525 | xhci_dbg(xhci, "port %d not suspended\n", port_index); | ||
1513 | t2 &= ~PORT_PLS_MASK; | 1526 | t2 &= ~PORT_PLS_MASK; |
1514 | t2 |= PORT_LINK_STROBE | XDEV_U3; | 1527 | t2 |= PORT_LINK_STROBE | XDEV_U3; |
1515 | set_bit(port_index, &bus_state->bus_suspended); | 1528 | set_bit(port_index, &bus_state->bus_suspended); |
@@ -1518,7 +1531,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd) | |||
1518 | * including the USB 3.0 roothub, but only if CONFIG_PM | 1531 | * including the USB 3.0 roothub, but only if CONFIG_PM |
1519 | * is enabled, so also enable remote wake here. | 1532 | * is enabled, so also enable remote wake here. |
1520 | */ | 1533 | */ |
1521 | if (hcd->self.root_hub->do_remote_wakeup) { | 1534 | if (wake_enabled) { |
1522 | if (t1 & PORT_CONNECT) { | 1535 | if (t1 & PORT_CONNECT) { |
1523 | t2 |= PORT_WKOC_E | PORT_WKDISC_E; | 1536 | t2 |= PORT_WKOC_E | PORT_WKDISC_E; |
1524 | t2 &= ~PORT_WKCONN_E; | 1537 | t2 &= ~PORT_WKCONN_E; |
@@ -1538,7 +1551,26 @@ int xhci_bus_suspend(struct usb_hcd *hcd) | |||
1538 | 1551 | ||
1539 | t1 = xhci_port_state_to_neutral(t1); | 1552 | t1 = xhci_port_state_to_neutral(t1); |
1540 | if (t1 != t2) | 1553 | if (t1 != t2) |
1541 | writel(t2, ports[port_index]->addr); | 1554 | portsc_buf[port_index] = t2; |
1555 | } | ||
1556 | |||
1557 | /* write port settings, stopping and suspending ports if needed */ | ||
1558 | port_index = max_ports; | ||
1559 | while (port_index--) { | ||
1560 | if (!portsc_buf[port_index]) | ||
1561 | continue; | ||
1562 | if (test_bit(port_index, &bus_state->bus_suspended)) { | ||
1563 | int slot_id; | ||
1564 | |||
1565 | slot_id = xhci_find_slot_id_by_port(hcd, xhci, | ||
1566 | port_index + 1); | ||
1567 | if (slot_id) { | ||
1568 | spin_unlock_irqrestore(&xhci->lock, flags); | ||
1569 | xhci_stop_device(xhci, slot_id, 1); | ||
1570 | spin_lock_irqsave(&xhci->lock, flags); | ||
1571 | } | ||
1572 | } | ||
1573 | writel(portsc_buf[port_index], ports[port_index]->addr); | ||
1542 | } | 1574 | } |
1543 | hcd->state = HC_STATE_SUSPENDED; | 1575 | hcd->state = HC_STATE_SUSPENDED; |
1544 | bus_state->next_statechange = jiffies + msecs_to_jiffies(10); | 1576 | bus_state->next_statechange = jiffies + msecs_to_jiffies(10); |