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); |
