Merge 4.20-rc4 into usb-next
We want the USB fixes in here as well. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
@@ -325,14 +325,16 @@ static int xhci_histb_remove(struct platform_device *dev)
|
||||
struct xhci_hcd_histb *histb = platform_get_drvdata(dev);
|
||||
struct usb_hcd *hcd = histb->hcd;
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
struct usb_hcd *shared_hcd = xhci->shared_hcd;
|
||||
|
||||
xhci->xhc_state |= XHCI_STATE_REMOVING;
|
||||
|
||||
usb_remove_hcd(xhci->shared_hcd);
|
||||
usb_remove_hcd(shared_hcd);
|
||||
xhci->shared_hcd = NULL;
|
||||
device_wakeup_disable(&dev->dev);
|
||||
|
||||
usb_remove_hcd(hcd);
|
||||
usb_put_hcd(xhci->shared_hcd);
|
||||
usb_put_hcd(shared_hcd);
|
||||
|
||||
xhci_histb_host_disable(histb);
|
||||
usb_put_hcd(hcd);
|
||||
|
@@ -876,7 +876,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
|
||||
status |= USB_PORT_STAT_SUSPEND;
|
||||
}
|
||||
if ((raw_port_status & PORT_PLS_MASK) == XDEV_RESUME &&
|
||||
!DEV_SUPERSPEED_ANY(raw_port_status)) {
|
||||
!DEV_SUPERSPEED_ANY(raw_port_status) && hcd->speed < HCD_USB3) {
|
||||
if ((raw_port_status & PORT_RESET) ||
|
||||
!(raw_port_status & PORT_PE))
|
||||
return 0xffffffff;
|
||||
@@ -921,7 +921,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
|
||||
time_left = wait_for_completion_timeout(
|
||||
&bus_state->rexit_done[wIndex],
|
||||
msecs_to_jiffies(
|
||||
XHCI_MAX_REXIT_TIMEOUT));
|
||||
XHCI_MAX_REXIT_TIMEOUT_MS));
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
|
||||
if (time_left) {
|
||||
@@ -935,7 +935,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
|
||||
} else {
|
||||
int port_status = readl(port->addr);
|
||||
xhci_warn(xhci, "Port resume took longer than %i msec, port status = 0x%x\n",
|
||||
XHCI_MAX_REXIT_TIMEOUT,
|
||||
XHCI_MAX_REXIT_TIMEOUT_MS,
|
||||
port_status);
|
||||
status |= USB_PORT_STAT_SUSPEND;
|
||||
clear_bit(wIndex, &bus_state->rexit_ports);
|
||||
@@ -1474,15 +1474,18 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
|
||||
unsigned long flags;
|
||||
struct xhci_hub *rhub;
|
||||
struct xhci_port **ports;
|
||||
u32 portsc_buf[USB_MAXCHILDREN];
|
||||
bool wake_enabled;
|
||||
|
||||
rhub = xhci_get_rhub(hcd);
|
||||
ports = rhub->ports;
|
||||
max_ports = rhub->num_ports;
|
||||
bus_state = &xhci->bus_state[hcd_index(hcd)];
|
||||
wake_enabled = hcd->self.root_hub->do_remote_wakeup;
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
|
||||
if (hcd->self.root_hub->do_remote_wakeup) {
|
||||
if (wake_enabled) {
|
||||
if (bus_state->resuming_ports || /* USB2 */
|
||||
bus_state->port_remote_wakeup) { /* USB3 */
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
@@ -1490,26 +1493,36 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
|
||||
return -EBUSY;
|
||||
}
|
||||
}
|
||||
|
||||
port_index = max_ports;
|
||||
/*
|
||||
* Prepare ports for suspend, but don't write anything before all ports
|
||||
* are checked and we know bus suspend can proceed
|
||||
*/
|
||||
bus_state->bus_suspended = 0;
|
||||
port_index = max_ports;
|
||||
while (port_index--) {
|
||||
/* suspend the port if the port is not suspended */
|
||||
u32 t1, t2;
|
||||
int slot_id;
|
||||
|
||||
t1 = readl(ports[port_index]->addr);
|
||||
t2 = xhci_port_state_to_neutral(t1);
|
||||
portsc_buf[port_index] = 0;
|
||||
|
||||
if ((t1 & PORT_PE) && !(t1 & PORT_PLS_MASK)) {
|
||||
xhci_dbg(xhci, "port %d not suspended\n", port_index);
|
||||
slot_id = xhci_find_slot_id_by_port(hcd, xhci,
|
||||
port_index + 1);
|
||||
if (slot_id) {
|
||||
/* Bail out if a USB3 port has a new device in link training */
|
||||
if ((t1 & PORT_PLS_MASK) == XDEV_POLLING) {
|
||||
bus_state->bus_suspended = 0;
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
xhci_dbg(xhci, "Bus suspend bailout, port in polling\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
/* suspend ports in U0, or bail out for new connect changes */
|
||||
if ((t1 & PORT_PE) && (t1 & PORT_PLS_MASK) == XDEV_U0) {
|
||||
if ((t1 & PORT_CSC) && wake_enabled) {
|
||||
bus_state->bus_suspended = 0;
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
xhci_stop_device(xhci, slot_id, 1);
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
xhci_dbg(xhci, "Bus suspend bailout, port connect change\n");
|
||||
return -EBUSY;
|
||||
}
|
||||
xhci_dbg(xhci, "port %d not suspended\n", port_index);
|
||||
t2 &= ~PORT_PLS_MASK;
|
||||
t2 |= PORT_LINK_STROBE | XDEV_U3;
|
||||
set_bit(port_index, &bus_state->bus_suspended);
|
||||
@@ -1518,7 +1531,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
|
||||
* including the USB 3.0 roothub, but only if CONFIG_PM
|
||||
* is enabled, so also enable remote wake here.
|
||||
*/
|
||||
if (hcd->self.root_hub->do_remote_wakeup) {
|
||||
if (wake_enabled) {
|
||||
if (t1 & PORT_CONNECT) {
|
||||
t2 |= PORT_WKOC_E | PORT_WKDISC_E;
|
||||
t2 &= ~PORT_WKCONN_E;
|
||||
@@ -1538,7 +1551,26 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
|
||||
|
||||
t1 = xhci_port_state_to_neutral(t1);
|
||||
if (t1 != t2)
|
||||
writel(t2, ports[port_index]->addr);
|
||||
portsc_buf[port_index] = t2;
|
||||
}
|
||||
|
||||
/* write port settings, stopping and suspending ports if needed */
|
||||
port_index = max_ports;
|
||||
while (port_index--) {
|
||||
if (!portsc_buf[port_index])
|
||||
continue;
|
||||
if (test_bit(port_index, &bus_state->bus_suspended)) {
|
||||
int slot_id;
|
||||
|
||||
slot_id = xhci_find_slot_id_by_port(hcd, xhci,
|
||||
port_index + 1);
|
||||
if (slot_id) {
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
xhci_stop_device(xhci, slot_id, 1);
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
}
|
||||
}
|
||||
writel(portsc_buf[port_index], ports[port_index]->addr);
|
||||
}
|
||||
hcd->state = HC_STATE_SUSPENDED;
|
||||
bus_state->next_statechange = jiffies + msecs_to_jiffies(10);
|
||||
|
@@ -590,12 +590,14 @@ static int xhci_mtk_remove(struct platform_device *dev)
|
||||
struct xhci_hcd_mtk *mtk = platform_get_drvdata(dev);
|
||||
struct usb_hcd *hcd = mtk->hcd;
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
struct usb_hcd *shared_hcd = xhci->shared_hcd;
|
||||
|
||||
usb_remove_hcd(xhci->shared_hcd);
|
||||
usb_remove_hcd(shared_hcd);
|
||||
xhci->shared_hcd = NULL;
|
||||
device_init_wakeup(&dev->dev, false);
|
||||
|
||||
usb_remove_hcd(hcd);
|
||||
usb_put_hcd(xhci->shared_hcd);
|
||||
usb_put_hcd(shared_hcd);
|
||||
usb_put_hcd(hcd);
|
||||
xhci_mtk_sch_exit(mtk);
|
||||
xhci_mtk_clks_disable(mtk);
|
||||
|
@@ -248,6 +248,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
|
||||
if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241)
|
||||
xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7;
|
||||
|
||||
if ((pdev->vendor == PCI_VENDOR_ID_BROADCOM ||
|
||||
pdev->vendor == PCI_VENDOR_ID_CAVIUM) &&
|
||||
pdev->device == 0x9026)
|
||||
xhci->quirks |= XHCI_RESET_PLL_ON_DISCONNECT;
|
||||
|
||||
if (xhci->quirks & XHCI_RESET_ON_RESUME)
|
||||
xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
|
||||
"QUIRK: Resetting on resume");
|
||||
@@ -380,6 +385,7 @@ static void xhci_pci_remove(struct pci_dev *dev)
|
||||
if (xhci->shared_hcd) {
|
||||
usb_remove_hcd(xhci->shared_hcd);
|
||||
usb_put_hcd(xhci->shared_hcd);
|
||||
xhci->shared_hcd = NULL;
|
||||
}
|
||||
|
||||
/* Workaround for spurious wakeups at shutdown with HSW */
|
||||
|
@@ -362,14 +362,16 @@ static int xhci_plat_remove(struct platform_device *dev)
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
struct clk *clk = xhci->clk;
|
||||
struct clk *reg_clk = xhci->reg_clk;
|
||||
struct usb_hcd *shared_hcd = xhci->shared_hcd;
|
||||
|
||||
xhci->xhc_state |= XHCI_STATE_REMOVING;
|
||||
|
||||
usb_remove_hcd(xhci->shared_hcd);
|
||||
usb_remove_hcd(shared_hcd);
|
||||
xhci->shared_hcd = NULL;
|
||||
usb_phy_shutdown(hcd->usb_phy);
|
||||
|
||||
usb_remove_hcd(hcd);
|
||||
usb_put_hcd(xhci->shared_hcd);
|
||||
usb_put_hcd(shared_hcd);
|
||||
|
||||
clk_disable_unprepare(clk);
|
||||
clk_disable_unprepare(reg_clk);
|
||||
|
@@ -1521,6 +1521,35 @@ static void handle_device_notification(struct xhci_hcd *xhci,
|
||||
usb_wakeup_notification(udev->parent, udev->portnum);
|
||||
}
|
||||
|
||||
/*
|
||||
* Quirk hanlder for errata seen on Cavium ThunderX2 processor XHCI
|
||||
* Controller.
|
||||
* As per ThunderX2errata-129 USB 2 device may come up as USB 1
|
||||
* If a connection to a USB 1 device is followed by another connection
|
||||
* to a USB 2 device.
|
||||
*
|
||||
* Reset the PHY after the USB device is disconnected if device speed
|
||||
* is less than HCD_USB3.
|
||||
* Retry the reset sequence max of 4 times checking the PLL lock status.
|
||||
*
|
||||
*/
|
||||
static void xhci_cavium_reset_phy_quirk(struct xhci_hcd *xhci)
|
||||
{
|
||||
struct usb_hcd *hcd = xhci_to_hcd(xhci);
|
||||
u32 pll_lock_check;
|
||||
u32 retry_count = 4;
|
||||
|
||||
do {
|
||||
/* Assert PHY reset */
|
||||
writel(0x6F, hcd->regs + 0x1048);
|
||||
udelay(10);
|
||||
/* De-assert the PHY reset */
|
||||
writel(0x7F, hcd->regs + 0x1048);
|
||||
udelay(200);
|
||||
pll_lock_check = readl(hcd->regs + 0x1070);
|
||||
} while (!(pll_lock_check & 0x1) && --retry_count);
|
||||
}
|
||||
|
||||
static void handle_port_status(struct xhci_hcd *xhci,
|
||||
union xhci_trb *event)
|
||||
{
|
||||
@@ -1556,6 +1585,13 @@ static void handle_port_status(struct xhci_hcd *xhci,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* We might get interrupts after shared_hcd is removed */
|
||||
if (port->rhub == &xhci->usb3_rhub && xhci->shared_hcd == NULL) {
|
||||
xhci_dbg(xhci, "ignore port event for removed USB3 hcd\n");
|
||||
bogus_port_status = true;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
hcd = port->rhub->hcd;
|
||||
bus_state = &xhci->bus_state[hcd_index(hcd)];
|
||||
hcd_portnum = port->hcd_portnum;
|
||||
@@ -1639,7 +1675,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
|
||||
* RExit to a disconnect state). If so, let the the driver know it's
|
||||
* out of the RExit state.
|
||||
*/
|
||||
if (!DEV_SUPERSPEED_ANY(portsc) &&
|
||||
if (!DEV_SUPERSPEED_ANY(portsc) && hcd->speed < HCD_USB3 &&
|
||||
test_and_clear_bit(hcd_portnum,
|
||||
&bus_state->rexit_ports)) {
|
||||
complete(&bus_state->rexit_done[hcd_portnum]);
|
||||
@@ -1647,8 +1683,12 @@ static void handle_port_status(struct xhci_hcd *xhci,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (hcd->speed < HCD_USB3)
|
||||
if (hcd->speed < HCD_USB3) {
|
||||
xhci_test_and_clear_bit(xhci, port, PORT_PLC);
|
||||
if ((xhci->quirks & XHCI_RESET_PLL_ON_DISCONNECT) &&
|
||||
(portsc & PORT_CSC) && !(portsc & PORT_CONNECT))
|
||||
xhci_cavium_reset_phy_quirk(xhci);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
/* Update event ring dequeue pointer before dropping the lock */
|
||||
@@ -2266,6 +2306,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
|
||||
goto cleanup;
|
||||
case COMP_RING_UNDERRUN:
|
||||
case COMP_RING_OVERRUN:
|
||||
case COMP_STOPPED_LENGTH_INVALID:
|
||||
goto cleanup;
|
||||
default:
|
||||
xhci_err(xhci, "ERROR Transfer event for unknown stream ring slot %u ep %u\n",
|
||||
|
@@ -1303,6 +1303,7 @@ static int tegra_xusb_remove(struct platform_device *pdev)
|
||||
|
||||
usb_remove_hcd(xhci->shared_hcd);
|
||||
usb_put_hcd(xhci->shared_hcd);
|
||||
xhci->shared_hcd = NULL;
|
||||
usb_remove_hcd(tegra->hcd);
|
||||
usb_put_hcd(tegra->hcd);
|
||||
|
||||
|
@@ -719,8 +719,6 @@ static void xhci_stop(struct usb_hcd *hcd)
|
||||
|
||||
/* Only halt host and free memory after both hcds are removed */
|
||||
if (!usb_hcd_is_primary_hcd(hcd)) {
|
||||
/* usb core will free this hcd shortly, unset pointer */
|
||||
xhci->shared_hcd = NULL;
|
||||
mutex_unlock(&xhci->mutex);
|
||||
return;
|
||||
}
|
||||
|
@@ -1680,7 +1680,7 @@ struct xhci_bus_state {
|
||||
* It can take up to 20 ms to transition from RExit to U0 on the
|
||||
* Intel Lynx Point LP xHCI host.
|
||||
*/
|
||||
#define XHCI_MAX_REXIT_TIMEOUT (20 * 1000)
|
||||
#define XHCI_MAX_REXIT_TIMEOUT_MS 20
|
||||
|
||||
static inline unsigned int hcd_index(struct usb_hcd *hcd)
|
||||
{
|
||||
@@ -1849,6 +1849,7 @@ struct xhci_hcd {
|
||||
#define XHCI_INTEL_USB_ROLE_SW BIT_ULL(31)
|
||||
#define XHCI_ZERO_64B_REGS BIT_ULL(32)
|
||||
#define XHCI_DEFAULT_PM_RUNTIME_ALLOW BIT_ULL(33)
|
||||
#define XHCI_RESET_PLL_ON_DISCONNECT BIT_ULL(34)
|
||||
|
||||
unsigned int num_active_eps;
|
||||
unsigned int limit_active_eps;
|
||||
|
Reference in New Issue
Block a user