[PATCH 1/8] xhci: remove the unused sw_lpm_support

2018-12-07 Thread Mathias Nyman
From: Zeng Tao 

It is introduced for the pre-0.96 xHC controllers, and the driver only
support HW LPM for 1.0 and later controllers.It's not actually used now
and is thought not to be used in the future any more, so just remove it.

Signed-off-by: Zeng Tao 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-mem.c | 20 
 drivers/usb/host/xhci.c |  3 +--
 drivers/usb/host/xhci.h |  2 --
 3 files changed, 5 insertions(+), 20 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index b1f27aa..791c5d8 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2181,23 +2181,11 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, 
unsigned int num_ports,
if (major_revision < 0x03 && xhci->num_ext_caps < max_caps)
xhci->ext_caps[xhci->num_ext_caps++] = temp;
 
-   /* Check the host's USB2 LPM capability */
-   if ((xhci->hci_version == 0x96) && (major_revision != 0x03) &&
-   (temp & XHCI_L1C)) {
+   if ((xhci->hci_version >= 0x100) && (major_revision != 0x03) &&
+(temp & XHCI_HLC)) {
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-   "xHCI 0.96: support USB2 software lpm");
-   xhci->sw_lpm_support = 1;
-   }
-
-   if ((xhci->hci_version >= 0x100) && (major_revision != 0x03)) {
-   xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-   "xHCI 1.0: support USB2 software lpm");
-   xhci->sw_lpm_support = 1;
-   if (temp & XHCI_HLC) {
-   xhci_dbg_trace(xhci, trace_xhci_dbg_init,
-   "xHCI 1.0: support USB2 hardware lpm");
-   xhci->hw_lpm_support = 1;
-   }
+  "xHCI 1.0: support USB2 hardware lpm");
+   xhci->hw_lpm_support = 1;
}
 
port_offset--;
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index c928dbb..553e974 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -4370,8 +4370,7 @@ static int xhci_update_device(struct usb_hcd *hcd, struct 
usb_device *udev)
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
int portnum = udev->portnum - 1;
 
-   if (hcd->speed >= HCD_USB3 || !xhci->sw_lpm_support ||
-   !udev->lpm_capable)
+   if (hcd->speed >= HCD_USB3 || !udev->lpm_capable)
return 0;
 
/* we only support lpm for non-hub device connected to root hub yet */
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 260b259..59b8562 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1858,8 +1858,6 @@ struct xhci_hcd {
struct xhci_port*hw_ports;
struct xhci_hub usb2_rhub;
struct xhci_hub usb3_rhub;
-   /* support xHCI 0.96 spec USB2 software LPM */
-   unsignedsw_lpm_support:1;
/* support xHCI 1.0 spec USB2 hardware LPM */
unsignedhw_lpm_support:1;
/* cached usb2 extened protocol capabilites */
-- 
2.7.4



[PATCH 4/8] xhci: move usb3 speficic bits to own function in get_port_status call

2018-12-07 Thread Mathias Nyman
refactoring, no functional changes

Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-hub.c | 68 ++---
 1 file changed, 40 insertions(+), 28 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 5dba0a4..60aeff3 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -818,6 +818,41 @@ static u32 xhci_get_ext_port_status(u32 raw_port_status, 
u32 port_li)
return ext_stat;
 }
 
+static void xhci_get_usb3_port_status(struct xhci_port *port, u32 *status,
+ u32 portsc)
+{
+   struct xhci_hcd *xhci;
+   u32 link_state;
+   u32 portnum;
+
+   xhci = hcd_to_xhci(port->rhub->hcd);
+   link_state = portsc & PORT_PLS_MASK;
+   portnum = port->hcd_portnum;
+
+   /* USB3 specific wPortChange bits
+*
+* Port link change with port in resume state should not be
+* reported to usbcore, as this is an internal state to be
+* handled by xhci driver. Reporting PLC to usbcore may
+* cause usbcore clearing PLC first and port change event
+* irq won't be generated.
+*/
+
+   if (portsc & PORT_PLC && (link_state != XDEV_RESUME))
+   *status |= USB_PORT_STAT_C_LINK_STATE << 16;
+   if (portsc & PORT_WRC)
+   *status |= USB_PORT_STAT_C_BH_RESET << 16;
+   if (portsc & PORT_CEC)
+   *status |= USB_PORT_STAT_C_CONFIG_ERROR << 16;
+
+   /* USB3 specific wPortStatus bits */
+   if (portsc & PORT_POWER)
+   *status |= USB_SS_PORT_STAT_POWER;
+
+   xhci_hub_report_usb3_link_state(xhci, status, portsc);
+   xhci_del_comp_mod_timer(xhci, portsc, portnum);
+}
+
 /*
  * Converts a raw xHCI port status into the format that external USB 2.0 or USB
  * 3.0 hubs use.
@@ -854,22 +889,8 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
if ((raw_port_status & PORT_RC))
status |= USB_PORT_STAT_C_RESET << 16;
/* USB3.0 only */
-   if (hcd->speed >= HCD_USB3) {
-   /* Port link change with port in resume state should not be
-* reported to usbcore, as this is an internal state to be
-* handled by xhci driver. Reporting PLC to usbcore may
-* cause usbcore clearing PLC first and port change event
-* irq won't be generated.
-*/
-   if ((raw_port_status & PORT_PLC) &&
-   (raw_port_status & PORT_PLS_MASK) != XDEV_RESUME)
-   status |= USB_PORT_STAT_C_LINK_STATE << 16;
-   if ((raw_port_status & PORT_WRC))
-   status |= USB_PORT_STAT_C_BH_RESET << 16;
-   if ((raw_port_status & PORT_CEC))
-   status |= USB_PORT_STAT_C_CONFIG_ERROR << 16;
-   }
-
+   if (hcd->speed >= HCD_USB3)
+   xhci_get_usb3_port_status(port, , raw_port_status);
if (hcd->speed < HCD_USB3) {
if ((raw_port_status & PORT_PLS_MASK) == XDEV_U3
&& (raw_port_status & PORT_POWER))
@@ -989,22 +1010,13 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
if (raw_port_status & PORT_RESET)
status |= USB_PORT_STAT_RESET;
if (raw_port_status & PORT_POWER) {
-   if (hcd->speed >= HCD_USB3)
-   status |= USB_SS_PORT_STAT_POWER;
-   else
+   if (hcd->speed < HCD_USB3)
status |= USB_PORT_STAT_POWER;
}
/* Update Port Link State */
-   if (hcd->speed >= HCD_USB3) {
-   xhci_hub_report_usb3_link_state(xhci, , raw_port_status);
-   /*
-* Verify if all USB3 Ports Have entered U0 already.
-* Delete Compliance Mode Timer if so.
-*/
-   xhci_del_comp_mod_timer(xhci, raw_port_status, wIndex);
-   } else {
+   if (hcd->speed < HCD_USB3)
xhci_hub_report_usb2_link_state(, raw_port_status);
-   }
+
if (bus_state->port_c_suspend & (1 << wIndex))
status |= USB_PORT_STAT_C_SUSPEND << 16;
 
-- 
2.7.4



[PATCH 6/8] xhci: cleanup code that sets portstatus and portchange bits

2018-12-07 Thread Mathias Nyman
Group the code where the wPortstatus and wPortChange bits
are set into one place.

No functional changes

Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-hub.c | 26 ++
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 5af4f90..c0de2d0 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -891,7 +891,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
rhub = xhci_get_rhub(hcd);
port = rhub->ports[wIndex];
 
-   /* wPortChange bits */
+   /* common wPortChange bits */
if (raw_port_status & PORT_CSC)
status |= USB_PORT_STAT_C_CONNECTION << 16;
if (raw_port_status & PORT_PEC)
@@ -901,7 +901,19 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
if ((raw_port_status & PORT_RC))
status |= USB_PORT_STAT_C_RESET << 16;
 
-   /* USB2 and USB3 specific bits including Port Link State */
+   /* common wPortStatus bits */
+   if (raw_port_status & PORT_CONNECT) {
+   status |= USB_PORT_STAT_CONNECTION;
+   status |= xhci_port_speed(raw_port_status);
+   }
+   if (raw_port_status & PORT_PE)
+   status |= USB_PORT_STAT_ENABLE;
+   if (raw_port_status & PORT_OC)
+   status |= USB_PORT_STAT_OVERCURRENT;
+   if (raw_port_status & PORT_RESET)
+   status |= USB_PORT_STAT_RESET;
+
+   /* USB2 and USB3 specific bits, including Port Link State */
if (hcd->speed >= HCD_USB3)
xhci_get_usb3_port_status(port, , raw_port_status);
else
@@ -1010,16 +1022,6 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
bus_state->resume_done[wIndex] = 0;
clear_bit(wIndex, _state->resuming_ports);
}
-   if (raw_port_status & PORT_CONNECT) {
-   status |= USB_PORT_STAT_CONNECTION;
-   status |= xhci_port_speed(raw_port_status);
-   }
-   if (raw_port_status & PORT_PE)
-   status |= USB_PORT_STAT_ENABLE;
-   if (raw_port_status & PORT_OC)
-   status |= USB_PORT_STAT_OVERCURRENT;
-   if (raw_port_status & PORT_RESET)
-   status |= USB_PORT_STAT_RESET;
 
if (bus_state->port_c_suspend & (1 << wIndex))
status |= USB_PORT_STAT_C_SUSPEND << 16;
-- 
2.7.4



[PATCH 5/8] xhci: move usb2 speficic bits to own function in get_port_status call

2018-12-07 Thread Mathias Nyman
Mostly refactoring, with the exception that USB_PORT_STAT_L1 link state
is reported if xhci port link is in U2 AND port is powered.

Previously we did not check if the port was powered, but according to
xhci spec 4.19.1.1.6 All the 'Enabled' states, including
USB_PORT_STAT_L1 (U2), U1, U0 and U3 must have Port power bit set.

Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-hub.c | 44 
 1 file changed, 24 insertions(+), 20 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 60aeff3..5af4f90 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -714,13 +714,6 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, struct 
xhci_port *port,
}
 }
 
-/* Updates Link Status for USB 2.1 port */
-static void xhci_hub_report_usb2_link_state(u32 *status, u32 status_reg)
-{
-   if ((status_reg & PORT_PLS_MASK) == XDEV_U2)
-   *status |= USB_PORT_STAT_L1;
-}
-
 /* Updates Link Status for super Speed port */
 static void xhci_hub_report_usb3_link_state(struct xhci_hcd *xhci,
u32 *status, u32 status_reg)
@@ -853,6 +846,25 @@ static void xhci_get_usb3_port_status(struct xhci_port 
*port, u32 *status,
xhci_del_comp_mod_timer(xhci, portsc, portnum);
 }
 
+static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status,
+ u32 portsc)
+{
+   u32 link_state;
+
+   link_state = portsc & PORT_PLS_MASK;
+
+   /* USB2 wPortStatus bits */
+   if (portsc & PORT_POWER) {
+   *status |= USB_PORT_STAT_POWER;
+
+   /* link state is only valid if port is powered */
+   if (link_state == XDEV_U3)
+   *status |= USB_PORT_STAT_SUSPEND;
+   if (link_state == XDEV_U2)
+   *status |= USB_PORT_STAT_L1;
+   }
+}
+
 /*
  * Converts a raw xHCI port status into the format that external USB 2.0 or USB
  * 3.0 hubs use.
@@ -888,14 +900,13 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
status |= USB_PORT_STAT_C_OVERCURRENT << 16;
if ((raw_port_status & PORT_RC))
status |= USB_PORT_STAT_C_RESET << 16;
-   /* USB3.0 only */
+
+   /* USB2 and USB3 specific bits including Port Link State */
if (hcd->speed >= HCD_USB3)
xhci_get_usb3_port_status(port, , raw_port_status);
-   if (hcd->speed < HCD_USB3) {
-   if ((raw_port_status & PORT_PLS_MASK) == XDEV_U3
-   && (raw_port_status & PORT_POWER))
-   status |= USB_PORT_STAT_SUSPEND;
-   }
+   else
+   xhci_get_usb2_port_status(port, , raw_port_status);
+
if ((raw_port_status & PORT_PLS_MASK) == XDEV_RESUME &&
!DEV_SUPERSPEED_ANY(raw_port_status) && hcd->speed < HCD_USB3) {
if ((raw_port_status & PORT_RESET) ||
@@ -1009,13 +1020,6 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
status |= USB_PORT_STAT_OVERCURRENT;
if (raw_port_status & PORT_RESET)
status |= USB_PORT_STAT_RESET;
-   if (raw_port_status & PORT_POWER) {
-   if (hcd->speed < HCD_USB3)
-   status |= USB_PORT_STAT_POWER;
-   }
-   /* Update Port Link State */
-   if (hcd->speed < HCD_USB3)
-   xhci_hub_report_usb2_link_state(, raw_port_status);
 
if (bus_state->port_c_suspend & (1 << wIndex))
status |= USB_PORT_STAT_C_SUSPEND << 16;
-- 
2.7.4



[PATCH 8/8] xhci: move usb2 get port status link resume handling to its own function

2018-12-07 Thread Mathias Nyman
Refactoring, no functional changes.

But worth mentioning that checking for port link resume state is now behind
a additional port power check.

This is fine as ports can't be in resume state if port power bit is not
set.

xhci spec section 4.19.1.1.6 figure 34 shows that port power bit must be
set for all 'Enable' substates, including U0,U1,U2,U3 (suspended), Resume,
and RExit states.

Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-hub.c | 188 
 1 file changed, 104 insertions(+), 84 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index d86d1d5..c760175 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -795,6 +795,100 @@ static void xhci_del_comp_mod_timer(struct xhci_hcd 
*xhci, u32 status,
}
 }
 
+static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
+u32 *status, u32 portsc,
+unsigned long flags)
+{
+   struct xhci_bus_state *bus_state;
+   struct xhci_hcd *xhci;
+   struct usb_hcd *hcd;
+   int slot_id;
+   u32 wIndex;
+
+   hcd = port->rhub->hcd;
+   bus_state = >rhub->bus_state;
+   xhci = hcd_to_xhci(hcd);
+   wIndex = port->hcd_portnum;
+
+   if ((portsc & PORT_RESET) || !(portsc & PORT_PE)) {
+   *status = 0x;
+   return -EINVAL;
+   }
+   /* did port event handler already start resume timing? */
+   if (!bus_state->resume_done[wIndex]) {
+   /* If not, maybe we are in a host initated resume? */
+   if (test_bit(wIndex, _state->resuming_ports)) {
+   /* Host initated resume doesn't time the resume
+* signalling using resume_done[].
+* It manually sets RESUME state, sleeps 20ms
+* and sets U0 state. This should probably be
+* changed, but not right now.
+*/
+   } else {
+   /* port resume was discovered now and here,
+* start resume timing
+*/
+   unsigned long timeout = jiffies +
+   msecs_to_jiffies(USB_RESUME_TIMEOUT);
+
+   set_bit(wIndex, _state->resuming_ports);
+   bus_state->resume_done[wIndex] = timeout;
+   mod_timer(>rh_timer, timeout);
+   usb_hcd_start_port_resume(>self, wIndex);
+   }
+   /* Has resume been signalled for USB_RESUME_TIME yet? */
+   } else if (time_after_eq(jiffies, bus_state->resume_done[wIndex])) {
+   int time_left;
+
+   xhci_dbg(xhci, "Resume USB2 port %d\n", wIndex + 1);
+   bus_state->resume_done[wIndex] = 0;
+   clear_bit(wIndex, _state->resuming_ports);
+
+   set_bit(wIndex, _state->rexit_ports);
+
+   xhci_test_and_clear_bit(xhci, port, PORT_PLC);
+   xhci_set_link_state(xhci, port, XDEV_U0);
+
+   spin_unlock_irqrestore(>lock, flags);
+   time_left = wait_for_completion_timeout(
+   _state->rexit_done[wIndex],
+   msecs_to_jiffies(XHCI_MAX_REXIT_TIMEOUT_MS));
+   spin_lock_irqsave(>lock, flags);
+
+   if (time_left) {
+   slot_id = xhci_find_slot_id_by_port(hcd, xhci,
+   wIndex + 1);
+   if (!slot_id) {
+   xhci_dbg(xhci, "slot_id is zero\n");
+   *status = 0x;
+   return -ENODEV;
+   }
+   xhci_ring_device(xhci, slot_id);
+   } else {
+   int port_status = readl(port->addr);
+
+   xhci_warn(xhci, "Port resume %i msec timed out, portsc 
= 0x%x\n",
+ XHCI_MAX_REXIT_TIMEOUT_MS,
+ port_status);
+   *status |= USB_PORT_STAT_SUSPEND;
+   clear_bit(wIndex, _state->rexit_ports);
+   }
+
+   usb_hcd_end_port_resume(>self, wIndex);
+   bus_state->port_c_suspend |= 1 << wIndex;
+   bus_state->suspended_ports &= ~(1 << wIndex);
+   } else {
+   /*
+* The resume has been signaling for less than
+* USB_RESUME_TIME. Report the port status as SUSPEND,
+* let the usbcore check port status again and clear
+* resume signaling later.
+*/
+   *status |= US

[PATCH 0/8] xhci features for usb-next

2018-12-07 Thread Mathias Nyman
Hi Greg

This series for usb-next mostly about refactoring the xhci roothub
side of the get_port_status request

-Mathias

Mathias Nyman (7):
  xhci: move bus_state structure under the xhci_hub structure.
  xhci: remove unused hcd_index()
  xhci: move usb3 speficic bits to own function in get_port_status call
  xhci: move usb2 speficic bits to own function in get_port_status call
  xhci: cleanup code that sets portstatus and portchange bits
  xhci: refactor U0 link state handling in get_port_status
  xhci: move usb2 get port status link resume handling to its own
function

Zeng Tao (1):
  xhci: remove the unused sw_lpm_support

 drivers/usb/host/xhci-hub.c  | 351 ---
 drivers/usb/host/xhci-mem.c  |  30 ++--
 drivers/usb/host/xhci-ring.c |   2 +-
 drivers/usb/host/xhci.c  |  22 +--
 drivers/usb/host/xhci.h  |  13 +-
 5 files changed, 219 insertions(+), 199 deletions(-)

-- 
2.7.4



[PATCH 2/8] xhci: move bus_state structure under the xhci_hub structure.

2018-12-07 Thread Mathias Nyman
Move the bus_state structure under struct usb_hub.

We need a bus_state strucure for each roothub to keep track of suspend
related info for each port.
Instead of keeping an array of two bus_state structures right under
struct xhci, it makes more sense move them to the xhci_hub structure.

No functional changes.

Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-hub.c  | 15 ++-
 drivers/usb/host/xhci-mem.c  | 10 +-
 drivers/usb/host/xhci-ring.c |  2 +-
 drivers/usb/host/xhci.c  | 19 ++-
 drivers/usb/host/xhci.h  |  4 ++--
 5 files changed, 24 insertions(+), 26 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 94aca1b..5dba0a4 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -1031,7 +1031,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, 
u16 wValue,
rhub = xhci_get_rhub(hcd);
ports = rhub->ports;
max_ports = rhub->num_ports;
-   bus_state = >bus_state[hcd_index(hcd)];
+   bus_state = >bus_state;
 
spin_lock_irqsave(>lock, flags);
switch (typeReq) {
@@ -1421,7 +1421,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
rhub = xhci_get_rhub(hcd);
ports = rhub->ports;
max_ports = rhub->num_ports;
-   bus_state = >bus_state[hcd_index(hcd)];
+   bus_state = >bus_state;
 
/* Initial status is no changes */
retval = (max_ports + 8) / 8;
@@ -1480,7 +1480,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
rhub = xhci_get_rhub(hcd);
ports = rhub->ports;
max_ports = rhub->num_ports;
-   bus_state = >bus_state[hcd_index(hcd)];
+   bus_state = >bus_state;
wake_enabled = hcd->self.root_hub->do_remote_wakeup;
 
spin_lock_irqsave(>lock, flags);
@@ -1622,7 +1622,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
rhub = xhci_get_rhub(hcd);
ports = rhub->ports;
max_ports = rhub->num_ports;
-   bus_state = >bus_state[hcd_index(hcd)];
+   bus_state = >bus_state;
 
if (time_before(jiffies, bus_state->next_statechange))
msleep(5);
@@ -1723,13 +1723,10 @@ int xhci_bus_resume(struct usb_hcd *hcd)
 
 unsigned long xhci_get_resuming_ports(struct usb_hcd *hcd)
 {
-   struct xhci_hcd *xhci = hcd_to_xhci(hcd);
-   struct xhci_bus_state *bus_state;
-
-   bus_state = >bus_state[hcd_index(hcd)];
+   struct xhci_hub *rhub = xhci_get_rhub(hcd);
 
/* USB3 port wakeups are reported via usb_wakeup_notification() */
-   return bus_state->resuming_ports;   /* USB2 ports only */
+   return rhub->bus_state.resuming_ports;  /* USB2 ports only */
 }
 
 #endif /* CONFIG_PM */
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 791c5d8..36a3eb8 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1922,8 +1922,8 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci)
 
xhci->page_size = 0;
xhci->page_shift = 0;
-   xhci->bus_state[0].bus_suspended = 0;
-   xhci->bus_state[1].bus_suspended = 0;
+   xhci->usb2_rhub.bus_state.bus_suspended = 0;
+   xhci->usb3_rhub.bus_state.bus_suspended = 0;
 }
 
 static int xhci_test_trb_in_td(struct xhci_hcd *xhci,
@@ -2524,10 +2524,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
for (i = 0; i < MAX_HC_SLOTS; i++)
xhci->devs[i] = NULL;
for (i = 0; i < USB_MAXCHILDREN; i++) {
-   xhci->bus_state[0].resume_done[i] = 0;
-   xhci->bus_state[1].resume_done[i] = 0;
+   xhci->usb2_rhub.bus_state.resume_done[i] = 0;
+   xhci->usb3_rhub.bus_state.resume_done[i] = 0;
/* Only the USB 2.0 completions will ever be used. */
-   init_completion(>bus_state[1].rexit_done[i]);
+   init_completion(>usb2_rhub.bus_state.rexit_done[i]);
}
 
if (scratchpad_alloc(xhci, flags))
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 6575058..40fa25c 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1593,7 +1593,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
}
 
hcd = port->rhub->hcd;
-   bus_state = >bus_state[hcd_index(hcd)];
+   bus_state = >rhub->bus_state;
hcd_portnum = port->hcd_portnum;
portsc = readl(port->addr);
 
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 553e974..6631e7f 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -169,7 +169,7 @@ int xhci_reset(struct xhci_hcd *xhci)
 {
u32 command;
u32 state;
-   int ret, i;
+   int ret;
 
state = readl(>op_regs->status);
 
@@ -215,11 +215,12 @@ int xhci_reset(struct xhci

[PATCH 3/8] xhci: remove unused hcd_index()

2018-12-07 Thread Mathias Nyman
Now that each root hub has their own bus_state strucure the
hcd_undex() used to get the correct bus_state strucure is
no longer needed.

No functional changes

Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci.h | 7 ---
 1 file changed, 7 deletions(-)

diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index b57b793..3c6b504 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1682,13 +1682,6 @@ struct xhci_bus_state {
  */
 #defineXHCI_MAX_REXIT_TIMEOUT_MS   20
 
-static inline unsigned int hcd_index(struct usb_hcd *hcd)
-{
-   if (hcd->speed >= HCD_USB3)
-   return 0;
-   else
-   return 1;
-}
 struct xhci_port {
__le32 __iomem  *addr;
int hw_portnum;
-- 
2.7.4



[PATCH 7/8] xhci: refactor U0 link state handling in get_port_status

2018-12-07 Thread Mathias Nyman
Move U0 link state handing to USB3 and USB2 specific functions

Note that
bus_state->resuming_ports:
bus_state->resume_done[]:
are only used for USB2, and don't need to cleared for USB3 ports

No functional changes

Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-hub.c | 32 +++-
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index c0de2d0..d86d1d5 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -814,10 +814,12 @@ static u32 xhci_get_ext_port_status(u32 raw_port_status, 
u32 port_li)
 static void xhci_get_usb3_port_status(struct xhci_port *port, u32 *status,
  u32 portsc)
 {
+   struct xhci_bus_state *bus_state;
struct xhci_hcd *xhci;
u32 link_state;
u32 portnum;
 
+   bus_state = >rhub->bus_state;
xhci = hcd_to_xhci(port->rhub->hcd);
link_state = portsc & PORT_PLS_MASK;
portnum = port->hcd_portnum;
@@ -839,8 +841,12 @@ static void xhci_get_usb3_port_status(struct xhci_port 
*port, u32 *status,
*status |= USB_PORT_STAT_C_CONFIG_ERROR << 16;
 
/* USB3 specific wPortStatus bits */
-   if (portsc & PORT_POWER)
+   if (portsc & PORT_POWER) {
*status |= USB_SS_PORT_STAT_POWER;
+   /* link state handling */
+   if (link_state == XDEV_U0)
+   bus_state->suspended_ports &= ~(1 << portnum);
+   }
 
xhci_hub_report_usb3_link_state(xhci, status, portsc);
xhci_del_comp_mod_timer(xhci, portsc, portnum);
@@ -849,9 +855,13 @@ static void xhci_get_usb3_port_status(struct xhci_port 
*port, u32 *status,
 static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status,
  u32 portsc)
 {
+   struct xhci_bus_state *bus_state;
u32 link_state;
+   u32 portnum;
 
+   bus_state = >rhub->bus_state;
link_state = portsc & PORT_PLS_MASK;
+   portnum = port->hcd_portnum;
 
/* USB2 wPortStatus bits */
if (portsc & PORT_POWER) {
@@ -862,6 +872,14 @@ static void xhci_get_usb2_port_status(struct xhci_port 
*port, u32 *status,
*status |= USB_PORT_STAT_SUSPEND;
if (link_state == XDEV_U2)
*status |= USB_PORT_STAT_L1;
+   if (link_state == XDEV_U0) {
+   bus_state->resume_done[portnum] = 0;
+   clear_bit(portnum, _state->resuming_ports);
+   if (bus_state->suspended_ports & (1 << portnum)) {
+   bus_state->suspended_ports &= ~(1 << portnum);
+   bus_state->port_c_suspend |= 1 << portnum;
+   }
+   }
}
 }
 
@@ -1011,18 +1029,6 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
usb_hcd_end_port_resume(>self, wIndex);
}
 
-
-   if ((raw_port_status & PORT_PLS_MASK) == XDEV_U0 &&
-   (raw_port_status & PORT_POWER)) {
-   if (bus_state->suspended_ports & (1 << wIndex)) {
-   bus_state->suspended_ports &= ~(1 << wIndex);
-   if (hcd->speed < HCD_USB3)
-   bus_state->port_c_suspend |= 1 << wIndex;
-   }
-   bus_state->resume_done[wIndex] = 0;
-   clear_bit(wIndex, _state->resuming_ports);
-   }
-
if (bus_state->port_c_suspend & (1 << wIndex))
status |= USB_PORT_STAT_C_SUSPEND << 16;
 
-- 
2.7.4



[PATCH 0/2] xhci fixes for usb-linus

2018-12-05 Thread Mathias Nyman
Hi Greg

A couple patches for 4.20.

Finally found a reason why devices attached after a high bandwidth USB3
isoc device may fail to enumerate with bandwidth error.

Second patch is a quirk for AMD SNPS host specific suspend issue.

-Mathias


Mathias Nyman (1):
  xhci: Prevent U1/U2 link pm states if exit latency is too long

Sandeep Singh (1):
  xhci: workaround CSS timeout on AMD SNPS 3.0 xHC

 drivers/usb/host/xhci-pci.c |  4 
 drivers/usb/host/xhci.c | 42 ++
 drivers/usb/host/xhci.h |  3 +++
 3 files changed, 45 insertions(+), 4 deletions(-)

-- 
2.7.4



[PATCH 1/2] xhci: workaround CSS timeout on AMD SNPS 3.0 xHC

2018-12-05 Thread Mathias Nyman
From: Sandeep Singh 

Occasionally AMD SNPS 3.0 xHC does not respond to
CSS when set, also it does not flag anything on SRE and HCE
to point the internal xHC errors on USBSTS register. This stalls
the entire system wide suspend and there is no point in stalling
just because of xHC CSS is not responding.

To work around this problem, if the xHC does not flag
anything on SRE and HCE, we can skip the CSS
timeout and allow the system to continue the suspend. Once the
system resume happens we can internally reset the controller
using XHCI_RESET_ON_RESUME quirk

Signed-off-by: Shyam Sundar S K 
Signed-off-by: Sandeep Singh 
cc: Nehal Shah 
Cc: 
Tested-by: Kai-Heng Feng 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-pci.c |  4 
 drivers/usb/host/xhci.c | 26 ++
 drivers/usb/host/xhci.h |  3 +++
 3 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index a951526..a9ec705 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -139,6 +139,10 @@ static void xhci_pci_quirks(struct device *dev, struct 
xhci_hcd *xhci)
 pdev->device == 0x43bb))
xhci->quirks |= XHCI_SUSPEND_DELAY;
 
+   if (pdev->vendor == PCI_VENDOR_ID_AMD &&
+   (pdev->device == 0x15e0 || pdev->device == 0x15e1))
+   xhci->quirks |= XHCI_SNPS_BROKEN_SUSPEND;
+
if (pdev->vendor == PCI_VENDOR_ID_AMD)
xhci->quirks |= XHCI_TRUST_TX_LENGTH;
 
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index c928dbb..c20b85e 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -968,6 +968,7 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
unsigned intdelay = XHCI_MAX_HALT_USEC;
struct usb_hcd  *hcd = xhci_to_hcd(xhci);
u32 command;
+   u32 res;
 
if (!hcd->state)
return 0;
@@ -1021,11 +1022,28 @@ int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
command = readl(>op_regs->command);
command |= CMD_CSS;
writel(command, >op_regs->command);
+   xhci->broken_suspend = 0;
if (xhci_handshake(>op_regs->status,
STS_SAVE, 0, 10 * 1000)) {
-   xhci_warn(xhci, "WARN: xHC save state timeout\n");
-   spin_unlock_irq(>lock);
-   return -ETIMEDOUT;
+   /*
+* AMD SNPS xHC 3.0 occasionally does not clear the
+* SSS bit of USBSTS and when driver tries to poll
+* to see if the xHC clears BIT(8) which never happens
+* and driver assumes that controller is not responding
+* and times out. To workaround this, its good to check
+* if SRE and HCE bits are not set (as per xhci
+* Section 5.4.2) and bypass the timeout.
+*/
+   res = readl(>op_regs->status);
+   if ((xhci->quirks & XHCI_SNPS_BROKEN_SUSPEND) &&
+   (((res & STS_SRE) == 0) &&
+   ((res & STS_HCE) == 0))) {
+   xhci->broken_suspend = 1;
+   } else {
+   xhci_warn(xhci, "WARN: xHC save state timeout\n");
+   spin_unlock_irq(>lock);
+   return -ETIMEDOUT;
+   }
}
spin_unlock_irq(>lock);
 
@@ -1078,7 +1096,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
set_bit(HCD_FLAG_HW_ACCESSIBLE, >shared_hcd->flags);
 
spin_lock_irq(>lock);
-   if (xhci->quirks & XHCI_RESET_ON_RESUME)
+   if ((xhci->quirks & XHCI_RESET_ON_RESUME) || xhci->broken_suspend)
hibernated = true;
 
if (!hibernated) {
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 260b259..c3515ba 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1850,6 +1850,7 @@ struct xhci_hcd {
 #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)
+#define XHCI_SNPS_BROKEN_SUSPENDBIT_ULL(35)
 
unsigned intnum_active_eps;
unsigned intlimit_active_eps;
@@ -1879,6 +1880,8 @@ struct xhci_hcd {
void*dbc;
/* platform-specific data -- must come last */
unsigned long   priv[0] __aligned(sizeof(s64));
+   /* Broken Suspend flag for SNPS Suspend resume issue */
+   u8  broken_suspend;
 };
 
 /* Platform specific overrides to generic XHCI hc_driver ops */
-- 
2.7.4



[PATCH 2/2] xhci: Prevent U1/U2 link pm states if exit latency is too long

2018-12-05 Thread Mathias Nyman
Don't allow USB3 U1 or U2 if the latency to wake up from the U-state
reaches the service interval for a periodic endpoint.

This is according to xhci 1.1 specification section 4.23.5.2 extra note:

"Software shall ensure that a device is prevented from entering a U-state
 where its worst case exit latency approaches the ESIT."

Allowing too long exit latencies for periodic endpoint confuses xHC
internal scheduling, and new devices may fail to enumerate with a
"Not enough bandwidth for new device state" error from the host.

Cc: 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index c20b85e..dae3be1 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -4514,6 +4514,14 @@ static u16 xhci_calculate_u1_timeout(struct xhci_hcd 
*xhci,
 {
unsigned long long timeout_ns;
 
+   /* Prevent U1 if service interval is shorter than U1 exit latency */
+   if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) {
+   if (xhci_service_interval_to_ns(desc) <= udev->u1_params.mel) {
+   dev_dbg(>dev, "Disable U1, ESIT shorter than exit 
latency\n");
+   return USB3_LPM_DISABLED;
+   }
+   }
+
if (xhci->quirks & XHCI_INTEL_HOST)
timeout_ns = xhci_calculate_intel_u1_timeout(udev, desc);
else
@@ -4570,6 +4578,14 @@ static u16 xhci_calculate_u2_timeout(struct xhci_hcd 
*xhci,
 {
unsigned long long timeout_ns;
 
+   /* Prevent U2 if service interval is shorter than U2 exit latency */
+   if (usb_endpoint_xfer_int(desc) || usb_endpoint_xfer_isoc(desc)) {
+   if (xhci_service_interval_to_ns(desc) <= udev->u2_params.mel) {
+   dev_dbg(>dev, "Disable U2, ESIT shorter than exit 
latency\n");
+   return USB3_LPM_DISABLED;
+   }
+   }
+
if (xhci->quirks & XHCI_INTEL_HOST)
timeout_ns = xhci_calculate_intel_u2_timeout(udev, desc);
else
-- 
2.7.4



Re: USB driver resets

2018-12-04 Thread Mathias Nyman

On 03.12.2018 12:36, Richard van der Hoff wrote:

Does anybody have any suggestions as to how I could set about debugging this? 
I'm seeing the same symptoms on a 4.19 kernel.


On 19/11/2018 15:27, Richard van der Hoff wrote:

I have a USB-3.1 dock, which I use for video (via displayport alt mode) and 
power delivery, as well as keyboard, mouse, etc.

From time to time, all connectivity with the dock drops out for a few seconds, 
before resetting itself. I'm trying to pin down if this is a problem with the 
usb drivers, pci drivers, laptop hardware, or the dock. It looks to me from the 
dmesg output like it could be a problem at the PCI layer, but I am only 
speculating really.

Attached are the dmesg output during the problem, lsusb -v, and lspci -v. They 
are all recorded with a 4.15.0 kernel; I've seen exactly the same symptoms with 
a number of kernels between 4.8 and 4.15.

Advice appreciated!



Mika (cc) would be the right person to contact about these kind of thunderbolt 
related issues.
I'm sure he would appreciate logs with a 4.19 - 4.20-rcx kernel.

-Mathias


[PATCH] usb: hub: delay hub autosuspend if USB3 port is still link training

2018-11-28 Thread Mathias Nyman
When initializing a hub we want to give a USB3 port in link training
the same debounce delay time before autosuspening the hub as already
trained, connected enabled ports.

USB3 ports won't reach the enabled state with "current connect status" and
"connect status change" bits set until the USB3 link training finishes.

Catching the port in link training (polling) and adding the debounce delay
prevents unnecessary failed attempts to autosuspend the hub.

Signed-off-by: Mathias Nyman 
---
 drivers/usb/core/hub.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 0f9381b..009f928 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1112,6 +1112,16 @@ static void hub_activate(struct usb_hub *hub, enum 
hub_activation_type type)
   USB_PORT_FEAT_ENABLE);
}
 
+   /*
+* Add debounce if USB3 link is in polling/link training state.
+* Link will automatically transition to Enabled state after
+* link training completes.
+*/
+   if (hub_is_superspeed(hdev) &&
+   ((portstatus & USB_PORT_STAT_LINK_STATE) ==
+   USB_SS_PORT_LS_POLLING))
+   need_debounce_delay = true;
+
/* Clear status-change flags; we'll debounce later */
if (portchange & USB_PORT_STAT_C_CONNECTION) {
need_debounce_delay = true;
-- 
2.7.4



[PATCH 1/1] xhci: Prevent bus suspend if a port connect change or polling state is detected

2018-11-15 Thread Mathias Nyman
USB3 roothub might autosuspend before a plugged USB3 device is detected,
causing USB3 device enumeration failure.

USB3 devices don't show up as connected and enabled until USB3 link trainig
completes. On a fast booting platform with a slow USB3 link training the
link might reach the connected enabled state just as the bus is suspending.

If this device is discovered first time by the xhci_bus_suspend() routine
it will be put to U3 suspended state like the other ports which failed to
suspend earlier.

The hub thread will notice the connect change and resume the bus,
moving the port back to U0

This U0 -> U3 -> U0 transition right after being connected seems to be
too much for some devices, causing them to first go to SS.Inactive state,
and finally end up stuck in a polling state with reset asserted

Fix this by failing the bus suspend if a port has a connect change or is
in a polling state in xhci_bus_suspend().

Don't do any port changes until all ports are checked, buffer all port
changes and only write them in the end if suspend can proceed

Cc: sta...@vger.kernel.org
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-hub.c | 60 ++---
 1 file changed, 46 insertions(+), 14 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index da98a11..94aca1b 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -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 = >bus_state[hcd_index(hcd)];
+   wake_enabled = hcd->self.root_hub->do_remote_wakeup;
 
spin_lock_irqsave(>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(>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(>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(>lock, flags);
-   xhci_stop_device(xhci, slot_id, 1);
-   spin_lock_irqsave(>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, _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) {
   

[PATCH 0/1] xhci fix for usb-linus

2018-11-15 Thread Mathias Nyman
Hi Greg

A case was found where USB3 devices fail to enumerate at boot.
If a USB3 link is trained slowly then the roothub might autosuspend
while device is just getting enabled.

This patch fixes the issue

-Mathias

Mathias Nyman (1):
  xhci: Prevent bus suspend if a port connect change or polling state is
detected

 drivers/usb/host/xhci-hub.c | 60 ++---
 1 file changed, 46 insertions(+), 14 deletions(-)

-- 
2.7.4



Re: [PATCH] xhci: handle stop ep on invalid CStream

2018-11-14 Thread Mathias Nyman

Hi

On 13.11.2018 08:48, Henry Lin wrote:

Below Note in xHCI spec 6.4.2.1 describes a Transfer Event is generated
for Stop Endpoint Command on invalid CStream:

CStream is not valid until a Streams endpoint transitions to the Start
Stream state for the first time. A Transfer Event generated by a Stop
Endpoint Command shall report '0' in the TRB Pointer and TRB Length fields
if the command is executed and CStream is invalid. Refer to section 4.12.1.

But, current implementation will output below error messages once driver
receives the Transfer Event for invalid CStream:

[  133.184633] xhci_hcd :01:00.2: ERROR Transfer event for unknown stream 
ring slot 1 ep 2
[  133.184635] xhci_hcd :01:00.2: @00046044a420   
1b00 01038001

This issue can be observed while uas driver is handling SCSI command that
connected UAS device doesn't support. UAS device rejects the unsupported
command and causes Data-In stream for SCSI command data stopped when
CStream is invalid.

This patch handles the transfer event to remove false error messages.



A patch by Sandeep Singh that takes care of the same COMP_STOPPED_LENGTH_INVALID
case with zero TRB pointer just got applied, so this should now be taken care 
of.

https://marc.info/?l=linux-usb=153753620603125=2

It's in Greg's usb-linus branch:
d9193ef xhci: Add check for invalid byte size error when UAS devices are 
connected.

-Mathias


[PATCH 3/6] xhci: Add check for invalid byte size error when UAS devices are connected.

2018-11-12 Thread Mathias Nyman
From: Sandeep Singh 

Observed "TRB completion code (27)" error which corresponds to Stopped -
Length Invalid error(xhci spec section 4.17.4) while connecting USB to
SATA bridge.

Looks like this case was not considered when the following patch[1] was
committed. Hence adding this new check which can prevent
the invalid byte size error.

[1] ade2e3a xhci: handle transfer events without TRB pointer

Cc: 
Signed-off-by: Sandeep Singh 
cc: Nehal Shah 
cc: Shyam Sundar S K 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-ring.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 80d464e..730a6ec 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2273,6 +2273,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",
-- 
2.7.4



[PATCH 5/6] usb: xhci: fix timeout for transition from RExit to U0

2018-11-12 Thread Mathias Nyman
From: Aaron Ma 

This definition is used by msecs_to_jiffies in milliseconds.
According to the comments, max rexit timeout should be 20ms.
Align with the comments to properly calculate the delay.

Verified on Sunrise Point-LP and Cannon Lake.

Cc: sta...@vger.kernel.org
Signed-off-by: Aaron Ma 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-hub.c | 4 ++--
 drivers/usb/host/xhci.h | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 60e4ac7..da98a11 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -921,7 +921,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
time_left = wait_for_completion_timeout(
_state->rexit_done[wIndex],
msecs_to_jiffies(
-   XHCI_MAX_REXIT_TIMEOUT));
+   XHCI_MAX_REXIT_TIMEOUT_MS));
spin_lock_irqsave(>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, _state->rexit_ports);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index bf0b369..5f0c4f1 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -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.
  */
-#defineXHCI_MAX_REXIT_TIMEOUT  (20 * 1000)
+#defineXHCI_MAX_REXIT_TIMEOUT_MS   20
 
 static inline unsigned int hcd_index(struct usb_hcd *hcd)
 {
-- 
2.7.4



[PATCH 6/6] xhci: Add quirk to workaround the errata seen on Cavium Thunder-X2 Soc

2018-11-12 Thread Mathias Nyman
From: "Cherian, George" 

Implement workaround for ThunderX2 Errata-129 (documented in
CN99XX Known Issues" available at Cavium support site).
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, the link will come up as USB 1 for the USB 2 device.

Resolution: Reset the PHY after the USB 1 device is disconnected.
The PHY reset sequence is done using private registers in XHCI register
space. After the PHY is reset we check for the PLL lock status and retry
the operation if it fails. From our tests, retrying 4 times is sufficient.

Add a new quirk flag XHCI_RESET_PLL_ON_DISCONNECT to invoke the workaround
in handle_xhci_port_status().

Cc: sta...@vger.kernel.org
Signed-off-by: George Cherian 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-pci.c  |  5 +
 drivers/usb/host/xhci-ring.c | 35 ++-
 drivers/usb/host/xhci.h  |  1 +
 3 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 1fb448c..a951526 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -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");
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 250b758..6575058 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -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)
 {
@@ -1654,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 */
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 5f0c4f1..260b259 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -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 intnum_active_eps;
unsigned intlimit_active_eps;
-- 
2.7.4



[PATCH 2/6] xhci: handle port status events for removed USB3 hcd

2018-11-12 Thread Mathias Nyman
At xhci removal the USB3 hcd (shared_hcd) is removed before the primary
USB2 hcd. Interrupts for port status changes may still occur for USB3
ports after the shared_hcd is freed, causing  NULL pointer dereference.

Check if xhci->shared_hcd is still valid before handing USB3 port events

Cc: 
Reported-by: Peter Chen 
Tested-by: Jack Pham 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-ring.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index a8d92c9..80d464e 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1556,6 +1556,13 @@ static void handle_port_status(struct xhci_hcd *xhci,
goto cleanup;
}
 
+   /* We might get interrupts after shared_hcd is removed */
+   if (port->rhub == >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 = >bus_state[hcd_index(hcd)];
hcd_portnum = port->hcd_portnum;
-- 
2.7.4



[PATCH 1/6] xhci: Fix leaking USB3 shared_hcd at xhci removal

2018-11-12 Thread Mathias Nyman
Ensure that the shared_hcd pointer is valid when calling usb_put_hcd()

The shared_hcd is removed and freed in xhci by first calling
usb_remove_hcd(xhci->shared_hcd), and later
usb_put_hcd(xhci->shared_hcd)

Afer commit fe190ed0d602 ("xhci: Do not halt the host until both HCD have
disconnected their devices.") the shared_hcd was never properly put as
xhci->shared_hcd was set to NULL before usb_put_hcd(xhci->shared_hcd) was
called.

shared_hcd (USB3) is removed before primary hcd (USB2).
While removing the primary hcd we might need to handle xhci interrupts
to cleanly remove last USB2 devices, therefore we need to set
xhci->shared_hcd to NULL before removing the primary hcd to let xhci
interrupt handler know shared_hcd is no longer available.

xhci-plat.c, xhci-histb.c and xhci-mtk first create both their hcd's before
adding them. so to keep the correct reverse removal order use a temporary
shared_hcd variable for them.
For more details see commit 4ac53087d6d4 ("usb: xhci: plat: Create both
HCDs before adding them")

Fixes: fe190ed0d602 ("xhci: Do not halt the host until both HCD have 
disconnected their devices.")
Cc: Joel Stanley 
Cc: Chunfeng Yun 
Cc: Thierry Reding 
Cc: Jianguo Sun 
Cc: 
Reported-by: Jack Pham 
Tested-by: Jack Pham 
Tested-by: Peter Chen 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-histb.c | 6 --
 drivers/usb/host/xhci-mtk.c   | 6 --
 drivers/usb/host/xhci-pci.c   | 1 +
 drivers/usb/host/xhci-plat.c  | 6 --
 drivers/usb/host/xhci-tegra.c | 1 +
 drivers/usb/host/xhci.c   | 2 --
 6 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/host/xhci-histb.c b/drivers/usb/host/xhci-histb.c
index 27f0016..3c4abb5 100644
--- a/drivers/usb/host/xhci-histb.c
+++ b/drivers/usb/host/xhci-histb.c
@@ -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);
 
usb_remove_hcd(hcd);
-   usb_put_hcd(xhci->shared_hcd);
+   usb_put_hcd(shared_hcd);
 
xhci_histb_host_disable(histb);
usb_put_hcd(hcd);
diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index 71d0d33..60987c7 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -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, 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);
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 01c5705..1fb448c 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -380,6 +380,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 */
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 32b5574..ef09cb0 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -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);
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index 6b5db34..938ff06 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -1303,6 +1303,7 @@ static int tegra_xusb_remove(struct platform_device *pdev)
 
usb_remove_hcd(xhci->shared_hcd);
us

[PATCH 0/6] xhci fixes for usb-linus

2018-11-12 Thread Mathias Nyman


A few xhci fixes for usb-linus, among othres fixing a hcd leak at removal,
setting timout values correctly, and making sure USB3 and USB2 ports don't
get mixed up in resume when port speed field may be unreliable.

This series was sent to Greg and other patch stakeholders earlier,but due
to a typo never made it to linux-usb mailing list. Resending it.

-Mathias

Aaron Ma (2):
  usb: xhci: fix uninitialized completion when USB3 port got wrong
status
  usb: xhci: fix timeout for transition from RExit to U0

Cherian, George (1):
  xhci: Add quirk to workaround the errata seen on Cavium Thunder-X2 Soc

Mathias Nyman (2):
  xhci: Fix leaking USB3 shared_hcd at xhci removal
  xhci: handle port status events for removed USB3 hcd

Sandeep Singh (1):
  xhci: Add check for invalid byte size error when UAS devices are
connected.

 drivers/usb/host/xhci-histb.c |  6 --
 drivers/usb/host/xhci-hub.c   |  6 +++---
 drivers/usb/host/xhci-mtk.c   |  6 --
 drivers/usb/host/xhci-pci.c   |  6 ++
 drivers/usb/host/xhci-plat.c  |  6 --
 drivers/usb/host/xhci-ring.c  | 45 +--
 drivers/usb/host/xhci-tegra.c |  1 +
 drivers/usb/host/xhci.c   |  2 --
 drivers/usb/host/xhci.h   |  3 ++-
 9 files changed, 67 insertions(+), 14 deletions(-)

-- 
2.7.4



[PATCH 4/6] usb: xhci: fix uninitialized completion when USB3 port got wrong status

2018-11-12 Thread Mathias Nyman
From: Aaron Ma 

Realtek USB3.0 Card Reader [0bda:0328] reports wrong port status on
Cannon lake PCH USB3.1 xHCI [8086:a36d] after resume from S3,
after clear port reset it works fine.

Since this device is registered on USB3 roothub at boot,
when port status reports not superspeed, xhci_get_port_status will call
an uninitialized completion in bus_state[0].
Kernel will hang because of NULL pointer.

Restrict the USB2 resume status check in USB2 roothub to fix hang issue.

Cc: sta...@vger.kernel.org
Signed-off-by: Aaron Ma 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-hub.c  | 2 +-
 drivers/usb/host/xhci-ring.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 12eea73..60e4ac7 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,
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 0x;
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 730a6ec..250b758 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1646,7 +1646,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,
_state->rexit_ports)) {
complete(_state->rexit_done[hcd_portnum]);
-- 
2.7.4



Re: EPROTO when USB 3 GbE adapters are under load

2018-10-26 Thread Mathias Nyman

On 25.10.2018 20:28, Alan Stern wrote:

On Thu, 25 Oct 2018, Mathias Nyman wrote:


On 25.10.2018 12:52, Hao Wei Tee wrote:

On 25/10/18 4:45 PM, Mathias Nyman wrote:

Reproducing the issue with a recent kernel with xhci traces enabled should show 
the reason for EPROTO error.

Add xhci traces before triggering the issue with:

mount -t debugfs none /sys/kernel/debug
echo 81920 > /sys/kernel/debug/tracing/buffer_size_kb
echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/enable

after issue is triggered save and send the trace at 
/sys/kernel/debug/tracing/trace
Note that it might be huge


Thanks for the suggestion.

Here[1] is (part of) the trace starting about 250 lines before the EPROTO 
happens.

[1]: 
https://gist.githubusercontent.com/angelsl/fdd04d2bded3a41029122b0536c00944/raw/b8e9f7d2695ac030b7f3dd53a1a9c3f37da7b7a0/trace

The first error happens at line 243 (timestamp 8144.248398) coinciding with the 
start of errors spewed into dmesg:

[ 8144.245359] r8152 2-2:1.0 enp0s20f0u2: Rx status -71
[ 8144.248837] r8152 2-2:1.0 enp0s20f0u2: Rx status -71
[ 8144.252392] r8152 2-2:1.0 enp0s20f0u2: Rx status -71
[ 8144.255987] r8152 2-2:1.0 enp0s20f0u2: Stop submitting intr, status -71


Thanks,
xHC controller reports that there was a transaction error on one of the bulk 
TRBs.

The transaction error causes the endpoint to halt (host side halt only).
Xhci driver resets the host side endpoint to recover from the halt,
then returns the broken URB (TRB) with -EPROTO status, and then moves past this 
TRB.


The host side of the endpoint should remain stopped until after the
URB's completion routine has had a chance to carry out error recovery.
Doesn't this imply the xHCI driver shouldn't reset the host-side
endpoint until after the giveback call returns?


True, on xhci side we could probably reset the endpoint, and even move the
dequeue pointer to the next TRB, but make sure the endpoint is not restarted 
yet.

The URB with -EPROTO status is given back in interrupt context, so this might 
limit
a bit what the higher-layer drivers can do in giveback.

Now thinking about it, xhci driver calls the URB giveback in the same "Transaction 
error"
interrupt handler, after first queuing areset endpoint and a set TR Deq pointer 
command.
The endpoint is only restarted after those commands finish, in the command 
completion interrupt
handler.

So in that sense the endpoint shouldn't be restarted until the next interrupt 
is handled,
which shouldn't be possible before the URB giveback call returned in the 
previous interrupt handler.

Well, at least not as long as we are in hard interrupt.

I think I need to dig a bit more into this.




Interesting thing here is that each TRB in the queue after the transaction error
also triggers a transaction error.
  
This might be a data toggle/sequence number sync issue.


It's more likely to be a problem on the device side.  Data toggle or
sequence number issues tend to be self-repairing (albeit with some data
loss) after a little while.


Ok, thanks, not spending too much time looking into that then.




The host side endpoint reset clears the host side sequence number,
and host expects device side endpoint to be reset and sequence to be cleared as 
well
as a result of returning -EPROTO.
If I remember correctly xhci driver does not wait for device side endpoint to 
be reset,
so if there are  TRBs in the queue they will be transferred, with a cleared 
sequence number
out of sync with the device side.


That's why it's important to wait until after the higher-layer driver
has had a chance to unlink the URBs that may be in the endpoint queue.
The driver may even want to reset the device.


Would it make sense to prevent endpoint from running until usb core calls
hcd->driver->endpoint_reset?
That is for halted endpoints, that returned URB with -EPROTO status.

-Mathias   


Re: EPROTO when USB 3 GbE adapters are under load

2018-10-25 Thread Mathias Nyman

On 25.10.2018 12:52, Hao Wei Tee wrote:

On 25/10/18 4:45 PM, Mathias Nyman wrote:

Reproducing the issue with a recent kernel with xhci traces enabled should show 
the reason for EPROTO error.

Add xhci traces before triggering the issue with:

mount -t debugfs none /sys/kernel/debug
echo 81920 > /sys/kernel/debug/tracing/buffer_size_kb
echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/enable

after issue is triggered save and send the trace at 
/sys/kernel/debug/tracing/trace
Note that it might be huge


Thanks for the suggestion.

Here[1] is (part of) the trace starting about 250 lines before the EPROTO 
happens.

[1]: 
https://gist.githubusercontent.com/angelsl/fdd04d2bded3a41029122b0536c00944/raw/b8e9f7d2695ac030b7f3dd53a1a9c3f37da7b7a0/trace

The first error happens at line 243 (timestamp 8144.248398) coinciding with the 
start of errors spewed into dmesg:

[ 8144.245359] r8152 2-2:1.0 enp0s20f0u2: Rx status -71
[ 8144.248837] r8152 2-2:1.0 enp0s20f0u2: Rx status -71
[ 8144.252392] r8152 2-2:1.0 enp0s20f0u2: Rx status -71
[ 8144.255987] r8152 2-2:1.0 enp0s20f0u2: Stop submitting intr, status -71


Thanks,
xHC controller reports that there was a transaction error on one of the bulk 
TRBs.

The transaction error causes the endpoint to halt (host side halt only).
Xhci driver resets the host side endpoint to recover from the halt,
then returns the broken URB (TRB) with -EPROTO status, and then moves past this 
TRB.

Interesting thing here is that each TRB in the queue after the transaction error
also triggers a transaction error.

This might be a data toggle/sequence number sync issue.
The host side endpoint reset clears the host side sequence number,
and host expects device side endpoint to be reset and sequence to be cleared as 
well
as a result of returning -EPROTO.
If I remember correctly xhci driver does not wait for device side endpoint to 
be reset,
so if there are  TRBs in the queue they will be transferred, with a cleared 
sequence number
out of sync with the device side.

There is a patch in usb-next that might help.
f8f80be xhci: Use soft retry to recover faster from transaction errors

It soft resets the halted host side endpoint, clears the halt without clearing 
the sequence number.

-Mathias


Re: EPROTO when USB 3 GbE adapters are under load

2018-10-25 Thread Mathias Nyman

On 25.10.2018 06:37, Hao Wei Tee wrote:

Hi,

There are multiple reports[1][2][3] (more elsewhere on the internet) of USB 3
GbE adapters throwing EPROTO errors on USB transfer especially when the devices
are under load. Both of the two common chipsets (Realtek RTL8153 (r8152[4]) and
Asix AX88179 (ax88179_178a[5])) seem to exhibit this behaviour.

[1]: https://bugzilla.kernel.org/show_bug.cgi?id=75381
[2]: https://bugzilla.kernel.org/show_bug.cgi?id=196747
[3]: https://bugzilla.kernel.org/show_bug.cgi?id=198931
[4]: 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/usb/r8152.c
[5]: 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/net/usb/ax88179_178a.c

I'm trying to figure out why this happens (while it doesn't seem to happen on
other OSes, but I'm not sure). I think it's unlikely that both drivers are 
buggy,
so perhaps it is something to do with the USB stack instead of the device 
drivers.

It wouldn't be surprising if both devices actually don't adhere to the USB specs
properly and other OSes are just more tolerant of that (?) but that is just
conjecture on my part.

Does anyone have any ideas?


Reproducing the issue with a recent kernel with xhci traces enabled should show 
the reason for EPROTO error.

Add xhci traces before triggering the issue with:

mount -t debugfs none /sys/kernel/debug
echo 81920 > /sys/kernel/debug/tracing/buffer_size_kb
echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/enable

after issue is triggered save and send the trace at 
/sys/kernel/debug/tracing/trace
Note that it might be huge

-Mathias



Re: USB hotplug on HP 255 G6 laptop

2018-10-16 Thread Mathias Nyman

On 16.10.2018 14:38, Jan Kara wrote:

On Wed 03-10-18 16:46:05, Jan Kara wrote:

On Wed 03-10-18 17:19:33, Mathias Nyman wrote:

On 02.10.2018 17:53, Jan Kara wrote:

On Tue 02-10-18 17:01:54, Mathias Nyman wrote:

On 02.10.2018 16:06, Jan Kara wrote:

Hello,

my wife has HP 255 G6 laptop. When it is attached to AC, everything works
as expected however when it is running on battery, USB hotplug stops
working - newly plugged devices do not appear to be visible to the kernel.
Only when the AC is plugged back in, the kernel suddently wakes up and
detects all newly attached devices. Maybe it is related to some power
management? Any idea how to debug this? Dmesg from the system is attached.
The kernels I've tested with (both behave the same way) are 4.18.11 kernel
and also openSUSE Leap 15 kernel which is 4.12-based. Thanks in advance for
any help.



Are you running laptop mode tools or similar that would enable runtime suspend
D3 state for xhci controller?


It is openSUSE Leap 15 installation with xfce4 desktop so I assume there is
some power-management going on. Not sure what I should look for but there's
xfce4-power-manager running, also upowerd is running.


what does lspci -vv say?


Attached.


check the content of the following files while running on battery:

cat /sys/bus/pci/devices/:00:10.0/firmware_node/power_state


D0


cat /sys/bus/pci/devices/:00:10.0/power/control


auto - when on battery, on - when on AC.


try: echo on > /sys/bus/pci/devices/:00:10.0/power/control
before pluggin in a usb device, does it help?


Yes, USB device gets recognized after this.



To me this looks like xhci is runtime suspended, but controller is still
in a PCI D0 state.

Normally the xHC should be put to PCI D3 in runtime suspend,  and woken
up by a PCI PME# when a device is plugged in, but PME# is not enabled in
D0 so in this case nothing wakes up the xHC.

The xhci runtime suspend code already stopped the controller, so probably
you're not getting an interrupt either.

PCI code looks at firmware ACPI tables to choose the suspend D state, if
something is off in the tables it's possible the wrong state is chosen.
worth checking.

Could you dump the DSDT ACPI table form /sys/firmware/acpi/tables/DSDT


Sure. Attached.


As a quick temporary workaround you could find and prevent the
powersaving program from enabling runtime suspend. (make sure it won't
write "auto" to /sys/bus/pci/devices/:00:10.0/power/control)


OK, thanks for the hint.


Any news here? Are really ACPI tables wrong on this laptop?



Can't say for sure

There might be differences how Windows and Linux parse ACPI tables.

If _PR0  or _PS0 is present for a device in ACPI tables then Linux will
assume the device is ACPI power manageable, and select PCI D states from ACPI 
tables.

_S3W should return the highest D-value (deepest sleep state) device can wake up 
from S3 (system suspend)
_S0W should return the highest D-value (deepest sleep state) device can wake up 
from S0 (Runtime suspend)

Your ACPI DSDT table shows:

Scope (_SB.PCI0.XHC0)
{
Name (_PR0, Package (0x01)  // _PR0: Power Resources for D0
{
P0U3
})
Name (_PR3, Package (0x01)  // _PR3: Power Resources for D3hot
{
P3U3
})
Method (_S0W, 0, NotSerialized)  // _S0W: S0 Device Wake State
{
If ((XHCD == One))
{
Return (0x04)
}
Else
{
Return (Zero)
}
}

Method (_S3W, 0, NotSerialized)  // _S3W: S3 Device Wake State
{
Return (0x04)
}


Those with better APCI and PCI knowledge might know more details, or better 
debugging for this,
but it at least would be possible to check which D state is chosen by adding 
the below code,
and recompiling the kernel:


diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index c2ab577..c9cb93a 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -501,6 +501,12 @@ static pci_power_t acpi_pci_choose_state(struct pci_dev 
*pdev)
else
d_max = ACPI_STATE_D3_COLD;
acpi_state = acpi_pm_device_sleep_state(>dev, NULL, d_max);
+
+   if (pdev->device == 0x31a8) {
+   dev_err(>dev, "HACK: device 0x%x: ACPI selected D%d state, 
Force D3\n",
+   pdev->device, acpi_state);
+   acpi_state = ACPI_STATE_D3_HOT;
+   }
if (acpi_state < 0)
return PCI_POWER_ERROR;

You need to change the "0x31a8" to whatever PCI ID your xhci controller has.
lspci -nn is your friend.

-Mathias


[PATCH 1/2] usb: xhci: tegra: Power-off power-domains on removal

2018-10-16 Thread Mathias Nyman
From: Jon Hunter 

Currently the XUSB power domains used by the Tegra xHCI controller are
never powered off on the removal of the driver, however, they will be
powered off on probe failure. Update the removal code to be consistent
with the probe failure path to power off the XUSB power domains.

Signed-off-by: Jon Hunter 
Acked-by: Thierry Reding 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-tegra.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index 4ee510a..920a50a 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -1249,6 +1249,11 @@ static int tegra_xusb_remove(struct platform_device 
*pdev)
pm_runtime_put_sync(>dev);
pm_runtime_disable(>dev);
 
+   if (!pdev->dev.pm_domain) {
+   tegra_powergate_power_off(TEGRA_POWERGATE_XUSBC);
+   tegra_powergate_power_off(TEGRA_POWERGATE_XUSBA);
+   }
+
tegra_xusb_padctl_put(tegra->padctl);
 
return 0;
-- 
2.7.4



[PATCH 0/2] xhci features for usb-next

2018-10-16 Thread Mathias Nyman
Hi Greg

These two patches are part 2/5 and 3/5 of the Tegra xhci genpd
support series.

It's how Jon Hunter proposed them to be merged:
" This series is making changes to more than one subsystem and at first
  glance may look like a maintainers nightmare. However, my proposal is
  this, once reviewed and people are happy ...
  1. Patches 1-3 should be merged first. Patches 1 can go via the Tegra
 tree and 2-3 via the USB tree.
  2. Once patches 1-3 are accepted, then 4 and 5 can be merged via the
   Tegra tree."

-Mathias

Jon Hunter (2):
  usb: xhci: tegra: Power-off power-domains on removal
  usb: xhci: tegra: Add genpd support

 drivers/usb/host/xhci-tegra.c | 92 +--
 1 file changed, 81 insertions(+), 11 deletions(-)

-- 
2.7.4



[PATCH 2/2] usb: xhci: tegra: Add genpd support

2018-10-16 Thread Mathias Nyman
From: Jon Hunter 

The generic power-domain framework has been updated to allow devices
that require more than one power-domain to create a new device for
each power-domain required and then link these new power-domain
devices to the consumer device.

Update the Tegra xHCI driver to use the new APIs provided by the
generic power-domain framework so we can use the generic power-domain
framework for managing the xHCI controllers power-domains. Please
note that to maintain backward compatibility with older device-tree
blobs these new generic power-domain APIs are only used if the
'power-domains' property is present and otherwise we fall back to
using the legacy Tegra APIs for managing the power-domains.

Signed-off-by: Jon Hunter 
Acked-by: Thierry Reding 
Reviewed-by: Ulf Hansson 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-tegra.c | 89 +--
 1 file changed, 77 insertions(+), 12 deletions(-)

diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index 920a50a..6b5db34 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -194,6 +195,11 @@ struct tegra_xusb {
struct reset_control *host_rst;
struct reset_control *ss_rst;
 
+   struct device *genpd_dev_host;
+   struct device *genpd_dev_ss;
+   struct device_link *genpd_dl_host;
+   struct device_link *genpd_dl_ss;
+
struct phy **phys;
unsigned int num_phys;
 
@@ -928,6 +934,57 @@ static int tegra_xusb_load_firmware(struct tegra_xusb 
*tegra)
return 0;
 }
 
+static void tegra_xusb_powerdomain_remove(struct device *dev,
+ struct tegra_xusb *tegra)
+{
+   if (tegra->genpd_dl_ss)
+   device_link_del(tegra->genpd_dl_ss);
+   if (tegra->genpd_dl_host)
+   device_link_del(tegra->genpd_dl_host);
+   if (tegra->genpd_dev_ss)
+   dev_pm_domain_detach(tegra->genpd_dev_ss, true);
+   if (tegra->genpd_dev_host)
+   dev_pm_domain_detach(tegra->genpd_dev_host, true);
+}
+
+static int tegra_xusb_powerdomain_init(struct device *dev,
+  struct tegra_xusb *tegra)
+{
+   int err;
+
+   tegra->genpd_dev_host = dev_pm_domain_attach_by_name(dev, "xusb_host");
+   if (IS_ERR(tegra->genpd_dev_host)) {
+   err = PTR_ERR(tegra->genpd_dev_host);
+   dev_err(dev, "failed to get host pm-domain: %d\n", err);
+   return err;
+   }
+
+   tegra->genpd_dev_ss = dev_pm_domain_attach_by_name(dev, "xusb_ss");
+   if (IS_ERR(tegra->genpd_dev_ss)) {
+   err = PTR_ERR(tegra->genpd_dev_ss);
+   dev_err(dev, "failed to get superspeed pm-domain: %d\n", err);
+   return err;
+   }
+
+   tegra->genpd_dl_host = device_link_add(dev, tegra->genpd_dev_host,
+  DL_FLAG_PM_RUNTIME |
+  DL_FLAG_STATELESS);
+   if (!tegra->genpd_dl_host) {
+   dev_err(dev, "adding host device link failed!\n");
+   return -ENODEV;
+   }
+
+   tegra->genpd_dl_ss = device_link_add(dev, tegra->genpd_dev_ss,
+DL_FLAG_PM_RUNTIME |
+DL_FLAG_STATELESS);
+   if (!tegra->genpd_dl_ss) {
+   dev_err(dev, "adding superspeed device link failed!\n");
+   return -ENODEV;
+   }
+
+   return 0;
+}
+
 static int tegra_xusb_probe(struct platform_device *pdev)
 {
struct tegra_xusb_mbox_msg msg;
@@ -1038,7 +1095,7 @@ static int tegra_xusb_probe(struct platform_device *pdev)
goto put_padctl;
}
 
-   if (!pdev->dev.pm_domain) {
+   if (!of_property_read_bool(pdev->dev.of_node, "power-domains")) {
tegra->host_rst = devm_reset_control_get(>dev,
 "xusb_host");
if (IS_ERR(tegra->host_rst)) {
@@ -1069,17 +1126,22 @@ static int tegra_xusb_probe(struct platform_device 
*pdev)
tegra->host_clk,
tegra->host_rst);
if (err) {
+   tegra_powergate_power_off(TEGRA_POWERGATE_XUSBA);
dev_err(>dev,
"failed to enable XUSBC domain: %d\n", err);
-   goto disable_xusba;
+   goto put_padctl;
}
+   } else {
+   err = tegra_xusb_powerdomai

Re: xHCI enable slot command if there are several ports connected

2018-10-10 Thread Mathias Nyman

On 09.10.2018 21:57, Alan Stern wrote:

On Tue, 9 Oct 2018, Dmitry Malkin wrote:


Hi guys,

Could someone can give me a hint to this question:

if there are multiple connected USB devices (multiple ports with set
PORTSC.CCS bit) to xHCI and I issue the very first enable slot command
which port will be "enabled"?


The "Enable slot" command name can be bit misleading, think of it more as
"obtain/request/allocate an empty slot from xHC hardware".
It's not enabling any port.

After this the xhci driver allocates a slot context for the slot.
Route String and other values need to be set to the slot context
before issuing an address device command.

-Mathias



I don't see anything regarding this in specification (also I cannot find
anything like this in linux xhci driver).


See the description of the Route String and the Root Hub Port Number
entries in the slot context.

Alan Stern


Motivation is just simple: if I run into situation where I need to reset
device through PORTSC how can I distinguish between different ports?







Re: USB hotplug on HP 255 G6 laptop

2018-10-03 Thread Mathias Nyman

On 02.10.2018 17:53, Jan Kara wrote:

On Tue 02-10-18 17:01:54, Mathias Nyman wrote:

On 02.10.2018 16:06, Jan Kara wrote:

Hello,

my wife has HP 255 G6 laptop. When it is attached to AC, everything works
as expected however when it is running on battery, USB hotplug stops
working - newly plugged devices do not appear to be visible to the kernel.
Only when the AC is plugged back in, the kernel suddently wakes up and
detects all newly attached devices. Maybe it is related to some power
management? Any idea how to debug this? Dmesg from the system is attached.
The kernels I've tested with (both behave the same way) are 4.18.11 kernel
and also openSUSE Leap 15 kernel which is 4.12-based. Thanks in advance for
any help.



Are you running laptop mode tools or similar that would enable runtime suspend
D3 state for xhci controller?


It is openSUSE Leap 15 installation with xfce4 desktop so I assume there is
some power-management going on. Not sure what I should look for but there's
xfce4-power-manager running, also upowerd is running.


what does lspci -vv say?


Attached.


check the content of the following files while running on battery:

cat /sys/bus/pci/devices/:00:10.0/firmware_node/power_state


D0


cat /sys/bus/pci/devices/:00:10.0/power/control


auto - when on battery, on - when on AC.


try: echo on > /sys/bus/pci/devices/:00:10.0/power/control
before pluggin in a usb device, does it help?


Yes, USB device gets recognized after this.



To me this looks like xhci is runtime suspended, but controller is still in a 
PCI D0 state.

Normally the xHC should be put to PCI D3 in runtime suspend,  and woken up by a 
PCI PME#
when a device is plugged in, but PME# is not enabled in D0 so in this case 
nothing wakes
up the xHC.

The xhci runtime suspend code already stopped the controller, so probably 
you're not
getting an interrupt either.

PCI code looks at firmware ACPI tables to choose the suspend D state, if 
something is off in the
tables it's possible the wrong state is chosen. worth checking.

Could you dump the DSDT ACPI table form /sys/firmware/acpi/tables/DSDT

As a quick temporary workaround you could find and prevent the powersaving 
program from enabling
runtime suspend. (make sure it won't write "auto" to 
/sys/bus/pci/devices/:00:10.0/power/control)

-Mathias


Re: USB hotplug on HP 255 G6 laptop

2018-10-02 Thread Mathias Nyman

On 02.10.2018 16:06, Jan Kara wrote:

Hello,

my wife has HP 255 G6 laptop. When it is attached to AC, everything works
as expected however when it is running on battery, USB hotplug stops
working - newly plugged devices do not appear to be visible to the kernel.
Only when the AC is plugged back in, the kernel suddently wakes up and
detects all newly attached devices. Maybe it is related to some power
management? Any idea how to debug this? Dmesg from the system is attached.
The kernels I've tested with (both behave the same way) are 4.18.11 kernel
and also openSUSE Leap 15 kernel which is 4.12-based. Thanks in advance for
any help.



Are you running laptop mode tools or similar that would enable runtime suspend
D3 state for xhci controller?

what does lspci -vv say?

check the content of the following files while running on battery:

cat /sys/bus/pci/devices/:00:10.0/firmware_node/power_state
cat /sys/bus/pci/devices/:00:10.0/power/control

try: echo on > /sys/bus/pci/devices/:00:10.0/power/control
before pluggin in a usb device, does it help?

cat /proc/acpi/wakeup  content could be useful

Also full dmesg including first plugging in the usb device, and then the AC 
power.
It will show if the connected devices are USB2 or USB3 devices, and if they are 
connected
to EHCI of xHC controller?

Thanks
Mathias




Re: USB ports on Thunderbolt 3 Dock always doesn't work after resume from suspend

2018-10-01 Thread Mathias Nyman

On 01.10.2018 10:17, Heikki Krogerus wrote:

+Mika, Mathias

On Sat, Sep 29, 2018 at 08:51:43AM +0200, Ondrej Holy wrote:

Hi,

I recently got new Lenovo Thinkpad T480s with the ThinkPad Thunderbolt
3 Dock. The USB ports (but probably also audio and ethernet) on the
dock always don't work after resume from suspend on up-to-date Fedora
29 with kernel-4.18.9-300.fc29.x86_64. HDMI port in the dock seems
works (but with some delay). It doesn't work even with latest
available kernel-4.19.0-0.rc5.git0.1.fc30.x86_64 from rawhide.
Replugging the dock usually helps to fix that issue.

Some probably relevant lines from dmesg after resume:
[ 6528.075126] xhci_hcd :0b:00.0: Refused to change power state,
currently in D3
[ 6528.075127] xhci_hcd :09:00.0: Refused to change power state,
currently in D3
[ 6528.075139] xhci_hcd :0b:00.0: WARN: xHC restore state timeout
[ 6528.075140] xhci_hcd :09:00.0: WARN: xHC restore state timeout
[ 6528.075140] xhci_hcd :0b:00.0: PCI post-resume error -110!
[ 6528.075141] xhci_hcd :09:00.0: PCI post-resume error -110!
[ 6528.075141] xhci_hcd :0b:00.0: HC died; cleaning up
[ 6528.075142] xhci_hcd :09:00.0: HC died; cleaning up
[ 6528.075150] dpm_run_callback(): pci_pm_resume+0x0/0xa0 returns -110
[ 6528.075153] dpm_run_callback(): pci_pm_resume+0x0/0xa0 returns -110
[ 6528.075155] PM: Device :0b:00.0 failed to resume async: error -110
[ 6528.075157] PM: Device :09:00.0 failed to resume async: error -110


xhci driver will react like this if the xHC host is not powered up after resume.
Log states it is still in D3 suspend state instead of D0.

I'm guessing there is some powermanagement issue for thunderbolt connected
PCI devices in resume, looking at dock firmware could be a good place to start.

-Mathias


Re: [RFT PATCH 2/2] xhci: handle port status events for removed USB3 hcd

2018-10-01 Thread Mathias Nyman

On 28.09.2018 21:10, Jack Pham wrote:

Hi Mathias,


Jack, Peter, do these patches solve the remove issues you are seeing?


At my two USB3 platforms, only apply the 1st patch can fix my problem.  Maybe
my USB3 port change interrupt occurs always before removing USB2 HCD.


It's possible yes.


Peter


Ditto. I think the xhci_irq() is getting triggered by something during
usb_remove_hcd() (usb_disconnect on the root hub?) but is able to
complete before it returns. That is, the NULL pointer dereference is
resolved yet I don't see that "ignore port event for removed USB3 hcd"
message at all.

Regardless, it's good to have here just in case, so
Tested-by: Jack Pham 

Will you be sending this as separate patches for -rc vs -stable?

Thanks,
Jack



Thanks, adding tested-by tags.

I'll send them to -rc with stable tag, and then later send a backported version
to older kernel once I have a upstream commit ID I can refer to.

Thanks
-Mathias


[PATCH v2 RESEND 2/3] usb: xhci-mtk: resume USB3 roothub first

2018-10-01 Thread Mathias Nyman
From: Chunfeng Yun 

Give USB3 devices a better chance to enumerate at USB3 speeds if
they are connected to a suspended host.
Porting from "671ffdff5b13 xhci: resume USB 3 roothub first"

Cc: 
Signed-off-by: Chunfeng Yun 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-mtk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index 7334da9..71d0d33 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -642,10 +642,10 @@ static int __maybe_unused xhci_mtk_resume(struct device 
*dev)
xhci_mtk_host_enable(mtk);
 
xhci_dbg(xhci, "%s: restart port polling\n", __func__);
-   set_bit(HCD_FLAG_POLL_RH, >flags);
-   usb_hcd_poll_rh_status(hcd);
set_bit(HCD_FLAG_POLL_RH, >shared_hcd->flags);
usb_hcd_poll_rh_status(xhci->shared_hcd);
+   set_bit(HCD_FLAG_POLL_RH, >flags);
+   usb_hcd_poll_rh_status(hcd);
return 0;
 }
 
-- 
2.7.4



Re: [PATCH v2 0/3] xhci fixes for usb-linus

2018-10-01 Thread Mathias Nyman

On 28.09.2018 15:51, Greg KH wrote:

On Thu, Sep 20, 2018 at 06:43:19PM +0300, Mathias Nyman wrote:

Hi Greg

Second try, shuffling patches between for-usb-linus and for-usb-next

A few patches that makes sure USB3 devices enumerate to correct speed
after resume on Mediatek hosts, enables role mux on Apollo lake platforms,
and adds the missing cold attach status (CAS) bit quirk to Intel Sunrise
Point xhci controllers.

Changes since v1

- Moved following patches from this series to for-usb-next (4.20)
   xhci: Avoid USB autosuspend when resuming USB2 ports.
   usb: xhci: tegra: Firmware header is little endian

- Added patches to this series from for-usb-next queue:
   usb: xhci-mtk: resume USB3 roothub first
   usb: typec: pci: Enable Intel USB role mux on Apollo Lake platforms

- Added stable tags

Chunfeng Yun (1):
   usb: xhci-mtk: resume USB3 roothub first

Heikki Krogerus (1):
   usb: typec: pci: Enable Intel USB role mux on Apollo Lake platforms

Mathias Nyman (1):
   xhci: Add missing CAS workaround for Intel Sunrise Point xHCI

  drivers/usb/host/xhci-mtk.c | 4 ++--
  drivers/usb/host/xhci-pci.c | 8 ++--
  2 files changed, 8 insertions(+), 4 deletions(-)


I only received 2 patches here, not 3, am I missing something on my end?

Can you resend all of these again?



Sure, resending

-Mathias



[PATCH v2 RESEND 3/3] usb: typec: pci: Enable Intel USB role mux on Apollo Lake platforms

2018-10-01 Thread Mathias Nyman
From: Heikki Krogerus 

Intel Apollo Lake has the same internal USB role mux as
Intel Cherry Trail.

Cc: 
Signed-off-by: Heikki Krogerus 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-pci.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 722860e..51dd8e0 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -179,10 +179,12 @@ static void xhci_pci_quirks(struct device *dev, struct 
xhci_hcd *xhci)
xhci->quirks |= XHCI_PME_STUCK_QUIRK;
}
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
-pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
+   pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)
xhci->quirks |= XHCI_SSIC_PORT_UNUSED;
+   if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+   (pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI))
xhci->quirks |= XHCI_INTEL_USB_ROLE_SW;
-   }
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
(pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
 pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
-- 
2.7.4



[PATCH v2 RESEND 1/3] xhci: Add missing CAS workaround for Intel Sunrise Point xHCI

2018-10-01 Thread Mathias Nyman
The workaround for missing CAS bit is also needed for xHC on Intel
sunrisepoint PCH. For more details see:

Intel 100/c230 series PCH specification update Doc #332692-006 Errata #8

Cc: 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-pci.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 6372edf..722860e 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -185,6 +185,8 @@ static void xhci_pci_quirks(struct device *dev, struct 
xhci_hcd *xhci)
}
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
(pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI ||
 pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI ||
 pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI))
xhci->quirks |= XHCI_MISSING_CAS;
-- 
2.7.4



[PATCH v2 RESEND 0/3] xhci fixes for usb-linus

2018-10-01 Thread Mathias Nyman
Hi Greg

Resending v2 due to lost patch 3/3
Second try, shuffling patches between for-usb-linus and for-usb-next

A few patches that makes sure USB3 devices enumerate to correct speed
after resume on Mediatek hosts, enables role mux on Apollo lake platforms,
and adds the missing cold attach status (CAS) bit quirk to Intel Sunrise
Point xhci controllers.

Changes since v1

- Moved following patches from this series to for-usb-next (4.20)
  xhci: Avoid USB autosuspend when resuming USB2 ports.
  usb: xhci: tegra: Firmware header is little endian

- Added patches to this series from for-usb-next queue:
  usb: xhci-mtk: resume USB3 roothub first
  usb: typec: pci: Enable Intel USB role mux on Apollo Lake platforms

- Added stable tags

Chunfeng Yun (1):
  usb: xhci-mtk: resume USB3 roothub first

Heikki Krogerus (1):
  usb: typec: pci: Enable Intel USB role mux on Apollo Lake platforms

Mathias Nyman (1):
  xhci: Add missing CAS workaround for Intel Sunrise Point xHCI

 drivers/usb/host/xhci-mtk.c | 4 ++--
 drivers/usb/host/xhci-pci.c | 8 ++--
 2 files changed, 8 insertions(+), 4 deletions(-)

-- 
2.7.4



Re: [RFT PATCH 2/2] xhci: handle port status events for removed USB3 hcd

2018-09-27 Thread Mathias Nyman

On 27.09.2018 19:26, Mathias Nyman wrote:

At xhci removal the USB3 hcd (shared_hcd) is removed before the primary
USB2 hcd. Interrupts for port status changes may still occur for USB3
ports after the shared_hcd is freed, causing  NULL pointer dereference.

Check if xhci->shared_hcd is still valid before handing USB3 port events

Cc: 
Reported-by: Peter Chen 
Signed-off-by: Mathias Nyman 
---
  drivers/usb/host/xhci-ring.c | 7 +++
  1 file changed, 7 insertions(+)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index f0a99aa..3d314b8 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1552,6 +1552,13 @@ static void handle_port_status(struct xhci_hcd *xhci,
goto cleanup;
}
  
+	/* We might get interrupts after shared_hcd is removed */

+   if (port->rhub == >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 = >bus_state[hcd_index(hcd)];
hcd_portnum = port->hcd_portnum;



This probably only applies from 4.18 onwards, to test on older kernel try 
something
like this instead:

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 6996235..7925da9 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1606,7 +1606,11 @@ static void handle_port_status(struct xhci_hcd *xhci,
hcd = xhci_to_hcd(xhci);
if ((major_revision == 0x03) != (hcd->speed >= HCD_USB3))
hcd = xhci->shared_hcd;
-
+   if (!hcd) {
+   bogus_port_status = true;
+   goto cleanup;
+   }
if (major_revision == 0) {
xhci_warn(xhci, "Event for port %u not in "
"Extended Capabilities, ignoring.\n",


Jack, Peter, do these patches solve the remove issues you are seeing?

Thanks
-Mathias


[RFT PATCH 2/2] xhci: handle port status events for removed USB3 hcd

2018-09-27 Thread Mathias Nyman
At xhci removal the USB3 hcd (shared_hcd) is removed before the primary
USB2 hcd. Interrupts for port status changes may still occur for USB3
ports after the shared_hcd is freed, causing  NULL pointer dereference.

Check if xhci->shared_hcd is still valid before handing USB3 port events

Cc: 
Reported-by: Peter Chen 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-ring.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index f0a99aa..3d314b8 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1552,6 +1552,13 @@ static void handle_port_status(struct xhci_hcd *xhci,
goto cleanup;
}
 
+   /* We might get interrupts after shared_hcd is removed */
+   if (port->rhub == >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 = >bus_state[hcd_index(hcd)];
hcd_portnum = port->hcd_portnum;
-- 
2.7.4



[RFT PATCH 1/2] xhci: Fix leaking USB3 shared_hcd at xhci removal

2018-09-27 Thread Mathias Nyman
Ensure that the shared_hcd pointer is valid when calling usb_put_hcd()

The shared_hcd is removed and freed in xhci by first calling
usb_remove_hcd(xhci->shared_hcd), and later
usb_put_hcd(xhci->shared_hcd)

Afer commit fe190ed0d602 ("xhci: Do not halt the host until both HCD have
disconnected their devices.") the shared_hcd was never properly put as
xhci->shared_hcd was set to NULL before usb_put_hcd(xhci->shared_hcd) was
called.

shared_hcd (USB3) is removed before primary hcd (USB2).
While removing the primary hcd we might need to handle xhci interrupts
to cleanly remove last USB2 devices, therefore we need to set
xhci->shared_hcd to NULL before removing the primary hcd to let xhci
interrupt handler know shared_hcd is no longer available.

xhci-plat.c, xhci-histb.c and xhci-mtk first create both their hcd's before
adding them. so to keep the correct reverse removal order use a temporary
shared_hcd variable for them.
For more details see commit 4ac53087d6d4 ("usb: xhci: plat: Create both
HCDs before adding them")

Fixes: fe190ed0d602 ("xhci: Do not halt the host until both HCD have 
disconnected their devices.")
Cc: Joel Stanley 
Cc: Chunfeng Yun 
Cc: Thierry Reding 
Cc: Jianguo Sun 
Cc: 
Reported-by: Jack Pham 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-histb.c | 6 --
 drivers/usb/host/xhci-mtk.c   | 6 --
 drivers/usb/host/xhci-pci.c   | 1 +
 drivers/usb/host/xhci-plat.c  | 6 --
 drivers/usb/host/xhci-tegra.c | 1 +
 drivers/usb/host/xhci.c   | 2 --
 6 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/drivers/usb/host/xhci-histb.c b/drivers/usb/host/xhci-histb.c
index 27f0016..3c4abb5 100644
--- a/drivers/usb/host/xhci-histb.c
+++ b/drivers/usb/host/xhci-histb.c
@@ -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);
 
usb_remove_hcd(hcd);
-   usb_put_hcd(xhci->shared_hcd);
+   usb_put_hcd(shared_hcd);
 
xhci_histb_host_disable(histb);
usb_put_hcd(hcd);
diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index 71d0d33..60987c7 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -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, 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);
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 51dd8e0..92fd6b6 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -356,6 +356,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 */
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 94e9392..e5da8ce 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -359,14 +359,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);
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index 4b463e5..b1cce98 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -1240,6 +1240,7 @@ static int tegra_xusb_remove(struct platform_device *pdev)
 
usb_remove_hcd(xhci->shared_hcd);
usb_put_hcd(xhci->shared_hcd);
+   xhci-&

Re: [PATCH 1/3] usb: host: xhci: fix oops when removing hcd

2018-09-26 Thread Mathias Nyman

Hi Jack, Peter

On 24.09.2018 19:37, Jack Pham wrote:

Hi Peter,

On Fri, Sep 21, 2018 at 09:48:43AM +0800, Peter Chen wrote:

Type-C-to-A cable, and the USB3 HCD has already been NULL at that time.
The oops log like below:

[681.782288] xhci-hcd xhci-hcd.1.auto: remove, state 1
[681.787490] usb usb4: USB disconnect, device number 1
[681.792808] usb 4-1: USB disconnect, device number 2
[681.818089] xhci-hcd xhci-hcd.1.auto: USB bus 4 deregistered
[681.823803] Unable to handle kernel NULL pointer dereference at virtual 
address 00a0
[681.823806] Mem abort info:
[681.823809]   Exception class = DABT (current EL), IL = 32 bits
[681.823811]   SET = 0, FnV = 0
[681.823813]   EA = 0, S1PTW = 0
[681.823814] Data abort info:
[681.823816]   ISV = 0, ISS = 0x0004
[681.823818]   CM = 0, WnR = 0
[681.823822] user pgtable: 4k pages, 48-bit VAs, pgd = 8000ae3fd000
[681.823824] [00a0] *pgd=
[681.823829] Internal error: Oops: 9604 [#1] PREEMPT SMP
[681.823832] Modules linked in: 8021q garp stp mrp crc32_ce qca6174(O) 
crct10dif_ce galcore(O)
[681.823849] CPU: 0 PID: 94 Comm: kworker/0:1 Tainted: G   O
4.14.62-imx_4.14.y+gcd63def #1
[681.823851] Hardware name: Freescale i.MX8MQ EVK (DT)
[681.823862] Workqueue: events_freezable __dwc3_set_mode
[681.823865] task: 8000b8a18000 task.stack: 0a01
[681.823872] PC is at xhci_irq+0x5fc/0x14b8
[681.823875] LR is at xhci_irq+0x3c/0x14b8





diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index f0a99aa0ac58..2dc5176b79d0 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2680,7 +2680,8 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
}
  
  	if (xhci->xhc_state & XHCI_STATE_DYING ||

-   xhci->xhc_state & XHCI_STATE_HALTED) {
+   xhci->xhc_state & XHCI_STATE_HALTED ||
+   xhci->xhc_state & XHCI_STATE_REMOVING) {
xhci_dbg(xhci, "xHCI dying, ignoring interrupt. "
"Shouldn't IRQs be disabled?\n");
/* Clear the event handler busy flag (RW1C);


We also noticed the same crash as you found, and tried to fix it in a
similar way, but noticed that this still allows a memory leak to happen.

It seems from commit fe190ed0d602a ("xhci: Do not halt the host until
both HCD have disconnected their devices.") this was added to
xhci_stop(), and is the reason we encounter the NULL pointer in
xhci_irq() when it tries to access xhci->shared_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(>mutex);
return;
}

While your fix will simply abort the xhci_irq() function if it
encounters XHCI_STATE_REMOVING, during xhci_plat_remove():

static int xhci_plat_remove(struct platform_device *dev)
{
struct usb_hcd  *hcd = platform_get_drvdata(dev);
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct clk *clk = xhci->clk;
struct clk *reg_clk = xhci->reg_clk;

xhci->xhc_state |= XHCI_STATE_REMOVING;

usb_remove_hcd(xhci->shared_hcd);
^ calls xhci_stop() and sets shared_hcd=NULL
usb_phy_shutdown(hcd->usb_phy);

usb_remove_hcd(hcd);
usb_put_hcd(xhci->shared_hcd);
^^^ shared_hcd==NULL, so this is a no-op

Since usb_put_hcd() doesn't get called for shared_hcd, we end up
with one additional kref count and hence a leak.


Nice catch,  this same issue exists in

xhci_pci_remove()
tegra_xusb_remove()
xhci_mtk_remove()
xhci_histb_remove()




Wondering if we need to also remove the xhci->shared_hcd = NULL from
xhci_stop(), in addition to your patches. Thoughts?


At some point the xhci->shared_hcd needs to be set NULL, it can be done in
in the xhci_plat_remove(), xhci_pci_remove() and the similar remove functions
after calling usb_remove_hcd(). we can't rely on xhci->shared_hcd after it
has been removed.

The xHC controller is stopped and interrupts disabled only after the primary
hcd (USB2) is removed, this is because usb core will try to cleanly flush last 
USB2
URBs and take down the last endpoints when the USB2 usb_remove_hcd(hcd) is 
called.
We need a running xHC controller to do this.

This means we can get interrupts we need to handle even if the shared_hcd is 
removed.
So I think we still need to handle interrupts even if XHCI_STATE_REMOVING flag 
is set.

I think we also need to make the xhci interrupt handler capable of handling 
situations
where xhci->shared_hcd is set to NULL

Does this sound reasonable?

-Mathias


[PATCH v2 07/10] xhci: Use soft retry to recover faster from transaction errors

2018-09-20 Thread Mathias Nyman
Use soft retry to recover from a USB Transaction Errors that are caused by
temporary error conditions. The USB device is not aware that the xHC
has halted the endpoint, and will be waiting for another retry

A Soft Retry perform additional retries and recover from an error which has
caused the xHC to halt an endpoint.

Soft retry has some limitations:
Soft Retry attempts shall not be performed on Isoch endpoints
Soft Retry attempts shall not be performed if the device is behind a TT in
a HS Hub

Software shall limit the number of unsuccessful Soft Retry attempts to
prevent an infinite loop.

For more details on Soft retry see xhci specs  4.6.8.1

Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-ring.c | 19 +++
 drivers/usb/host/xhci.h  |  2 ++
 2 files changed, 21 insertions(+)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index f0a99aa..c41341e 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1155,6 +1155,10 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd 
*xhci, int slot_id,
/* Clear our internal halted state */
xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_HALTED;
}
+
+   /* if this was a soft reset, then restart */
+   if ((le32_to_cpu(trb->generic.field[3])) & TRB_TSP)
+   ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
 }
 
 static void xhci_handle_cmd_enable_slot(struct xhci_hcd *xhci, int slot_id,
@@ -2132,10 +2136,16 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, 
struct xhci_td *td,
union xhci_trb *ep_trb, struct xhci_transfer_event *event,
struct xhci_virt_ep *ep, int *status)
 {
+   struct xhci_slot_ctx *slot_ctx;
struct xhci_ring *ep_ring;
u32 trb_comp_code;
u32 remaining, requested, ep_trb_len;
+   unsigned int slot_id;
+   int ep_index;
 
+   slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
+   slot_ctx = xhci_get_slot_ctx(xhci, xhci->devs[slot_id]->out_ctx);
+   ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1;
ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
remaining = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
@@ -2144,6 +2154,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, 
struct xhci_td *td,
 
switch (trb_comp_code) {
case COMP_SUCCESS:
+   ep_ring->err_count = 0;
/* handle success with untransferred data as short packet */
if (ep_trb != td->last_trb || remaining) {
xhci_warn(xhci, "WARN Successful completion on short 
TX\n");
@@ -2167,6 +2178,14 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, 
struct xhci_td *td,
ep_trb_len  = 0;
remaining   = 0;
break;
+   case COMP_USB_TRANSACTION_ERROR:
+   if ((ep_ring->err_count++ > MAX_SOFT_RETRY) ||
+   le32_to_cpu(slot_ctx->tt_info) & TT_SLOT)
+   break;
+   *status = 0;
+   xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index,
+   ep_ring->stream_id, td, EP_SOFT_RESET);
+   return 0;
default:
/* do nothing */
break;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 6230a57..b635785 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1496,6 +1496,7 @@ static inline const char *xhci_trb_type_string(u8 type)
 /* How much data is left before the 64KB boundary? */
 #define TRB_BUFF_LEN_UP_TO_BOUNDARY(addr)  (TRB_MAX_BUFF_SIZE - \
(addr & (TRB_MAX_BUFF_SIZE - 1)))
+#define MAX_SOFT_RETRY 3
 
 struct xhci_segment {
union xhci_trb  *trbs;
@@ -1583,6 +1584,7 @@ struct xhci_ring {
 * if we own the TRB (if we are the consumer).  See section 4.9.1.
 */
u32 cycle_state;
+   unsigned interr_count;
unsigned intstream_id;
unsigned intnum_segs;
unsigned intnum_trbs_free;
-- 
2.7.4



[PATCH v2 03/10] usb: xhci-mtk: improve bandwidth scheduling

2018-09-20 Thread Mathias Nyman
From: Chunfeng Yun 

Mainly improve SuperSpeed ISOC bandwidth in last microframe,
and LowSpeed/FullSpeed IN INT/ISOC bandwidth in split and
idle microframes by introduing a bandwidth budget table;

Signed-off-by: Chunfeng Yun 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-mtk-sch.c | 162 +---
 drivers/usb/host/xhci-mtk.h |   2 +
 2 files changed, 104 insertions(+), 60 deletions(-)

diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
index 057f453..7efd890 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
@@ -18,6 +18,11 @@
 #define HS_BW_BOUNDARY 6144
 /* usb2 spec section11.18.1: at most 188 FS bytes per microframe */
 #define FS_PAYLOAD_MAX 188
+/*
+ * max number of microframes for split transfer,
+ * for fs isoc in : 1 ss + 1 idle + 7 cs
+ */
+#define TT_MICROFRAMES_MAX 9
 
 /* mtk scheduler bitmasks */
 #define EP_BPKTS(p)((p) & 0x3f)
@@ -64,20 +69,57 @@ static int get_bw_index(struct xhci_hcd *xhci, struct 
usb_device *udev,
return bw_index;
 }
 
+static u32 get_esit(struct xhci_ep_ctx *ep_ctx)
+{
+   u32 esit;
+
+   esit = 1 << CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx->ep_info));
+   if (esit > XHCI_MTK_MAX_ESIT)
+   esit = XHCI_MTK_MAX_ESIT;
+
+   return esit;
+}
+
+static struct mu3h_sch_ep_info *create_sch_ep(struct usb_device *udev,
+   struct usb_host_endpoint *ep, struct xhci_ep_ctx *ep_ctx)
+{
+   struct mu3h_sch_ep_info *sch_ep;
+   u32 len_bw_budget_table;
+   size_t mem_size;
+
+   if (is_fs_or_ls(udev->speed))
+   len_bw_budget_table = TT_MICROFRAMES_MAX;
+   else if ((udev->speed == USB_SPEED_SUPER)
+   && usb_endpoint_xfer_isoc(>desc))
+   len_bw_budget_table = get_esit(ep_ctx);
+   else
+   len_bw_budget_table = 1;
+
+   mem_size = sizeof(struct mu3h_sch_ep_info) +
+   len_bw_budget_table * sizeof(u32);
+   sch_ep = kzalloc(mem_size, GFP_KERNEL);
+   if (!sch_ep)
+   return ERR_PTR(-ENOMEM);
+
+   sch_ep->ep = ep;
+
+   return sch_ep;
+}
+
 static void setup_sch_info(struct usb_device *udev,
struct xhci_ep_ctx *ep_ctx, struct mu3h_sch_ep_info *sch_ep)
 {
u32 ep_type;
-   u32 ep_interval;
-   u32 max_packet_size;
+   u32 maxpkt;
u32 max_burst;
u32 mult;
u32 esit_pkts;
u32 max_esit_payload;
+   u32 *bwb_table = sch_ep->bw_budget_table;
+   int i;
 
ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2));
-   ep_interval = CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx->ep_info));
-   max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
+   maxpkt = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
max_burst = CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx->ep_info2));
mult = CTX_TO_EP_MULT(le32_to_cpu(ep_ctx->ep_info));
max_esit_payload =
@@ -85,9 +127,10 @@ static void setup_sch_info(struct usb_device *udev,
le32_to_cpu(ep_ctx->ep_info)) << 16) |
 CTX_TO_MAX_ESIT_PAYLOAD(le32_to_cpu(ep_ctx->tx_info));
 
-   sch_ep->esit = 1 << ep_interval;
+   sch_ep->esit = get_esit(ep_ctx);
sch_ep->offset = 0;
sch_ep->burst_mode = 0;
+   sch_ep->repeat = 0;
 
if (udev->speed == USB_SPEED_HIGH) {
sch_ep->cs_count = 0;
@@ -98,7 +141,6 @@ static void setup_sch_info(struct usb_device *udev,
 * in a interval
 */
sch_ep->num_budget_microframes = 1;
-   sch_ep->repeat = 0;
 
/*
 * xHCI spec section6.2.3.4
@@ -106,26 +148,30 @@ static void setup_sch_info(struct usb_device *udev,
 * opportunities per microframe
 */
sch_ep->pkts = max_burst + 1;
-   sch_ep->bw_cost_per_microframe = max_packet_size * sch_ep->pkts;
+   sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
+   bwb_table[0] = sch_ep->bw_cost_per_microframe;
} else if (udev->speed == USB_SPEED_SUPER) {
/* usb3_r1 spec section4.4.7 & 4.4.8 */
sch_ep->cs_count = 0;
+   sch_ep->burst_mode = 1;
/*
 * some device's (d)wBytesPerInterval is set as 0,
 * then max_esit_payload is 0, so evaluate esit_pkts from
 * mult and burst
 */
-   esit_pkts = DIV_ROUND_UP(max_esit_payload, max_packet_size);
+   esit_pkts = DIV_ROUND_UP(max_esit_payload, maxpkt);
if (esit_pkts == 0)
esit_pkts = (mult + 1) * (max_burst + 1);
 
if (ep_type == INT_IN_EP || 

[PATCH v2 00/10] xhci features for usb-next

2018-09-20 Thread Mathias Nyman
Hi Greg

Second try, shuffling patches.

A few new features for xhci, among others better transaction error
handling, default runtime PM allowing for Intel Alpine and Tiran Ridge
xhci controllers, and Mediatek isoc transfer related xhci improvements.

Changes since v1

- moved following patches from this series to for-usb-linus (4.19)
  usb: xhci-mtk: resume USB3 roothub first
  usb: typec: pci: Enable Intel USB role mux on Apollo Lake platforms

- added patches to this series from for-usb-linus queue:
  xhci: Avoid USB autosuspend when resuming USB2 ports.
  usb: xhci: tegra: Firmware header is little endian

-Mathias

Anshuman Gupta (1):
  xhci: Avoid USB autosuspend when resuming USB2 ports.

Chunfeng Yun (5):
  usb: xhci-mtk: use maximum ESIT payload of endpiont context
  usb: xhci-mtk: fix ISOC error when interval is zero
  usb: xhci-mtk: improve bandwidth scheduling
  usb: xhci-mtk: supports bandwidth scheduling with multi-TT
  usb: xhci-mtk: supports SSP without external USB3 gen2 hub

Mathias Nyman (2):
  xhci: Use soft retry to recover faster from transaction errors
  xhci-pci: allow host runtime PM as default for Intel Alpine and Titan
Ridge

Peter Chen (1):
  usb: host: xhci-plat: add platform TPL support

Thierry Reding (1):
  usb: xhci: tegra: Firmware header is little endian

 drivers/usb/host/xhci-hub.c |   5 +
 drivers/usb/host/xhci-mtk-sch.c | 429 +---
 drivers/usb/host/xhci-mtk.h |  23 +++
 drivers/usb/host/xhci-pci.c |  24 +++
 drivers/usb/host/xhci-plat.c|   3 +
 drivers/usb/host/xhci-ring.c|  20 ++
 drivers/usb/host/xhci-tegra.c   |  52 ++---
 drivers/usb/host/xhci.h |   3 +
 8 files changed, 463 insertions(+), 96 deletions(-)

-- 
2.7.4



[PATCH v2 09/10] usb: xhci: tegra: Firmware header is little endian

2018-09-20 Thread Mathias Nyman
From: Thierry Reding 

The XUSB firmware header is in little endian byte order, so make the
fields __le32 and __le16 instead of u32 and u16 to avoid warnings from
sparse when the fields are used with the endian-aware __le32_to_cpu()
and __le16_to_cpu() accessors, respectively.

Signed-off-by: Thierry Reding 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-tegra.c | 52 +--
 1 file changed, 26 insertions(+), 26 deletions(-)

diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index 4b463e5..4ee510a 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -107,35 +107,35 @@
 #define IMEM_BLOCK_SIZE256
 
 struct tegra_xusb_fw_header {
-   u32 boot_loadaddr_in_imem;
-   u32 boot_codedfi_offset;
-   u32 boot_codetag;
-   u32 boot_codesize;
-   u32 phys_memaddr;
-   u16 reqphys_memsize;
-   u16 alloc_phys_memsize;
-   u32 rodata_img_offset;
-   u32 rodata_section_start;
-   u32 rodata_section_end;
-   u32 main_fnaddr;
-   u32 fwimg_cksum;
-   u32 fwimg_created_time;
-   u32 imem_resident_start;
-   u32 imem_resident_end;
-   u32 idirect_start;
-   u32 idirect_end;
-   u32 l2_imem_start;
-   u32 l2_imem_end;
-   u32 version_id;
+   __le32 boot_loadaddr_in_imem;
+   __le32 boot_codedfi_offset;
+   __le32 boot_codetag;
+   __le32 boot_codesize;
+   __le32 phys_memaddr;
+   __le16 reqphys_memsize;
+   __le16 alloc_phys_memsize;
+   __le32 rodata_img_offset;
+   __le32 rodata_section_start;
+   __le32 rodata_section_end;
+   __le32 main_fnaddr;
+   __le32 fwimg_cksum;
+   __le32 fwimg_created_time;
+   __le32 imem_resident_start;
+   __le32 imem_resident_end;
+   __le32 idirect_start;
+   __le32 idirect_end;
+   __le32 l2_imem_start;
+   __le32 l2_imem_end;
+   __le32 version_id;
u8 init_ddirect;
u8 reserved[3];
-   u32 phys_addr_log_buffer;
-   u32 total_log_entries;
-   u32 dequeue_ptr;
-   u32 dummy_var[2];
-   u32 fwimg_len;
+   __le32 phys_addr_log_buffer;
+   __le32 total_log_entries;
+   __le32 dequeue_ptr;
+   __le32 dummy_var[2];
+   __le32 fwimg_len;
u8 magic[8];
-   u32 ss_low_power_entry_timeout;
+   __le32 ss_low_power_entry_timeout;
u8 num_hsic_port;
u8 padding[139]; /* Pad to 256 bytes */
 };
-- 
2.7.4



[PATCH v2 01/10] usb: xhci-mtk: use maximum ESIT payload of endpiont context

2018-09-20 Thread Mathias Nyman
From: Chunfeng Yun 

Make use of maximum ESIT payload of endpoint context to calculate
the number of packets to send in each ESIT

Signed-off-by: Chunfeng Yun 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-mtk-sch.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
index fa33d6e..46fe0a2 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
@@ -73,12 +73,17 @@ static void setup_sch_info(struct usb_device *udev,
u32 max_burst;
u32 mult;
u32 esit_pkts;
+   u32 max_esit_payload;
 
ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2));
ep_interval = CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx->ep_info));
max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
max_burst = CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx->ep_info2));
mult = CTX_TO_EP_MULT(le32_to_cpu(ep_ctx->ep_info));
+   max_esit_payload =
+   (CTX_TO_MAX_ESIT_PAYLOAD_HI(
+   le32_to_cpu(ep_ctx->ep_info)) << 16) |
+CTX_TO_MAX_ESIT_PAYLOAD(le32_to_cpu(ep_ctx->tx_info));
 
sch_ep->esit = 1 << ep_interval;
sch_ep->offset = 0;
@@ -105,7 +110,15 @@ static void setup_sch_info(struct usb_device *udev,
} else if (udev->speed == USB_SPEED_SUPER) {
/* usb3_r1 spec section4.4.7 & 4.4.8 */
sch_ep->cs_count = 0;
-   esit_pkts = (mult + 1) * (max_burst + 1);
+   /*
+* some device's (d)wBytesPerInterval is set as 0,
+* then max_esit_payload is 0, so evaluate esit_pkts from
+* mult and burst
+*/
+   esit_pkts = DIV_ROUND_UP(max_esit_payload, max_packet_size);
+   if (esit_pkts == 0)
+   esit_pkts = (mult + 1) * (max_burst + 1);
+
if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) {
sch_ep->pkts = esit_pkts;
sch_ep->num_budget_microframes = 1;
-- 
2.7.4



[PATCH v2 10/10] xhci: Avoid USB autosuspend when resuming USB2 ports.

2018-09-20 Thread Mathias Nyman
From: Anshuman Gupta 

When USB bus host controller root hub resumes from autosuspend,
it immediately tries to enter auto-suspend, but there can be a
scenario when root hub is resuming its usb2 ports, in that particular
case USB host controller auto suspend fails since it is busy
to resuming its usb2 ports.

This makes multiple failed cycles of auto-suspend until all usb2
ports of host controller root hub do not resume.

This patch uses USB core framework usb_hcd_start_port_resume,
usb_hcd_end_port_resume API's in order to  autoresume/autosuspend
root hub properly.

Signed-off-by: Anshuman Gupta 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-hub.c  | 5 +
 drivers/usb/host/xhci-ring.c | 1 +
 2 files changed, 6 insertions(+)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 7e2a531..12eea73 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -900,6 +900,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
set_bit(wIndex, _state->resuming_ports);
bus_state->resume_done[wIndex] = timeout;
mod_timer(>rh_timer, timeout);
+   usb_hcd_start_port_resume(>self, wIndex);
}
/* Has resume been signalled for USB_RESUME_TIME yet? */
} else if (time_after_eq(jiffies,
@@ -940,6 +941,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
clear_bit(wIndex, _state->rexit_ports);
}
 
+   usb_hcd_end_port_resume(>self, wIndex);
bus_state->port_c_suspend |= 1 << wIndex;
bus_state->suspended_ports &= ~(1 << wIndex);
} else {
@@ -962,6 +964,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
(raw_port_status & PORT_PLS_MASK) != XDEV_RESUME) {
bus_state->resume_done[wIndex] = 0;
clear_bit(wIndex, _state->resuming_ports);
+   usb_hcd_end_port_resume(>self, wIndex);
}
 
 
@@ -1337,6 +1340,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, 
u16 wValue,
goto error;
 
set_bit(wIndex, _state->resuming_ports);
+   usb_hcd_start_port_resume(>self, wIndex);
xhci_set_link_state(xhci, ports[wIndex],
XDEV_RESUME);
spin_unlock_irqrestore(>lock, flags);
@@ -1345,6 +1349,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, 
u16 wValue,
xhci_set_link_state(xhci, ports[wIndex],
XDEV_U0);
clear_bit(wIndex, _state->resuming_ports);
+   usb_hcd_end_port_resume(>self, wIndex);
}
bus_state->port_c_suspend |= 1 << wIndex;
 
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index c41341e..a8d92c9 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1606,6 +1606,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
set_bit(HCD_FLAG_POLL_RH, >flags);
mod_timer(>rh_timer,
  bus_state->resume_done[hcd_portnum]);
+   usb_hcd_start_port_resume(>self, hcd_portnum);
bogus_port_status = true;
}
}
-- 
2.7.4



[PATCH v2 08/10] xhci-pci: allow host runtime PM as default for Intel Alpine and Titan Ridge

2018-09-20 Thread Mathias Nyman
The xhci controller on Alpine and Titan Ridge keeps the whole thunderbolt
awake if the host controller is not allowed tp sleep.
This is the case even if no USB devices are connected to the host.

Because of this bigger impact, allow runtime pm as default for these xhci
controllers in the driver.

Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-pci.c | 24 
 drivers/usb/host/xhci.h |  1 +
 2 files changed, 25 insertions(+)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 6372edf..9433e70 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -41,6 +41,13 @@
 #define PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI 0x1aa8
 #define PCI_DEVICE_ID_INTEL_APL_XHCI   0x5aa8
 #define PCI_DEVICE_ID_INTEL_DNV_XHCI   0x19d0
+#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_XHCI   0x15b5
+#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_XHCI   0x15b6
+#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_XHCI 0x15db
+#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_4C_XHCI 0x15d4
+#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_XHCI0x15e9
+#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_XHCI0x15ec
+#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI0x15f0
 
 #define PCI_DEVICE_ID_AMD_PROMONTORYA_40x43b9
 #define PCI_DEVICE_ID_AMD_PROMONTORYA_30x43ba
@@ -189,6 +196,16 @@ static void xhci_pci_quirks(struct device *dev, struct 
xhci_hcd *xhci)
 pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI))
xhci->quirks |= XHCI_MISSING_CAS;
 
+   if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+   (pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_4C_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI))
+   xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
+
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
pdev->device == PCI_DEVICE_ID_EJ168) {
xhci->quirks |= XHCI_RESET_ON_RESUME;
@@ -332,6 +349,9 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct 
pci_device_id *id)
/* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */
pm_runtime_put_noidle(>dev);
 
+   if (xhci->quirks & XHCI_DEFAULT_PM_RUNTIME_ALLOW)
+   pm_runtime_allow(>dev);
+
return 0;
 
 put_usb3_hcd:
@@ -349,6 +369,10 @@ static void xhci_pci_remove(struct pci_dev *dev)
 
xhci = hcd_to_xhci(pci_get_drvdata(dev));
xhci->xhc_state |= XHCI_STATE_REMOVING;
+
+   if (xhci->quirks & XHCI_DEFAULT_PM_RUNTIME_ALLOW)
+   pm_runtime_forbid(>dev);
+
if (xhci->shared_hcd) {
usb_remove_hcd(xhci->shared_hcd);
usb_put_hcd(xhci->shared_hcd);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index b635785..bf0b369 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1848,6 +1848,7 @@ struct xhci_hcd {
 #define XHCI_SUSPEND_DELAY BIT_ULL(30)
 #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)
 
unsigned intnum_active_eps;
unsigned intlimit_active_eps;
-- 
2.7.4



[PATCH v2 02/10] usb: xhci-mtk: fix ISOC error when interval is zero

2018-09-20 Thread Mathias Nyman
From: Chunfeng Yun 

If the interval equal zero, needn't round up to power of two
for the number of packets in each ESIT, so fix it.

Signed-off-by: Chunfeng Yun 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-mtk-sch.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
index 46fe0a2..057f453 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
@@ -126,7 +126,9 @@ static void setup_sch_info(struct usb_device *udev,
}
 
if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) {
-   if (esit_pkts <= sch_ep->esit)
+   if (sch_ep->esit == 1)
+   sch_ep->pkts = esit_pkts;
+   else if (esit_pkts <= sch_ep->esit)
sch_ep->pkts = 1;
else
sch_ep->pkts = roundup_pow_of_two(esit_pkts)
-- 
2.7.4



[PATCH v2 06/10] usb: host: xhci-plat: add platform TPL support

2018-09-20 Thread Mathias Nyman
From: Peter Chen 

The TPL support is used to identify targeted devices during
EH2.0 and EH3.0 certification test, the user can add "tpl-support"
at dts to enable this feature.

Signed-off-by: Peter Chen 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-plat.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 94e9392..32b5574 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "xhci.h"
 #include "xhci-plat.h"
@@ -305,6 +306,8 @@ static int xhci_plat_probe(struct platform_device *pdev)
hcd->skip_phy_initialization = 1;
}
 
+   hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node);
+   xhci->shared_hcd->tpl_support = hcd->tpl_support;
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (ret)
goto disable_usb_phy;
-- 
2.7.4



[PATCH v2 04/10] usb: xhci-mtk: supports bandwidth scheduling with multi-TT

2018-09-20 Thread Mathias Nyman
From: Chunfeng Yun 

Supports LowSpeed and FullSpeed INT/ISOC bandwidth scheduling
with USB multi-TT

Signed-off-by: Chunfeng Yun 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-mtk-sch.c | 247 ++--
 drivers/usb/host/xhci-mtk.h |  21 
 2 files changed, 258 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
index 7efd890..36050a1 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
@@ -80,10 +80,98 @@ static u32 get_esit(struct xhci_ep_ctx *ep_ctx)
return esit;
 }
 
+static struct mu3h_sch_tt *find_tt(struct usb_device *udev)
+{
+   struct usb_tt *utt = udev->tt;
+   struct mu3h_sch_tt *tt, **tt_index, **ptt;
+   unsigned int port;
+   bool allocated_index = false;
+
+   if (!utt)
+   return NULL;/* Not below a TT */
+
+   /*
+* Find/create our data structure.
+* For hubs with a single TT, we get it directly.
+* For hubs with multiple TTs, there's an extra level of pointers.
+*/
+   tt_index = NULL;
+   if (utt->multi) {
+   tt_index = utt->hcpriv;
+   if (!tt_index) {/* Create the index array */
+   tt_index = kcalloc(utt->hub->maxchild,
+   sizeof(*tt_index), GFP_KERNEL);
+   if (!tt_index)
+   return ERR_PTR(-ENOMEM);
+   utt->hcpriv = tt_index;
+   allocated_index = true;
+   }
+   port = udev->ttport - 1;
+   ptt = _index[port];
+   } else {
+   port = 0;
+   ptt = (struct mu3h_sch_tt **) >hcpriv;
+   }
+
+   tt = *ptt;
+   if (!tt) {  /* Create the mu3h_sch_tt */
+   tt = kzalloc(sizeof(*tt), GFP_KERNEL);
+   if (!tt) {
+   if (allocated_index) {
+   utt->hcpriv = NULL;
+   kfree(tt_index);
+   }
+   return ERR_PTR(-ENOMEM);
+   }
+   INIT_LIST_HEAD(>ep_list);
+   tt->usb_tt = utt;
+   tt->tt_port = port;
+   *ptt = tt;
+   }
+
+   return tt;
+}
+
+/* Release the TT above udev, if it's not in use */
+static void drop_tt(struct usb_device *udev)
+{
+   struct usb_tt *utt = udev->tt;
+   struct mu3h_sch_tt *tt, **tt_index, **ptt;
+   int i, cnt;
+
+   if (!utt || !utt->hcpriv)
+   return; /* Not below a TT, or never allocated */
+
+   cnt = 0;
+   if (utt->multi) {
+   tt_index = utt->hcpriv;
+   ptt = _index[udev->ttport - 1];
+   /*  How many entries are left in tt_index? */
+   for (i = 0; i < utt->hub->maxchild; ++i)
+   cnt += !!tt_index[i];
+   } else {
+   tt_index = NULL;
+   ptt = (struct mu3h_sch_tt **)>hcpriv;
+   }
+
+   tt = *ptt;
+   if (!tt || !list_empty(>ep_list))
+   return; /* never allocated , or still in use*/
+
+   *ptt = NULL;
+   kfree(tt);
+
+   if (cnt == 1) {
+   utt->hcpriv = NULL;
+   kfree(tt_index);
+   }
+}
+
 static struct mu3h_sch_ep_info *create_sch_ep(struct usb_device *udev,
struct usb_host_endpoint *ep, struct xhci_ep_ctx *ep_ctx)
 {
struct mu3h_sch_ep_info *sch_ep;
+   struct mu3h_sch_tt *tt = NULL;
u32 len_bw_budget_table;
size_t mem_size;
 
@@ -101,6 +189,15 @@ static struct mu3h_sch_ep_info *create_sch_ep(struct 
usb_device *udev,
if (!sch_ep)
return ERR_PTR(-ENOMEM);
 
+   if (is_fs_or_ls(udev->speed)) {
+   tt = find_tt(udev);
+   if (IS_ERR(tt)) {
+   kfree(sch_ep);
+   return ERR_PTR(-ENOMEM);
+   }
+   }
+
+   sch_ep->sch_tt = tt;
sch_ep->ep = ep;
 
return sch_ep;
@@ -128,6 +225,8 @@ static void setup_sch_info(struct usb_device *udev,
 CTX_TO_MAX_ESIT_PAYLOAD(le32_to_cpu(ep_ctx->tx_info));
 
sch_ep->esit = get_esit(ep_ctx);
+   sch_ep->ep_type = ep_type;
+   sch_ep->maxpkt = maxpkt;
sch_ep->offset = 0;
sch_ep->burst_mode = 0;
sch_ep->repeat = 0;
@@ -197,8 +296,13 @@ static void setup_sch_info(struct usb_device *udev,
}
} else if (is_fs_or_ls(udev->speed)) {
sch_ep->pkts = 1; /* at most one packet for each microframe */
+
+   /*
+* num_budget_microframes and cs_count will be updated when
+* check TT for INT_OUT_EP, ISOC/INT_IN_EP type
+ 

[PATCH v2 05/10] usb: xhci-mtk: supports SSP without external USB3 gen2 hub

2018-09-20 Thread Mathias Nyman
From: Chunfeng Yun 

Supports SSP scheduling only for SSP device directly connected
to root hub but not through external USB3 gen2 hub which need
use a new scheduling way.

Signed-off-by: Chunfeng Yun 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-mtk-sch.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
index 36050a1..fea 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
@@ -13,6 +13,7 @@
 #include "xhci.h"
 #include "xhci-mtk.h"
 
+#define SSP_BW_BOUNDARY13
 #define SS_BW_BOUNDARY 51000
 /* table 5-5. High-speed Isoc Transaction Limits in usb_20 spec */
 #define HS_BW_BOUNDARY 6144
@@ -25,7 +26,7 @@
 #define TT_MICROFRAMES_MAX 9
 
 /* mtk scheduler bitmasks */
-#define EP_BPKTS(p)((p) & 0x3f)
+#define EP_BPKTS(p)((p) & 0x7f)
 #define EP_BCSCOUNT(p) (((p) & 0x7) << 8)
 #define EP_BBM(p)  ((p) << 11)
 #define EP_BOFFSET(p)  ((p) & 0x3fff)
@@ -56,7 +57,7 @@ static int get_bw_index(struct xhci_hcd *xhci, struct 
usb_device *udev,
 
virt_dev = xhci->devs[udev->slot_id];
 
-   if (udev->speed == USB_SPEED_SUPER) {
+   if (udev->speed >= USB_SPEED_SUPER) {
if (usb_endpoint_dir_out(>desc))
bw_index = (virt_dev->real_port - 1) * 2;
else
@@ -177,7 +178,7 @@ static struct mu3h_sch_ep_info *create_sch_ep(struct 
usb_device *udev,
 
if (is_fs_or_ls(udev->speed))
len_bw_budget_table = TT_MICROFRAMES_MAX;
-   else if ((udev->speed == USB_SPEED_SUPER)
+   else if ((udev->speed >= USB_SPEED_SUPER)
&& usb_endpoint_xfer_isoc(>desc))
len_bw_budget_table = get_esit(ep_ctx);
else
@@ -249,7 +250,7 @@ static void setup_sch_info(struct usb_device *udev,
sch_ep->pkts = max_burst + 1;
sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
bwb_table[0] = sch_ep->bw_cost_per_microframe;
-   } else if (udev->speed == USB_SPEED_SUPER) {
+   } else if (udev->speed >= USB_SPEED_SUPER) {
/* usb3_r1 spec section4.4.7 & 4.4.8 */
sch_ep->cs_count = 0;
sch_ep->burst_mode = 1;
@@ -511,8 +512,12 @@ static int check_sch_bw(struct usb_device *udev,
break;
}
 
-   bw_boundary = (udev->speed == USB_SPEED_SUPER)
-   ? SS_BW_BOUNDARY : HS_BW_BOUNDARY;
+   if (udev->speed == USB_SPEED_SUPER_PLUS)
+   bw_boundary = SSP_BW_BOUNDARY;
+   else if (udev->speed == USB_SPEED_SUPER)
+   bw_boundary = SS_BW_BOUNDARY;
+   else
+   bw_boundary = HS_BW_BOUNDARY;
 
/* check bandwidth */
if (min_bw > bw_boundary)
-- 
2.7.4



[PATCH v2 3/3] usb: typec: pci: Enable Intel USB role mux on Apollo Lake platforms

2018-09-20 Thread Mathias Nyman
From: Heikki Krogerus 

Intel Apollo Lake has the same internal USB role mux as
Intel Cherry Trail.

Cc: 
Signed-off-by: Heikki Krogerus 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-pci.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 722860e..51dd8e0 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -179,10 +179,12 @@ static void xhci_pci_quirks(struct device *dev, struct 
xhci_hcd *xhci)
xhci->quirks |= XHCI_PME_STUCK_QUIRK;
}
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
-pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
+   pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)
xhci->quirks |= XHCI_SSIC_PORT_UNUSED;
+   if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+   (pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI))
xhci->quirks |= XHCI_INTEL_USB_ROLE_SW;
-   }
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
(pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
 pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
-- 
2.7.4



[PATCH v2 0/3] xhci fixes for usb-linus

2018-09-20 Thread Mathias Nyman
Hi Greg

Second try, shuffling patches between for-usb-linus and for-usb-next

A few patches that makes sure USB3 devices enumerate to correct speed
after resume on Mediatek hosts, enables role mux on Apollo lake platforms,
and adds the missing cold attach status (CAS) bit quirk to Intel Sunrise
Point xhci controllers.

Changes since v1

- Moved following patches from this series to for-usb-next (4.20)
  xhci: Avoid USB autosuspend when resuming USB2 ports.
  usb: xhci: tegra: Firmware header is little endian

- Added patches to this series from for-usb-next queue:
  usb: xhci-mtk: resume USB3 roothub first
  usb: typec: pci: Enable Intel USB role mux on Apollo Lake platforms

- Added stable tags

Chunfeng Yun (1):
  usb: xhci-mtk: resume USB3 roothub first

Heikki Krogerus (1):
  usb: typec: pci: Enable Intel USB role mux on Apollo Lake platforms

Mathias Nyman (1):
  xhci: Add missing CAS workaround for Intel Sunrise Point xHCI

 drivers/usb/host/xhci-mtk.c | 4 ++--
 drivers/usb/host/xhci-pci.c | 8 ++--
 2 files changed, 8 insertions(+), 4 deletions(-)

-- 
2.7.4



[PATCH v2 2/3] usb: xhci-mtk: resume USB3 roothub first

2018-09-20 Thread Mathias Nyman
From: Chunfeng Yun 

Give USB3 devices a better chance to enumerate at USB3 speeds if
they are connected to a suspended host.
Porting from "671ffdff5b13 xhci: resume USB 3 roothub first"

Cc: 
Signed-off-by: Chunfeng Yun 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-mtk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index 7334da9..71d0d33 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -642,10 +642,10 @@ static int __maybe_unused xhci_mtk_resume(struct device 
*dev)
xhci_mtk_host_enable(mtk);
 
xhci_dbg(xhci, "%s: restart port polling\n", __func__);
-   set_bit(HCD_FLAG_POLL_RH, >flags);
-   usb_hcd_poll_rh_status(hcd);
set_bit(HCD_FLAG_POLL_RH, >shared_hcd->flags);
usb_hcd_poll_rh_status(xhci->shared_hcd);
+   set_bit(HCD_FLAG_POLL_RH, >flags);
+   usb_hcd_poll_rh_status(hcd);
return 0;
 }
 
-- 
2.7.4



[PATCH v2 1/3] xhci: Add missing CAS workaround for Intel Sunrise Point xHCI

2018-09-20 Thread Mathias Nyman
The workaround for missing CAS bit is also needed for xHC on Intel
sunrisepoint PCH. For more details see:

Intel 100/c230 series PCH specification update Doc #332692-006 Errata #8

Cc: 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-pci.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 6372edf..722860e 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -185,6 +185,8 @@ static void xhci_pci_quirks(struct device *dev, struct 
xhci_hcd *xhci)
}
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
(pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI ||
 pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI ||
 pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI))
xhci->quirks |= XHCI_MISSING_CAS;
-- 
2.7.4



Re: [PATCH 2/3] xhci: Avoid USB autosuspend when resuming USB2 ports.

2018-09-17 Thread Mathias Nyman

On 14.09.2018 16:00, Greg KH wrote:

On Fri, Sep 14, 2018 at 03:33:30PM +0300, Mathias Nyman wrote:

From: Anshuman Gupta 

When USB bus host controller root hub resumes from autosuspend,
it immediately tries to enter auto-suspend, but there can be a
scenario when root hub is resuming its usb2 ports, in that particular
case USB host controller auto suspend fails since it is busy
to resuming its usb2 ports.

This makes multiple failed cycles of auto-suspend until all usb2
ports of host controller root hub do not resume.

This patch uses USB core framework usb_hcd_start_port_resume,
usb_hcd_end_port_resume API's in order to  autoresume/autosuspend
root hub properly.

Signed-off-by: Anshuman Gupta 
Signed-off-by: Mathias Nyman 


Not needed in stable?  Does this fix a specific commit?

thanks,

greg k-h



This improves a bad initial design that prevented autosuspend by
returning -EBUSY in xhci_bus_suspend() if a usb2 port was resuming.

Instead increment usage count on the roothub to prevent pm from polling
xhci_bus_suspend(). This is also what EHCI does.

I'm not sure If this fixes a actual bug for Anshuman Gupta caused by
the -EBUSY polling,(4.19 +stable), or if this is just a improvement in
suspend/resume code for xhci (4.20).

Anshuman Gupta, any comments?

-Mathias


Re: [PATCH 07/10] usb: typec: pci: Enable Intel USB role mux on Apollo Lake platforms

2018-09-17 Thread Mathias Nyman

On 14.09.2018 16:27, Greg KH wrote:

On Thu, Sep 13, 2018 at 03:24:00PM +0300, Mathias Nyman wrote:

From: Heikki Krogerus 

Intel Apollo Lake has the same internal USB role mux as
Intel Cherry Trail.

Signed-off-by: Heikki Krogerus 
Signed-off-by: Mathias Nyman 
---
  drivers/usb/host/xhci-pci.c | 6 --
  1 file changed, 4 insertions(+), 2 deletions(-)


Why is this not a 4.19-final patch?  Stable?



This wasn't urgent in any way according to Heikki, so
I queued it for linux-next. But both are fine.

But Stable would make sense.

-Mathias


Re: [PATCH 3/3] xhci: Add missing CAS workaround for Intel Sunrise Point xHCI

2018-09-17 Thread Mathias Nyman

On 14.09.2018 16:01, Greg KH wrote:

On Fri, Sep 14, 2018 at 03:33:31PM +0300, Mathias Nyman wrote:

The workaround for missing CAS bit is also needed for xHC on Intel
sunrisepoint PCH. For more details see:

Intel 100/c230 series PCH specification update Doc #332692-006 Errata #8

Signed-off-by: Mathias Nyman 
---
  drivers/usb/host/xhci-pci.c | 2 ++
  1 file changed, 2 insertions(+)


No stable tree tagging?



Sorry, my bad, this should go to stable as well.

-Mathias


Re: [PATCH 01/10] usb: xhci-mtk: resume USB3 roothub first

2018-09-17 Thread Mathias Nyman

On 14.09.2018 16:27, Greg KH wrote:

On Thu, Sep 13, 2018 at 03:23:54PM +0300, Mathias Nyman wrote:

From: Chunfeng Yun 

Give USB3 devices a better chance to enumerate at USB3 speeds if
they are connected to a suspended host.
Porting from "671ffdff5b13 xhci: resume USB 3 roothub first"

Signed-off-by: Chunfeng Yun 
Signed-off-by: Mathias Nyman 
---
  drivers/usb/host/xhci-mtk.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)


Isn't this a bugfix for 4.19-final?  And maybe for stable?



This was part of a 6 patch series that mostly contained mediatek
bandwidth scheduling improvements.

But I agree, this first one could go to 4.19 with stable flag.

-Mathias



[PATCH 3/3] xhci: Add missing CAS workaround for Intel Sunrise Point xHCI

2018-09-14 Thread Mathias Nyman
The workaround for missing CAS bit is also needed for xHC on Intel
sunrisepoint PCH. For more details see:

Intel 100/c230 series PCH specification update Doc #332692-006 Errata #8

Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-pci.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 6372edf..722860e 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -185,6 +185,8 @@ static void xhci_pci_quirks(struct device *dev, struct 
xhci_hcd *xhci)
}
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
(pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI ||
 pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI ||
 pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI))
xhci->quirks |= XHCI_MISSING_CAS;
-- 
2.7.4



[PATCH 0/3] xhci fixes for usb-linus

2018-09-14 Thread Mathias Nyman
Hi Greg

A few xhci fixes for usb-linus, two powermanagenet related tunings, and one
xhci tegra sparse warning fix.

-Mathias

Anshuman Gupta (1):
  xhci: Avoid USB autosuspend when resuming USB2 ports.

Mathias Nyman (1):
  xhci: Add missing CAS workaround for Intel Sunrise Point xHCI

Thierry Reding (1):
  usb: xhci: tegra: Firmware header is little endian

 drivers/usb/host/xhci-hub.c   |  5 +
 drivers/usb/host/xhci-pci.c   |  2 ++
 drivers/usb/host/xhci-ring.c  |  1 +
 drivers/usb/host/xhci-tegra.c | 52 +--
 4 files changed, 34 insertions(+), 26 deletions(-)

-- 
2.7.4



[PATCH 2/3] xhci: Avoid USB autosuspend when resuming USB2 ports.

2018-09-14 Thread Mathias Nyman
From: Anshuman Gupta 

When USB bus host controller root hub resumes from autosuspend,
it immediately tries to enter auto-suspend, but there can be a
scenario when root hub is resuming its usb2 ports, in that particular
case USB host controller auto suspend fails since it is busy
to resuming its usb2 ports.

This makes multiple failed cycles of auto-suspend until all usb2
ports of host controller root hub do not resume.

This patch uses USB core framework usb_hcd_start_port_resume,
usb_hcd_end_port_resume API's in order to  autoresume/autosuspend
root hub properly.

Signed-off-by: Anshuman Gupta 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-hub.c  | 5 +
 drivers/usb/host/xhci-ring.c | 1 +
 2 files changed, 6 insertions(+)

diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 7e2a531..12eea73 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -900,6 +900,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
set_bit(wIndex, _state->resuming_ports);
bus_state->resume_done[wIndex] = timeout;
mod_timer(>rh_timer, timeout);
+   usb_hcd_start_port_resume(>self, wIndex);
}
/* Has resume been signalled for USB_RESUME_TIME yet? */
} else if (time_after_eq(jiffies,
@@ -940,6 +941,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
clear_bit(wIndex, _state->rexit_ports);
}
 
+   usb_hcd_end_port_resume(>self, wIndex);
bus_state->port_c_suspend |= 1 << wIndex;
bus_state->suspended_ports &= ~(1 << wIndex);
} else {
@@ -962,6 +964,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,
(raw_port_status & PORT_PLS_MASK) != XDEV_RESUME) {
bus_state->resume_done[wIndex] = 0;
clear_bit(wIndex, _state->resuming_ports);
+   usb_hcd_end_port_resume(>self, wIndex);
}
 
 
@@ -1337,6 +1340,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, 
u16 wValue,
goto error;
 
set_bit(wIndex, _state->resuming_ports);
+   usb_hcd_start_port_resume(>self, wIndex);
xhci_set_link_state(xhci, ports[wIndex],
XDEV_RESUME);
spin_unlock_irqrestore(>lock, flags);
@@ -1345,6 +1349,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, 
u16 wValue,
xhci_set_link_state(xhci, ports[wIndex],
XDEV_U0);
clear_bit(wIndex, _state->resuming_ports);
+   usb_hcd_end_port_resume(>self, wIndex);
}
bus_state->port_c_suspend |= 1 << wIndex;
 
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index f0a99aa..cd46597 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1602,6 +1602,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
set_bit(HCD_FLAG_POLL_RH, >flags);
mod_timer(>rh_timer,
  bus_state->resume_done[hcd_portnum]);
+   usb_hcd_start_port_resume(>self, hcd_portnum);
bogus_port_status = true;
}
}
-- 
2.7.4



[PATCH 1/3] usb: xhci: tegra: Firmware header is little endian

2018-09-14 Thread Mathias Nyman
From: Thierry Reding 

The XUSB firmware header is in little endian byte order, so make the
fields __le32 and __le16 instead of u32 and u16 to avoid warnings from
sparse when the fields are used with the endian-aware __le32_to_cpu()
and __le16_to_cpu() accessors, respectively.

Signed-off-by: Thierry Reding 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-tegra.c | 52 +--
 1 file changed, 26 insertions(+), 26 deletions(-)

diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index 4b463e5..4ee510a 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -107,35 +107,35 @@
 #define IMEM_BLOCK_SIZE256
 
 struct tegra_xusb_fw_header {
-   u32 boot_loadaddr_in_imem;
-   u32 boot_codedfi_offset;
-   u32 boot_codetag;
-   u32 boot_codesize;
-   u32 phys_memaddr;
-   u16 reqphys_memsize;
-   u16 alloc_phys_memsize;
-   u32 rodata_img_offset;
-   u32 rodata_section_start;
-   u32 rodata_section_end;
-   u32 main_fnaddr;
-   u32 fwimg_cksum;
-   u32 fwimg_created_time;
-   u32 imem_resident_start;
-   u32 imem_resident_end;
-   u32 idirect_start;
-   u32 idirect_end;
-   u32 l2_imem_start;
-   u32 l2_imem_end;
-   u32 version_id;
+   __le32 boot_loadaddr_in_imem;
+   __le32 boot_codedfi_offset;
+   __le32 boot_codetag;
+   __le32 boot_codesize;
+   __le32 phys_memaddr;
+   __le16 reqphys_memsize;
+   __le16 alloc_phys_memsize;
+   __le32 rodata_img_offset;
+   __le32 rodata_section_start;
+   __le32 rodata_section_end;
+   __le32 main_fnaddr;
+   __le32 fwimg_cksum;
+   __le32 fwimg_created_time;
+   __le32 imem_resident_start;
+   __le32 imem_resident_end;
+   __le32 idirect_start;
+   __le32 idirect_end;
+   __le32 l2_imem_start;
+   __le32 l2_imem_end;
+   __le32 version_id;
u8 init_ddirect;
u8 reserved[3];
-   u32 phys_addr_log_buffer;
-   u32 total_log_entries;
-   u32 dequeue_ptr;
-   u32 dummy_var[2];
-   u32 fwimg_len;
+   __le32 phys_addr_log_buffer;
+   __le32 total_log_entries;
+   __le32 dequeue_ptr;
+   __le32 dummy_var[2];
+   __le32 fwimg_len;
u8 magic[8];
-   u32 ss_low_power_entry_timeout;
+   __le32 ss_low_power_entry_timeout;
u8 num_hsic_port;
u8 padding[139]; /* Pad to 256 bytes */
 };
-- 
2.7.4



[PATCH 04/10] usb: xhci-mtk: improve bandwidth scheduling

2018-09-13 Thread Mathias Nyman
From: Chunfeng Yun 

Mainly improve SuperSpeed ISOC bandwidth in last microframe,
and LowSpeed/FullSpeed IN INT/ISOC bandwidth in split and
idle microframes by introduing a bandwidth budget table;

Signed-off-by: Chunfeng Yun 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-mtk-sch.c | 162 +---
 drivers/usb/host/xhci-mtk.h |   2 +
 2 files changed, 104 insertions(+), 60 deletions(-)

diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
index 057f453..7efd890 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
@@ -18,6 +18,11 @@
 #define HS_BW_BOUNDARY 6144
 /* usb2 spec section11.18.1: at most 188 FS bytes per microframe */
 #define FS_PAYLOAD_MAX 188
+/*
+ * max number of microframes for split transfer,
+ * for fs isoc in : 1 ss + 1 idle + 7 cs
+ */
+#define TT_MICROFRAMES_MAX 9
 
 /* mtk scheduler bitmasks */
 #define EP_BPKTS(p)((p) & 0x3f)
@@ -64,20 +69,57 @@ static int get_bw_index(struct xhci_hcd *xhci, struct 
usb_device *udev,
return bw_index;
 }
 
+static u32 get_esit(struct xhci_ep_ctx *ep_ctx)
+{
+   u32 esit;
+
+   esit = 1 << CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx->ep_info));
+   if (esit > XHCI_MTK_MAX_ESIT)
+   esit = XHCI_MTK_MAX_ESIT;
+
+   return esit;
+}
+
+static struct mu3h_sch_ep_info *create_sch_ep(struct usb_device *udev,
+   struct usb_host_endpoint *ep, struct xhci_ep_ctx *ep_ctx)
+{
+   struct mu3h_sch_ep_info *sch_ep;
+   u32 len_bw_budget_table;
+   size_t mem_size;
+
+   if (is_fs_or_ls(udev->speed))
+   len_bw_budget_table = TT_MICROFRAMES_MAX;
+   else if ((udev->speed == USB_SPEED_SUPER)
+   && usb_endpoint_xfer_isoc(>desc))
+   len_bw_budget_table = get_esit(ep_ctx);
+   else
+   len_bw_budget_table = 1;
+
+   mem_size = sizeof(struct mu3h_sch_ep_info) +
+   len_bw_budget_table * sizeof(u32);
+   sch_ep = kzalloc(mem_size, GFP_KERNEL);
+   if (!sch_ep)
+   return ERR_PTR(-ENOMEM);
+
+   sch_ep->ep = ep;
+
+   return sch_ep;
+}
+
 static void setup_sch_info(struct usb_device *udev,
struct xhci_ep_ctx *ep_ctx, struct mu3h_sch_ep_info *sch_ep)
 {
u32 ep_type;
-   u32 ep_interval;
-   u32 max_packet_size;
+   u32 maxpkt;
u32 max_burst;
u32 mult;
u32 esit_pkts;
u32 max_esit_payload;
+   u32 *bwb_table = sch_ep->bw_budget_table;
+   int i;
 
ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2));
-   ep_interval = CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx->ep_info));
-   max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
+   maxpkt = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
max_burst = CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx->ep_info2));
mult = CTX_TO_EP_MULT(le32_to_cpu(ep_ctx->ep_info));
max_esit_payload =
@@ -85,9 +127,10 @@ static void setup_sch_info(struct usb_device *udev,
le32_to_cpu(ep_ctx->ep_info)) << 16) |
 CTX_TO_MAX_ESIT_PAYLOAD(le32_to_cpu(ep_ctx->tx_info));
 
-   sch_ep->esit = 1 << ep_interval;
+   sch_ep->esit = get_esit(ep_ctx);
sch_ep->offset = 0;
sch_ep->burst_mode = 0;
+   sch_ep->repeat = 0;
 
if (udev->speed == USB_SPEED_HIGH) {
sch_ep->cs_count = 0;
@@ -98,7 +141,6 @@ static void setup_sch_info(struct usb_device *udev,
 * in a interval
 */
sch_ep->num_budget_microframes = 1;
-   sch_ep->repeat = 0;
 
/*
 * xHCI spec section6.2.3.4
@@ -106,26 +148,30 @@ static void setup_sch_info(struct usb_device *udev,
 * opportunities per microframe
 */
sch_ep->pkts = max_burst + 1;
-   sch_ep->bw_cost_per_microframe = max_packet_size * sch_ep->pkts;
+   sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
+   bwb_table[0] = sch_ep->bw_cost_per_microframe;
} else if (udev->speed == USB_SPEED_SUPER) {
/* usb3_r1 spec section4.4.7 & 4.4.8 */
sch_ep->cs_count = 0;
+   sch_ep->burst_mode = 1;
/*
 * some device's (d)wBytesPerInterval is set as 0,
 * then max_esit_payload is 0, so evaluate esit_pkts from
 * mult and burst
 */
-   esit_pkts = DIV_ROUND_UP(max_esit_payload, max_packet_size);
+   esit_pkts = DIV_ROUND_UP(max_esit_payload, maxpkt);
if (esit_pkts == 0)
esit_pkts = (mult + 1) * (max_burst + 1);
 
if (ep_type == INT_IN_EP || 

[PATCH 10/10] xhci-pci: allow host runtime PM as default for Intel Alpine and Titan Ridge

2018-09-13 Thread Mathias Nyman
The xhci controller on Alpine and Titan Ridge keeps the whole thunderbolt
awake if the host controller is not allowed tp sleep.
This is the case even if no USB devices are connected to the host.

Because of this bigger impact, allow runtime pm as default for these xhci
controllers in the driver.

Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-pci.c | 24 
 drivers/usb/host/xhci.h |  1 +
 2 files changed, 25 insertions(+)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index aef66ad..213af17 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -41,6 +41,13 @@
 #define PCI_DEVICE_ID_INTEL_BROXTON_B_XHCI 0x1aa8
 #define PCI_DEVICE_ID_INTEL_APL_XHCI   0x5aa8
 #define PCI_DEVICE_ID_INTEL_DNV_XHCI   0x19d0
+#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_XHCI   0x15b5
+#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_XHCI   0x15b6
+#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_XHCI 0x15db
+#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_4C_XHCI 0x15d4
+#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_XHCI0x15e9
+#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_XHCI0x15ec
+#define PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI0x15f0
 
 #define PCI_DEVICE_ID_AMD_PROMONTORYA_40x43b9
 #define PCI_DEVICE_ID_AMD_PROMONTORYA_30x43ba
@@ -191,6 +198,16 @@ static void xhci_pci_quirks(struct device *dev, struct 
xhci_hcd *xhci)
 pdev->device == PCI_DEVICE_ID_INTEL_DNV_XHCI))
xhci->quirks |= XHCI_MISSING_CAS;
 
+   if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+   (pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_4C_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_TITAN_RIDGE_2C_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_TITAN_RIDGE_DD_XHCI))
+   xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
+
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
pdev->device == PCI_DEVICE_ID_EJ168) {
xhci->quirks |= XHCI_RESET_ON_RESUME;
@@ -334,6 +351,9 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct 
pci_device_id *id)
/* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */
pm_runtime_put_noidle(>dev);
 
+   if (xhci->quirks & XHCI_DEFAULT_PM_RUNTIME_ALLOW)
+   pm_runtime_allow(>dev);
+
return 0;
 
 put_usb3_hcd:
@@ -351,6 +371,10 @@ static void xhci_pci_remove(struct pci_dev *dev)
 
xhci = hcd_to_xhci(pci_get_drvdata(dev));
xhci->xhc_state |= XHCI_STATE_REMOVING;
+
+   if (xhci->quirks & XHCI_DEFAULT_PM_RUNTIME_ALLOW)
+   pm_runtime_forbid(>dev);
+
if (xhci->shared_hcd) {
usb_remove_hcd(xhci->shared_hcd);
usb_put_hcd(xhci->shared_hcd);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index b635785..bf0b369 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1848,6 +1848,7 @@ struct xhci_hcd {
 #define XHCI_SUSPEND_DELAY BIT_ULL(30)
 #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)
 
unsigned intnum_active_eps;
unsigned intlimit_active_eps;
-- 
2.7.4



[PATCH 06/10] usb: xhci-mtk: supports SSP without external USB3 gen2 hub

2018-09-13 Thread Mathias Nyman
From: Chunfeng Yun 

Supports SSP scheduling only for SSP device directly connected
to root hub but not through external USB3 gen2 hub which need
use a new scheduling way.

Signed-off-by: Chunfeng Yun 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-mtk-sch.c | 17 +++--
 1 file changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
index 36050a1..fea 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
@@ -13,6 +13,7 @@
 #include "xhci.h"
 #include "xhci-mtk.h"
 
+#define SSP_BW_BOUNDARY13
 #define SS_BW_BOUNDARY 51000
 /* table 5-5. High-speed Isoc Transaction Limits in usb_20 spec */
 #define HS_BW_BOUNDARY 6144
@@ -25,7 +26,7 @@
 #define TT_MICROFRAMES_MAX 9
 
 /* mtk scheduler bitmasks */
-#define EP_BPKTS(p)((p) & 0x3f)
+#define EP_BPKTS(p)((p) & 0x7f)
 #define EP_BCSCOUNT(p) (((p) & 0x7) << 8)
 #define EP_BBM(p)  ((p) << 11)
 #define EP_BOFFSET(p)  ((p) & 0x3fff)
@@ -56,7 +57,7 @@ static int get_bw_index(struct xhci_hcd *xhci, struct 
usb_device *udev,
 
virt_dev = xhci->devs[udev->slot_id];
 
-   if (udev->speed == USB_SPEED_SUPER) {
+   if (udev->speed >= USB_SPEED_SUPER) {
if (usb_endpoint_dir_out(>desc))
bw_index = (virt_dev->real_port - 1) * 2;
else
@@ -177,7 +178,7 @@ static struct mu3h_sch_ep_info *create_sch_ep(struct 
usb_device *udev,
 
if (is_fs_or_ls(udev->speed))
len_bw_budget_table = TT_MICROFRAMES_MAX;
-   else if ((udev->speed == USB_SPEED_SUPER)
+   else if ((udev->speed >= USB_SPEED_SUPER)
&& usb_endpoint_xfer_isoc(>desc))
len_bw_budget_table = get_esit(ep_ctx);
else
@@ -249,7 +250,7 @@ static void setup_sch_info(struct usb_device *udev,
sch_ep->pkts = max_burst + 1;
sch_ep->bw_cost_per_microframe = maxpkt * sch_ep->pkts;
bwb_table[0] = sch_ep->bw_cost_per_microframe;
-   } else if (udev->speed == USB_SPEED_SUPER) {
+   } else if (udev->speed >= USB_SPEED_SUPER) {
/* usb3_r1 spec section4.4.7 & 4.4.8 */
sch_ep->cs_count = 0;
sch_ep->burst_mode = 1;
@@ -511,8 +512,12 @@ static int check_sch_bw(struct usb_device *udev,
break;
}
 
-   bw_boundary = (udev->speed == USB_SPEED_SUPER)
-   ? SS_BW_BOUNDARY : HS_BW_BOUNDARY;
+   if (udev->speed == USB_SPEED_SUPER_PLUS)
+   bw_boundary = SSP_BW_BOUNDARY;
+   else if (udev->speed == USB_SPEED_SUPER)
+   bw_boundary = SS_BW_BOUNDARY;
+   else
+   bw_boundary = HS_BW_BOUNDARY;
 
/* check bandwidth */
if (min_bw > bw_boundary)
-- 
2.7.4



[PATCH 08/10] usb: host: xhci-plat: add platform TPL support

2018-09-13 Thread Mathias Nyman
From: Peter Chen 

The TPL support is used to identify targeted devices during
EH2.0 and EH3.0 certification test, the user can add "tpl-support"
at dts to enable this feature.

Signed-off-by: Peter Chen 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-plat.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 8dc77e3..1924ffd 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "xhci.h"
 #include "xhci-plat.h"
@@ -300,6 +301,8 @@ static int xhci_plat_probe(struct platform_device *pdev)
hcd->skip_phy_initialization = 1;
}
 
+   hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node);
+   xhci->shared_hcd->tpl_support = hcd->tpl_support;
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (ret)
goto disable_usb_phy;
-- 
2.7.4



[PATCH 09/10] xhci: Use soft retry to recover faster from transaction errors

2018-09-13 Thread Mathias Nyman
Use soft retry to recover from a USB Transaction Errors that are caused by
temporary error conditions. The USB device is not aware that the xHC
has halted the endpoint, and will be waiting for another retry

A Soft Retry perform additional retries and recover from an error which has
caused the xHC to halt an endpoint.

Soft retry has some limitations:
Soft Retry attempts shall not be performed on Isoch endpoints
Soft Retry attempts shall not be performed if the device is behind a TT in
a HS Hub

Software shall limit the number of unsuccessful Soft Retry attempts to
prevent an infinite loop.

For more details on Soft retry see xhci specs  4.6.8.1

Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-ring.c | 19 +++
 drivers/usb/host/xhci.h  |  2 ++
 2 files changed, 21 insertions(+)

diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index f0a99aa..c41341e 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1155,6 +1155,10 @@ static void xhci_handle_cmd_reset_ep(struct xhci_hcd 
*xhci, int slot_id,
/* Clear our internal halted state */
xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_HALTED;
}
+
+   /* if this was a soft reset, then restart */
+   if ((le32_to_cpu(trb->generic.field[3])) & TRB_TSP)
+   ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
 }
 
 static void xhci_handle_cmd_enable_slot(struct xhci_hcd *xhci, int slot_id,
@@ -2132,10 +2136,16 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, 
struct xhci_td *td,
union xhci_trb *ep_trb, struct xhci_transfer_event *event,
struct xhci_virt_ep *ep, int *status)
 {
+   struct xhci_slot_ctx *slot_ctx;
struct xhci_ring *ep_ring;
u32 trb_comp_code;
u32 remaining, requested, ep_trb_len;
+   unsigned int slot_id;
+   int ep_index;
 
+   slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
+   slot_ctx = xhci_get_slot_ctx(xhci, xhci->devs[slot_id]->out_ctx);
+   ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1;
ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
remaining = EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
@@ -2144,6 +2154,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, 
struct xhci_td *td,
 
switch (trb_comp_code) {
case COMP_SUCCESS:
+   ep_ring->err_count = 0;
/* handle success with untransferred data as short packet */
if (ep_trb != td->last_trb || remaining) {
xhci_warn(xhci, "WARN Successful completion on short 
TX\n");
@@ -2167,6 +2178,14 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, 
struct xhci_td *td,
ep_trb_len  = 0;
remaining   = 0;
break;
+   case COMP_USB_TRANSACTION_ERROR:
+   if ((ep_ring->err_count++ > MAX_SOFT_RETRY) ||
+   le32_to_cpu(slot_ctx->tt_info) & TT_SLOT)
+   break;
+   *status = 0;
+   xhci_cleanup_halted_endpoint(xhci, slot_id, ep_index,
+   ep_ring->stream_id, td, EP_SOFT_RESET);
+   return 0;
default:
/* do nothing */
break;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 6230a57..b635785 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1496,6 +1496,7 @@ static inline const char *xhci_trb_type_string(u8 type)
 /* How much data is left before the 64KB boundary? */
 #define TRB_BUFF_LEN_UP_TO_BOUNDARY(addr)  (TRB_MAX_BUFF_SIZE - \
(addr & (TRB_MAX_BUFF_SIZE - 1)))
+#define MAX_SOFT_RETRY 3
 
 struct xhci_segment {
union xhci_trb  *trbs;
@@ -1583,6 +1584,7 @@ struct xhci_ring {
 * if we own the TRB (if we are the consumer).  See section 4.9.1.
 */
u32 cycle_state;
+   unsigned interr_count;
unsigned intstream_id;
unsigned intnum_segs;
unsigned intnum_trbs_free;
-- 
2.7.4



[PATCH 07/10] usb: typec: pci: Enable Intel USB role mux on Apollo Lake platforms

2018-09-13 Thread Mathias Nyman
From: Heikki Krogerus 

Intel Apollo Lake has the same internal USB role mux as
Intel Cherry Trail.

Signed-off-by: Heikki Krogerus 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-pci.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 6372edf..aef66ad 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -179,10 +179,12 @@ static void xhci_pci_quirks(struct device *dev, struct 
xhci_hcd *xhci)
xhci->quirks |= XHCI_PME_STUCK_QUIRK;
}
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
-pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
+   pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)
xhci->quirks |= XHCI_SSIC_PORT_UNUSED;
+   if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+   (pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
+pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI))
xhci->quirks |= XHCI_INTEL_USB_ROLE_SW;
-   }
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
(pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
 pdev->device == PCI_DEVICE_ID_INTEL_APL_XHCI ||
-- 
2.7.4



[PATCH 05/10] usb: xhci-mtk: supports bandwidth scheduling with multi-TT

2018-09-13 Thread Mathias Nyman
From: Chunfeng Yun 

Supports LowSpeed and FullSpeed INT/ISOC bandwidth scheduling
with USB multi-TT

Signed-off-by: Chunfeng Yun 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-mtk-sch.c | 247 ++--
 drivers/usb/host/xhci-mtk.h |  21 
 2 files changed, 258 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
index 7efd890..36050a1 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
@@ -80,10 +80,98 @@ static u32 get_esit(struct xhci_ep_ctx *ep_ctx)
return esit;
 }
 
+static struct mu3h_sch_tt *find_tt(struct usb_device *udev)
+{
+   struct usb_tt *utt = udev->tt;
+   struct mu3h_sch_tt *tt, **tt_index, **ptt;
+   unsigned int port;
+   bool allocated_index = false;
+
+   if (!utt)
+   return NULL;/* Not below a TT */
+
+   /*
+* Find/create our data structure.
+* For hubs with a single TT, we get it directly.
+* For hubs with multiple TTs, there's an extra level of pointers.
+*/
+   tt_index = NULL;
+   if (utt->multi) {
+   tt_index = utt->hcpriv;
+   if (!tt_index) {/* Create the index array */
+   tt_index = kcalloc(utt->hub->maxchild,
+   sizeof(*tt_index), GFP_KERNEL);
+   if (!tt_index)
+   return ERR_PTR(-ENOMEM);
+   utt->hcpriv = tt_index;
+   allocated_index = true;
+   }
+   port = udev->ttport - 1;
+   ptt = _index[port];
+   } else {
+   port = 0;
+   ptt = (struct mu3h_sch_tt **) >hcpriv;
+   }
+
+   tt = *ptt;
+   if (!tt) {  /* Create the mu3h_sch_tt */
+   tt = kzalloc(sizeof(*tt), GFP_KERNEL);
+   if (!tt) {
+   if (allocated_index) {
+   utt->hcpriv = NULL;
+   kfree(tt_index);
+   }
+   return ERR_PTR(-ENOMEM);
+   }
+   INIT_LIST_HEAD(>ep_list);
+   tt->usb_tt = utt;
+   tt->tt_port = port;
+   *ptt = tt;
+   }
+
+   return tt;
+}
+
+/* Release the TT above udev, if it's not in use */
+static void drop_tt(struct usb_device *udev)
+{
+   struct usb_tt *utt = udev->tt;
+   struct mu3h_sch_tt *tt, **tt_index, **ptt;
+   int i, cnt;
+
+   if (!utt || !utt->hcpriv)
+   return; /* Not below a TT, or never allocated */
+
+   cnt = 0;
+   if (utt->multi) {
+   tt_index = utt->hcpriv;
+   ptt = _index[udev->ttport - 1];
+   /*  How many entries are left in tt_index? */
+   for (i = 0; i < utt->hub->maxchild; ++i)
+   cnt += !!tt_index[i];
+   } else {
+   tt_index = NULL;
+   ptt = (struct mu3h_sch_tt **)>hcpriv;
+   }
+
+   tt = *ptt;
+   if (!tt || !list_empty(>ep_list))
+   return; /* never allocated , or still in use*/
+
+   *ptt = NULL;
+   kfree(tt);
+
+   if (cnt == 1) {
+   utt->hcpriv = NULL;
+   kfree(tt_index);
+   }
+}
+
 static struct mu3h_sch_ep_info *create_sch_ep(struct usb_device *udev,
struct usb_host_endpoint *ep, struct xhci_ep_ctx *ep_ctx)
 {
struct mu3h_sch_ep_info *sch_ep;
+   struct mu3h_sch_tt *tt = NULL;
u32 len_bw_budget_table;
size_t mem_size;
 
@@ -101,6 +189,15 @@ static struct mu3h_sch_ep_info *create_sch_ep(struct 
usb_device *udev,
if (!sch_ep)
return ERR_PTR(-ENOMEM);
 
+   if (is_fs_or_ls(udev->speed)) {
+   tt = find_tt(udev);
+   if (IS_ERR(tt)) {
+   kfree(sch_ep);
+   return ERR_PTR(-ENOMEM);
+   }
+   }
+
+   sch_ep->sch_tt = tt;
sch_ep->ep = ep;
 
return sch_ep;
@@ -128,6 +225,8 @@ static void setup_sch_info(struct usb_device *udev,
 CTX_TO_MAX_ESIT_PAYLOAD(le32_to_cpu(ep_ctx->tx_info));
 
sch_ep->esit = get_esit(ep_ctx);
+   sch_ep->ep_type = ep_type;
+   sch_ep->maxpkt = maxpkt;
sch_ep->offset = 0;
sch_ep->burst_mode = 0;
sch_ep->repeat = 0;
@@ -197,8 +296,13 @@ static void setup_sch_info(struct usb_device *udev,
}
} else if (is_fs_or_ls(udev->speed)) {
sch_ep->pkts = 1; /* at most one packet for each microframe */
+
+   /*
+* num_budget_microframes and cs_count will be updated when
+* check TT for INT_OUT_EP, ISOC/INT_IN_EP type
+ 

[PATCH 02/10] usb: xhci-mtk: use maximum ESIT payload of endpiont context

2018-09-13 Thread Mathias Nyman
From: Chunfeng Yun 

Make use of maximum ESIT payload of endpoint context to calculate
the number of packets to send in each ESIT

Signed-off-by: Chunfeng Yun 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-mtk-sch.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
index fa33d6e..46fe0a2 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
@@ -73,12 +73,17 @@ static void setup_sch_info(struct usb_device *udev,
u32 max_burst;
u32 mult;
u32 esit_pkts;
+   u32 max_esit_payload;
 
ep_type = CTX_TO_EP_TYPE(le32_to_cpu(ep_ctx->ep_info2));
ep_interval = CTX_TO_EP_INTERVAL(le32_to_cpu(ep_ctx->ep_info));
max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
max_burst = CTX_TO_MAX_BURST(le32_to_cpu(ep_ctx->ep_info2));
mult = CTX_TO_EP_MULT(le32_to_cpu(ep_ctx->ep_info));
+   max_esit_payload =
+   (CTX_TO_MAX_ESIT_PAYLOAD_HI(
+   le32_to_cpu(ep_ctx->ep_info)) << 16) |
+CTX_TO_MAX_ESIT_PAYLOAD(le32_to_cpu(ep_ctx->tx_info));
 
sch_ep->esit = 1 << ep_interval;
sch_ep->offset = 0;
@@ -105,7 +110,15 @@ static void setup_sch_info(struct usb_device *udev,
} else if (udev->speed == USB_SPEED_SUPER) {
/* usb3_r1 spec section4.4.7 & 4.4.8 */
sch_ep->cs_count = 0;
-   esit_pkts = (mult + 1) * (max_burst + 1);
+   /*
+* some device's (d)wBytesPerInterval is set as 0,
+* then max_esit_payload is 0, so evaluate esit_pkts from
+* mult and burst
+*/
+   esit_pkts = DIV_ROUND_UP(max_esit_payload, max_packet_size);
+   if (esit_pkts == 0)
+   esit_pkts = (mult + 1) * (max_burst + 1);
+
if (ep_type == INT_IN_EP || ep_type == INT_OUT_EP) {
sch_ep->pkts = esit_pkts;
sch_ep->num_budget_microframes = 1;
-- 
2.7.4



[PATCH 01/10] usb: xhci-mtk: resume USB3 roothub first

2018-09-13 Thread Mathias Nyman
From: Chunfeng Yun 

Give USB3 devices a better chance to enumerate at USB3 speeds if
they are connected to a suspended host.
Porting from "671ffdff5b13 xhci: resume USB 3 roothub first"

Signed-off-by: Chunfeng Yun 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-mtk.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index 7334da9..71d0d33 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -642,10 +642,10 @@ static int __maybe_unused xhci_mtk_resume(struct device 
*dev)
xhci_mtk_host_enable(mtk);
 
xhci_dbg(xhci, "%s: restart port polling\n", __func__);
-   set_bit(HCD_FLAG_POLL_RH, >flags);
-   usb_hcd_poll_rh_status(hcd);
set_bit(HCD_FLAG_POLL_RH, >shared_hcd->flags);
usb_hcd_poll_rh_status(xhci->shared_hcd);
+   set_bit(HCD_FLAG_POLL_RH, >flags);
+   usb_hcd_poll_rh_status(hcd);
return 0;
 }
 
-- 
2.7.4



[PATCH 03/10] usb: xhci-mtk: fix ISOC error when interval is zero

2018-09-13 Thread Mathias Nyman
From: Chunfeng Yun 

If the interval equal zero, needn't round up to power of two
for the number of packets in each ESIT, so fix it.

Signed-off-by: Chunfeng Yun 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-mtk-sch.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci-mtk-sch.c b/drivers/usb/host/xhci-mtk-sch.c
index 46fe0a2..057f453 100644
--- a/drivers/usb/host/xhci-mtk-sch.c
+++ b/drivers/usb/host/xhci-mtk-sch.c
@@ -126,7 +126,9 @@ static void setup_sch_info(struct usb_device *udev,
}
 
if (ep_type == ISOC_IN_EP || ep_type == ISOC_OUT_EP) {
-   if (esit_pkts <= sch_ep->esit)
+   if (sch_ep->esit == 1)
+   sch_ep->pkts = esit_pkts;
+   else if (esit_pkts <= sch_ep->esit)
sch_ep->pkts = 1;
else
sch_ep->pkts = roundup_pow_of_two(esit_pkts)
-- 
2.7.4



[PATCH 00/10] xhci features for usb-next

2018-09-13 Thread Mathias Nyman
Hi Greg

A few new features for xhci, better transaction error handling,
default runtime PM allowing for Intel Alpine and Tiran Ridge xhci controllers,
and Mediatek related xhci improvements.

-Mathias

Chunfeng Yun (6):
  usb: xhci-mtk: resume USB3 roothub first
  usb: xhci-mtk: use maximum ESIT payload of endpiont context
  usb: xhci-mtk: fix ISOC error when interval is zero
  usb: xhci-mtk: improve bandwidth scheduling
  usb: xhci-mtk: supports bandwidth scheduling with multi-TT
  usb: xhci-mtk: supports SSP without external USB3 gen2 hub

Heikki Krogerus (1):
  usb: typec: pci: Enable Intel USB role mux on Apollo Lake platforms

Mathias Nyman (2):
  xhci: Use soft retry to recover faster from transaction errors
  xhci-pci: allow host runtime PM as default for Intel Alpine and Titan
Ridge

Peter Chen (1):
  usb: host: xhci-plat: add platform TPL support

 drivers/usb/host/xhci-mtk-sch.c | 429 +---
 drivers/usb/host/xhci-mtk.c |   4 +-
 drivers/usb/host/xhci-mtk.h |  23 +++
 drivers/usb/host/xhci-pci.c |  30 ++-
 drivers/usb/host/xhci-plat.c|   3 +
 drivers/usb/host/xhci-ring.c|  19 ++
 drivers/usb/host/xhci.h |   3 +
 7 files changed, 437 insertions(+), 74 deletions(-)

-- 
2.7.4



Re: [PATCH 1/1] usb: host: xhci-plat: add platform TPL support

2018-09-13 Thread Mathias Nyman

On 13.09.2018 09:54, Peter Chen wrote:

On Wed, Jul 18, 2018 at 2:45 PM Peter Chen  wrote:


The TPL support is used to identify targeted devices during
EH2.0 and EH3.0 certification test, the user can add "tpl-support"
at dts to enable this feature.

Signed-off-by: Peter Chen 
---
  drivers/usb/host/xhci-plat.c | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index c1b22fc64e38..270976cf4156 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -18,6 +18,7 @@
  #include 
  #include 
  #include 
+#include 

  #include "xhci.h"
  #include "xhci-plat.h"
@@ -299,6 +300,8 @@ static int xhci_plat_probe(struct platform_device *pdev)
 hcd->skip_phy_initialization = 1;
 }

+   hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node);
+   xhci->shared_hcd->tpl_support = hcd->tpl_support;
 ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
 if (ret)
 goto disable_usb_phy;
--
2.14.1



Ping...



Thanks, adding to queue

-Mathias


Re: Aw: Re: Fw: Re: keyboard-problem on bpi-r2 since 4.17

2018-09-04 Thread Mathias Nyman

On 04.09.2018 17:51, Frank Wunderlich wrote:

this fixes the issue:

adding the following lines to drivers/usb/host/xhci-mem.c line:1616

if (xhci->quirks & XHCI_MTK_HOST) {
in_ep_ctx->reserved[0] = out_ep_ctx->reserved[0];
in_ep_ctx->reserved[1] = out_ep_ctx->reserved[1];
}
  
commit below is wrong...i got the response:
  
This issue is caused by the commit : 27082e2654dc (“xhci: Clear the host side toggle manually when endpoint is ‘soft reset’”)...
  
i think this commit is meant: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f5249461b504d35aa1a40140983b7ec415807d9e


sorry for confusion, had searched and not compared the result again :(

pushed to my github: 
https://github.com/frank-w/BPI-R2-4.14/commit/c9acc5a4285d0de71171c7c1fb3ae7dc0bffec34

official patch will be send by mediatek

regards Frank
  


Ok, thanks, makes sense.

I'll wait for that patch

I'm offline rest of the week so responses will be delayed

-Mathias



[PATCH] usb: Don't die twice if PCI xhci host is not responding in resume

2018-09-04 Thread Mathias Nyman
usb_hc_died() should only be called once, and with the primary HCD
as parameter. It will mark both primary and secondary hcd's dead.

Remove the extra call to usb_cd_died with the shared hcd as parameter.

Fixes: ff9d78b36f76 ("USB: Set usb_hcd->state and flags for shared roothubs")
Signed-off-by: Mathias Nyman 
---
 drivers/usb/core/hcd-pci.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 66fe1b7..0343246 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -515,8 +515,6 @@ static int resume_common(struct device *dev, int event)
event == PM_EVENT_RESTORE);
if (retval) {
dev_err(dev, "PCI post-resume error %d!\n", retval);
-   if (hcd->shared_hcd)
-   usb_hc_died(hcd->shared_hcd);
usb_hc_died(hcd);
}
}
-- 
2.7.4



Re: Fw: Aw: Re: keyboard-problem on bpi-r2 since 4.17

2018-09-04 Thread Mathias Nyman

On 04.09.2018 16:14, Frank Wunderlich wrote:

Hi,

i got an info that my issue was caused by this commit:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=217491487c43892318c18b6dcafe33b6353efd40

Patch is in progress...


That patch has been there since 4.13
If 4.16 works for you then it's probably something else

  
is there another way to show more debug-messages?
  
i have a working 4.16-tree, maybe i can merge newer versions (go

forward from it instead of backwards).
  


xhci debugging can be added by:

mount -t debugfs none /sys/kernel/debug
echo -n 'module xhci_hcd =p' > /sys/kernel/debug/dynamic_debug/control


and tracing with: (before pressing keyboard key)

(mount -t debugfs none /sys/kernel/debug)
echo 81920 > /sys/kernel/debug/tracing/buffer_size_kb
echo 1 > /sys/kernel/debug/tracing/events/xhci-hcd/enable

after pressing key traces are found at:
/sys/kernel/debug/tracing/trace

-Mathias


[PATCH v2] usb: Avoid use-after-free by flushing endpoints early in usb_set_interface()

2018-09-03 Thread Mathias Nyman
The steps taken by usb core to set a new interface is very different from
what is done on the xHC host side.

xHC hardware will do everything in one go. One command is used to set up
new endpoints, free old endpoints, check bandwidth, and run the new
endpoints.

All this is done by xHC when usb core asks the hcd to check for
available bandwidth. At this point usb core has not yet flushed the old
endpoints, which will cause use-after-free issues in xhci driver as
queued URBs are cancelled on a re-allocated endpoint.

To resolve this add a call to usb_disable_interface() which will flush
the endpoints before calling usb_hcd_alloc_bandwidth()

Additional checks in xhci driver will also be implemented to gracefully
handle stale URB cancel on freed and re-allocated endpoints

Cc: 
Reported-by: Sudip Mukherjee 
Signed-off-by: Mathias Nyman 
---
  v2: update kerneldoc as well
---
 drivers/usb/core/message.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 228672f..bfa5eda 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1341,6 +1341,11 @@ void usb_enable_interface(struct usb_device *dev,
  * is submitted that needs that bandwidth.  Some other operating systems
  * allocate bandwidth early, when a configuration is chosen.
  *
+ * xHCI reserves bandwidth and configures the alternate setting in
+ * usb_hcd_alloc_bandwidth(). If it fails the original interface altsetting
+ * may be disabled. Drivers cannot rely on any particular alternate
+ * setting being in effect after a failure.
+ *
  * This call is synchronous, and may not be used in an interrupt context.
  * Also, drivers must not change altsettings while urbs are scheduled for
  * endpoints in that interface; all such urbs must first be completed
@@ -1376,6 +1381,12 @@ int usb_set_interface(struct usb_device *dev, int 
interface, int alternate)
 alternate);
return -EINVAL;
}
+   /*
+* usb3 hosts configure the interface in usb_hcd_alloc_bandwidth,
+* including freeing dropped endpoint ring buffers.
+* Make sure the interface endpoints are flushed before that
+*/
+   usb_disable_interface(dev, iface, false);
 
/* Make sure we have enough bandwidth for this alternate interface.
 * Remove the current alt setting and add the new alt setting.
-- 
2.7.4



Re: [PATCH] usb: Avoid use-after-free by flushing endpoints early in usb_set_interface()

2018-09-03 Thread Mathias Nyman

On 31.08.2018 17:39, Alan Stern wrote:

On Fri, 31 Aug 2018, Mathias Nyman wrote:


The steps taken by usb core to set a new interface is very different from
what is done on the xHC host side.

xHC hardware will do everything in one go. One command is used to set up
new endpoints, free old endpoints, check bandwidth, and run the new
endpoints.

All this is done by xHC when usb core asks the hcd to check for
available bandwidth. At this point usb core has not yet flushed the old
endpoints, which will cause use-after-free issues in xhci driver as
queued URBs are cancelled on a re-allocated endpoint.

To resolve this add a call to usb_disable_interface() which will flush
the endpoints before calling usb_hcd_alloc_bandwidth()

Additional checks in xhci driver will also be implemented to gracefully
handle stale URB cancel on freed and re-allocated endpoints

Cc: 
Reported-by: Sudip Mukherjee 
Signed-off-by: Mathias Nyman 
---
  drivers/usb/core/message.c | 7 +++
  1 file changed, 7 insertions(+)

diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 228672f..304bef2 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1377,6 +1377,13 @@ int usb_set_interface(struct usb_device *dev, int 
interface, int alternate)
return -EINVAL;
}
  
+	/*

+* usb3 hosts configure the interface in usb_hcd_alloc_bandwidth,
+* including freeing dropped endpoint ring buffers.
+* Make sure the interface endpoints are flushed before that
+*/
+   usb_disable_interface(dev, iface, false);
+
/* Make sure we have enough bandwidth for this alternate interface.
 * Remove the current alt setting and add the new alt setting.
 */


Please also update the kerneldoc for this function.  It should now
specify that if the request fails, the original interface altsetting
may be disabled.  Drivers cannot rely on any particular alternate
setting being in effect after a failure.

Alan Stern



Sure, thanks, will do

-Mathias


[PATCH 0/2] xhci fixes for usb-linus

2018-08-31 Thread Mathias Nyman
Hi Greg

A couple of xhci fixes, one finding all quirks for platform xhci devices,
and another fixing use-after-free case if stale URBs are cancelled on
already re-allocated endpoints.

-Mathias

Anurag Kumar Vulisha (1):
  usb: host: xhci-plat: Iterate over parent nodes for finding quirks

Mathias Nyman (1):
  xhci: Fix use after free for URB cancellation on a reallocated
endpoint

 drivers/usb/host/xhci-plat.c | 27 ---
 drivers/usb/host/xhci.c  | 30 ++
 2 files changed, 46 insertions(+), 11 deletions(-)

-- 
2.7.4



[PATCH 1/2] usb: host: xhci-plat: Iterate over parent nodes for finding quirks

2018-08-31 Thread Mathias Nyman
From: Anurag Kumar Vulisha 

In xhci_plat_probe() both sysdev and pdev->dev are being used
for finding quirks. There are some drivers(like dwc3 host.c)
which adds quirks(like usb3-lpm-capable) into pdev and the logic
present in xhci_plat_probe() checks for quirks in either sysdev
or pdev for finding the quirks. Because of this logic, some of
the quirks are getting missed(usb3-lpm-capable quirk added by dwc3
host.c driver is getting missed).This patch fixes this by iterating
over all the available parents for finding the quirks. In this way
all the quirks which are present in child or parent are correctly
updated.

Signed-off-by: Anurag Kumar Vulisha 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-plat.c | 27 ---
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index 8dc77e3..94e9392 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -153,7 +153,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
 {
const struct xhci_plat_priv *priv_match;
const struct hc_driver  *driver;
-   struct device   *sysdev;
+   struct device   *sysdev, *tmpdev;
struct xhci_hcd *xhci;
struct resource *res;
struct usb_hcd  *hcd;
@@ -273,19 +273,24 @@ static int xhci_plat_probe(struct platform_device *pdev)
goto disable_clk;
}
 
-   if (device_property_read_bool(sysdev, "usb2-lpm-disable"))
-   xhci->quirks |= XHCI_HW_LPM_DISABLE;
+   /* imod_interval is the interrupt moderation value in nanoseconds. */
+   xhci->imod_interval = 4;
 
-   if (device_property_read_bool(sysdev, "usb3-lpm-capable"))
-   xhci->quirks |= XHCI_LPM_SUPPORT;
+   /* Iterate over all parent nodes for finding quirks */
+   for (tmpdev = >dev; tmpdev; tmpdev = tmpdev->parent) {
 
-   if (device_property_read_bool(>dev, "quirk-broken-port-ped"))
-   xhci->quirks |= XHCI_BROKEN_PORT_PED;
+   if (device_property_read_bool(tmpdev, "usb2-lpm-disable"))
+   xhci->quirks |= XHCI_HW_LPM_DISABLE;
 
-   /* imod_interval is the interrupt moderation value in nanoseconds. */
-   xhci->imod_interval = 4;
-   device_property_read_u32(sysdev, "imod-interval-ns",
->imod_interval);
+   if (device_property_read_bool(tmpdev, "usb3-lpm-capable"))
+   xhci->quirks |= XHCI_LPM_SUPPORT;
+
+   if (device_property_read_bool(tmpdev, "quirk-broken-port-ped"))
+   xhci->quirks |= XHCI_BROKEN_PORT_PED;
+
+   device_property_read_u32(tmpdev, "imod-interval-ns",
+>imod_interval);
+   }
 
hcd->usb_phy = devm_usb_get_phy_by_phandle(sysdev, "usb-phy", 0);
if (IS_ERR(hcd->usb_phy)) {
-- 
2.7.4



[PATCH 2/2] xhci: Fix use after free for URB cancellation on a reallocated endpoint

2018-08-31 Thread Mathias Nyman
Make sure the cancelled URB is on the current endpoint ring.

If the endpoint ring has been reallocated since the URB was enqueued
then the URB may contain TD and TRB pointers to a already freed ring.
In this the case return the URB without touching any of the freed ring
structure data.

Don't try to stop the ring. It would be useless.

This can occur if endpoint is not flushed before it is dropped and
re-added, which is the case in usb_set_interface() as xhci does
things in an odd order.

Cc: 
Tested-by: Sudip Mukherjee 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci.c | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 61f48b1..0420eef 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -37,6 +37,21 @@ static unsigned long long quirks;
 module_param(quirks, ullong, S_IRUGO);
 MODULE_PARM_DESC(quirks, "Bit flags for quirks to be enabled as default");
 
+static bool td_on_ring(struct xhci_td *td, struct xhci_ring *ring)
+{
+   struct xhci_segment *seg = ring->first_seg;
+
+   if (!td || !td->start_seg)
+   return false;
+   do {
+   if (seg == td->start_seg)
+   return true;
+   seg = seg->next;
+   } while (seg && seg != ring->first_seg);
+
+   return false;
+}
+
 /* TODO: copied from ehci-hcd.c - can this be refactored? */
 /*
  * xhci_handshake - spin reading hc until handshake completes or fails
@@ -1571,6 +1586,21 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct 
urb *urb, int status)
goto done;
}
 
+   /*
+* check ring is not re-allocated since URB was enqueued. If it is, then
+* make sure none of the ring related pointers in this URB private data
+* are touched, such as td_list, otherwise we overwrite freed data
+*/
+   if (!td_on_ring(_priv->td[0], ep_ring)) {
+   xhci_err(xhci, "Canceled URB td not found on endpoint ring");
+   for (i = urb_priv->num_tds_done; i < urb_priv->num_tds; i++) {
+   td = _priv->td[i];
+   if (!list_empty(>cancelled_td_list))
+   list_del_init(>cancelled_td_list);
+   }
+   goto err_giveback;
+   }
+
if (xhci->xhc_state & XHCI_STATE_HALTED) {
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
"HC halted, freeing TD manually.");
-- 
2.7.4



[PATCH] usb: Avoid use-after-free by flushing endpoints early in usb_set_interface()

2018-08-31 Thread Mathias Nyman
The steps taken by usb core to set a new interface is very different from
what is done on the xHC host side.

xHC hardware will do everything in one go. One command is used to set up
new endpoints, free old endpoints, check bandwidth, and run the new
endpoints.

All this is done by xHC when usb core asks the hcd to check for
available bandwidth. At this point usb core has not yet flushed the old
endpoints, which will cause use-after-free issues in xhci driver as
queued URBs are cancelled on a re-allocated endpoint.

To resolve this add a call to usb_disable_interface() which will flush
the endpoints before calling usb_hcd_alloc_bandwidth()

Additional checks in xhci driver will also be implemented to gracefully
handle stale URB cancel on freed and re-allocated endpoints

Cc: 
Reported-by: Sudip Mukherjee 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/core/message.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 228672f..304bef2 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1377,6 +1377,13 @@ int usb_set_interface(struct usb_device *dev, int 
interface, int alternate)
return -EINVAL;
}
 
+   /*
+* usb3 hosts configure the interface in usb_hcd_alloc_bandwidth,
+* including freeing dropped endpoint ring buffers.
+* Make sure the interface endpoints are flushed before that
+*/
+   usb_disable_interface(dev, iface, false);
+
/* Make sure we have enough bandwidth for this alternate interface.
 * Remove the current alt setting and add the new alt setting.
 */
-- 
2.7.4



[PATCH 1/1] usb: xhci: Fix memory leak in xhci_endpoint_reset()

2018-07-20 Thread Mathias Nyman
From: Zheng Xiaowei 

If td_list is not empty the cfg_cmd will not be freed,
call xhci_free_command to free it.

Signed-off-by: Zheng Xiaowei 
Cc: 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 2f4850f..68e6132 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3051,6 +3051,7 @@ static void xhci_endpoint_reset(struct usb_hcd *hcd,
if (!list_empty(>ring->td_list)) {
dev_err(>dev, "EP not empty, refuse reset\n");
spin_unlock_irqrestore(>lock, flags);
+   xhci_free_command(xhci, cfg_cmd);
goto cleanup;
}
xhci_queue_stop_endpoint(xhci, stop_cmd, udev->slot_id, ep_index, 0);
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/1] xhci fix for usb-linus

2018-07-20 Thread Mathias Nyman
Hi Greg

Thanks for picking up xhci patches while I've been away

This one small fix could be added to usb-linus still.

-Mathias

Zheng Xiaowei (1):
  usb: xhci: Fix memory leak in xhci_endpoint_reset()

 drivers/usb/host/xhci.c | 1 +
 1 file changed, 1 insertion(+)

-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/1] usb: xhci: dbc: Don't decrement runtime PM counter if DBC is not started

2018-07-02 Thread Mathias Nyman
From: Kai-Heng Feng 

pm_runtime_put_sync() gets called everytime in xhci_dbc_stop().

If dbc is not started, this makes the runtime PM counter incorrectly
becomes 0, and calls autosuspend function. Then we'll keep seeing this:
[54664.762220] xhci_hcd :00:14.0: Root hub is not suspended

So only calls pm_runtime_put_sync() when dbc was started.

Signed-off-by: Kai-Heng Feng 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-dbgcap.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c
index 1fbfd89..387f124 100644
--- a/drivers/usb/host/xhci-dbgcap.c
+++ b/drivers/usb/host/xhci-dbgcap.c
@@ -508,16 +508,18 @@ static int xhci_do_dbc_start(struct xhci_hcd *xhci)
return 0;
 }
 
-static void xhci_do_dbc_stop(struct xhci_hcd *xhci)
+static int xhci_do_dbc_stop(struct xhci_hcd *xhci)
 {
struct xhci_dbc *dbc = xhci->dbc;
 
if (dbc->state == DS_DISABLED)
-   return;
+   return -1;
 
writel(0, >regs->control);
xhci_dbc_mem_cleanup(xhci);
dbc->state = DS_DISABLED;
+
+   return 0;
 }
 
 static int xhci_dbc_start(struct xhci_hcd *xhci)
@@ -544,6 +546,7 @@ static int xhci_dbc_start(struct xhci_hcd *xhci)
 
 static void xhci_dbc_stop(struct xhci_hcd *xhci)
 {
+   int ret;
unsigned long   flags;
struct xhci_dbc *dbc = xhci->dbc;
struct dbc_port *port = >port;
@@ -556,10 +559,11 @@ static void xhci_dbc_stop(struct xhci_hcd *xhci)
xhci_dbc_tty_unregister_device(xhci);
 
spin_lock_irqsave(>lock, flags);
-   xhci_do_dbc_stop(xhci);
+   ret = xhci_do_dbc_stop(xhci);
spin_unlock_irqrestore(>lock, flags);
 
-   pm_runtime_put_sync(xhci_to_hcd(xhci)->self.controller);
+   if (!ret)
+   pm_runtime_put_sync(xhci_to_hcd(xhci)->self.controller);
 }
 
 static void
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/1] xhci fix for usb-linus

2018-07-02 Thread Mathias Nyman
Hi Greg

A small fix for usb-linus making sure runtime PM get/put is balanced

-Mathias

Kai-Heng Feng (1):
  usb: xhci: dbc: Don't decrement runtime PM counter if DBC is not
started

 drivers/usb/host/xhci-dbgcap.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/5] xhci: Fix perceived dead host due to runtime suspend race with event handler

2018-06-21 Thread Mathias Nyman
Don't rely on event interrupt (EINT) bit alone to detect pending port
change in resume. If no change event is detected the host may be suspended
again, oterwise roothubs are resumed.

There is a lag in xHC setting EINT. If we don't notice the pending change
in resume, and the controller is runtime suspeded again, it causes the
event handler to assume host is dead as it will fail to read xHC registers
once PCI puts the controller to D3 state.

[  268.520969] xhci_hcd: xhci_resume: starting port polling.
[  268.520985] xhci_hcd: xhci_hub_status_data: stopping port polling.
[  268.521030] xhci_hcd: xhci_suspend: stopping port polling.
[  268.521040] xhci_hcd: // Setting command ring address to 0x349bd001
[  268.521139] xhci_hcd: Port Status Change Event for port 3
[  268.521149] xhci_hcd: resume root hub
[  268.521163] xhci_hcd: port resume event for port 3
[  268.521168] xhci_hcd: xHC is not running.
[  268.521174] xhci_hcd: handle_port_status: starting port polling.
[  268.596322] xhci_hcd: xhci_hc_died: xHCI host controller not responding, 
assume dead

The EINT lag is described in a additional note in xhci specs 4.19.2:

"Due to internal xHC scheduling and system delays, there will be a lag
between a change bit being set and the Port Status Change Event that it
generated being written to the Event Ring. If SW reads the PORTSC and
sees a change bit set, there is no guarantee that the corresponding Port
Status Change Event has already been written into the Event Ring."

Cc: 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci.c | 40 +---
 drivers/usb/host/xhci.h |  4 
 2 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 8c8da2d..f11ec61 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -908,6 +908,41 @@ static void xhci_disable_port_wake_on_bits(struct xhci_hcd 
*xhci)
spin_unlock_irqrestore(>lock, flags);
 }
 
+static bool xhci_pending_portevent(struct xhci_hcd *xhci)
+{
+   struct xhci_port**ports;
+   int port_index;
+   u32 status;
+   u32 portsc;
+
+   status = readl(>op_regs->status);
+   if (status & STS_EINT)
+   return true;
+   /*
+* Checking STS_EINT is not enough as there is a lag between a change
+* bit being set and the Port Status Change Event that it generated
+* being written to the Event Ring. See note in xhci 1.1 section 4.19.2.
+*/
+
+   port_index = xhci->usb2_rhub.num_ports;
+   ports = xhci->usb2_rhub.ports;
+   while (port_index--) {
+   portsc = readl(ports[port_index]->addr);
+   if (portsc & PORT_CHANGE_MASK ||
+   (portsc & PORT_PLS_MASK) == XDEV_RESUME)
+   return true;
+   }
+   port_index = xhci->usb3_rhub.num_ports;
+   ports = xhci->usb3_rhub.ports;
+   while (port_index--) {
+   portsc = readl(ports[port_index]->addr);
+   if (portsc & PORT_CHANGE_MASK ||
+   (portsc & PORT_PLS_MASK) == XDEV_RESUME)
+   return true;
+   }
+   return false;
+}
+
 /*
  * Stop HC (not bus-specific)
  *
@@ -1009,7 +1044,7 @@ EXPORT_SYMBOL_GPL(xhci_suspend);
  */
 int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 {
-   u32 command, temp = 0, status;
+   u32 command, temp = 0;
struct usb_hcd  *hcd = xhci_to_hcd(xhci);
struct usb_hcd  *secondary_hcd;
int retval = 0;
@@ -1134,8 +1169,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
  done:
if (retval == 0) {
/* Resume root hubs only when have pending events. */
-   status = readl(>op_regs->status);
-   if (status & STS_EINT) {
+   if (xhci_pending_portevent(xhci)) {
usb_hcd_resume_root_hub(xhci->shared_hcd);
usb_hcd_resume_root_hub(hcd);
}
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 939e2f86..841e89f 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -382,6 +382,10 @@ struct xhci_op_regs {
 #define PORT_PLC   (1 << 22)
 /* port configure error change - port failed to configure its link partner */
 #define PORT_CEC   (1 << 23)
+#define PORT_CHANGE_MASK   (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \
+PORT_RC | PORT_PLC | PORT_CEC)
+
+
 /* Cold Attach Status - xHC can set this bit to report device attached during
  * Sx state. Warm port reset should be perfomed to clear this bit and move port
  * to connected state.
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-

[PATCH 0/5] xhci fixes for usb-linus

2018-06-21 Thread Mathias Nyman
Hi Greg

A few xhci fixes for usb-linus.
Fixing a oops in xhci tracing, a race in S3 resume event handling,
tegra runtime PM, and other small fixes.

-Mathias

Ajay Gupta (1):
  usb: xhci: increase CRS timeout value

Dongjiu Geng (1):
  usb: xhci: remove the code build warning

Mathias Nyman (1):
  xhci: Fix perceived dead host due to runtime suspend race with event
handler

Stefan Agner (1):
  usb: xhci: tegra: fix runtime PM error handling

Zhengjun Xing (1):
  xhci: Fix kernel oops in trace_xhci_free_virt_device

 drivers/usb/host/xhci-mem.c   |  4 ++--
 drivers/usb/host/xhci-tegra.c |  6 +++---
 drivers/usb/host/xhci-trace.h | 36 -
 drivers/usb/host/xhci.c   | 47 +++
 drivers/usb/host/xhci.h   |  4 
 5 files changed, 83 insertions(+), 14 deletions(-)

-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/5] usb: xhci: remove the code build warning

2018-06-21 Thread Mathias Nyman
From: Dongjiu Geng 

Initialize the 'err' variate to remove the build warning,
the warning is shown as below:

drivers/usb/host/xhci-tegra.c: In function 'tegra_xusb_mbox_thread':
drivers/usb/host/xhci-tegra.c:552:6: warning: 'err' may be used uninitialized 
in this function [-Wuninitialized]
drivers/usb/host/xhci-tegra.c:482:6: note: 'err' was declared here

Fixes: e84fce0f8837 ("usb: xhci: Add NVIDIA Tegra XUSB controller driver")
Signed-off-by: Dongjiu Geng 
Acked-by: Thierry Reding 
Acked-by: Jon Hunter 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-tegra.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index a8c1d07..d50549f 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -481,7 +481,7 @@ static void tegra_xusb_mbox_handle(struct tegra_xusb *tegra,
unsigned long mask;
unsigned int port;
bool idle, enable;
-   int err;
+   int err = 0;
 
memset(, 0, sizeof(rsp));
 
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/5] xhci: Fix kernel oops in trace_xhci_free_virt_device

2018-06-21 Thread Mathias Nyman
From: Zhengjun Xing 

commit 44a182b9d177 ("xhci: Fix use-after-free in xhci_free_virt_device")
set dev->udev pointer to NULL in xhci_free_dev(), it will cause kernel
panic in trace_xhci_free_virt_device. This patch reimplement the trace
function trace_xhci_free_virt_device, remove dev->udev dereference and
added more useful parameters to show in the trace function,it also makes
sure dev->udev is not NULL before calling trace_xhci_free_virt_device.
This issue happened when xhci-hcd trace is enabled and USB devices hot
plug test. Original use-after-free patch went to stable so this needs so
be applied there as well.

[ 1092.022457] usb 2-4: USB disconnect, device number 6
[ 1092.092772] BUG: unable to handle kernel NULL pointer dereference at 

[ 1092.101694] PGD 0 P4D 0
[ 1092.104601] Oops:  [#1] SMP
[ 1092.207734] Workqueue: usb_hub_wq hub_event
[ 1092.212507] RIP: 0010:trace_event_raw_event_xhci_log_virt_dev+0x6c/0xf0
[ 1092.220050] RSP: 0018:8c252e883d28 EFLAGS: 00010086
[ 1092.226024] RAX: 8c24af86fa84 RBX: 0003 RCX: 8c25255c2a01
[ 1092.234130] RDX:  RSI: aef55009 RDI: 8c252e883d28
[ 1092.242242] RBP: 8c252550e2c0 R08: 8c24af86fa84 R09: 0a70
[ 1092.250364] R10: 0a70 R11:  R12: 8c251f21a000
[ 1092.258468] R13: 000c R14: 8c251f21a000 R15: 8c251f432f60
[ 1092.266572] FS:  () GS:8c252e88() 
knlGS:
[ 1092.275757] CS:  0010 DS:  ES:  CR0: 80050033
[ 1092.282281] CR2:  CR3: 000154209001 CR4: 003606e0
[ 1092.290384] Call Trace:
[ 1092.293156]  
[ 1092.295439]  xhci_free_virt_device.part.34+0x182/0x1a0
[ 1092.301288]  handle_cmd_completion+0x7ac/0xfa0
[ 1092.306336]  ? trace_event_raw_event_xhci_log_trb+0x6e/0xa0
[ 1092.312661]  xhci_irq+0x3e8/0x1f60
[ 1092.316524]  __handle_irq_event_percpu+0x75/0x180
[ 1092.321876]  handle_irq_event_percpu+0x20/0x50
[ 1092.326922]  handle_irq_event+0x36/0x60
[ 1092.331273]  handle_edge_irq+0x6d/0x180
[ 1092.335644]  handle_irq+0x16/0x20
[ 1092.339417]  do_IRQ+0x41/0xc0
[ 1092.342782]  common_interrupt+0xf/0xf
[ 1092.346955]  

Fixes: 44a182b9d177 ("xhci: Fix use-after-free in xhci_free_virt_device")
Cc: 
Signed-off-by: Zhengjun Xing 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-mem.c   |  4 ++--
 drivers/usb/host/xhci-trace.h | 36 +++-
 2 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index acbd3d7..8a62eee 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -886,12 +886,12 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int 
slot_id)
 
dev = xhci->devs[slot_id];
 
-   trace_xhci_free_virt_device(dev);
-
xhci->dcbaa->dev_context_ptrs[slot_id] = 0;
if (!dev)
return;
 
+   trace_xhci_free_virt_device(dev);
+
if (dev->tt_info)
old_active_eps = dev->tt_info->active_eps;
 
diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h
index 410544f..88b4274 100644
--- a/drivers/usb/host/xhci-trace.h
+++ b/drivers/usb/host/xhci-trace.h
@@ -171,6 +171,37 @@ DEFINE_EVENT(xhci_log_trb, xhci_dbc_gadget_ep_queue,
TP_ARGS(ring, trb)
 );
 
+DECLARE_EVENT_CLASS(xhci_log_free_virt_dev,
+   TP_PROTO(struct xhci_virt_device *vdev),
+   TP_ARGS(vdev),
+   TP_STRUCT__entry(
+   __field(void *, vdev)
+   __field(unsigned long long, out_ctx)
+   __field(unsigned long long, in_ctx)
+   __field(u8, fake_port)
+   __field(u8, real_port)
+   __field(u16, current_mel)
+
+   ),
+   TP_fast_assign(
+   __entry->vdev = vdev;
+   __entry->in_ctx = (unsigned long long) vdev->in_ctx->dma;
+   __entry->out_ctx = (unsigned long long) vdev->out_ctx->dma;
+   __entry->fake_port = (u8) vdev->fake_port;
+   __entry->real_port = (u8) vdev->real_port;
+   __entry->current_mel = (u16) vdev->current_mel;
+   ),
+   TP_printk("vdev %p ctx %llx | %llx fake_port %d real_port %d 
current_mel %d",
+   __entry->vdev, __entry->in_ctx, __entry->out_ctx,
+   __entry->fake_port, __entry->real_port, __entry->current_mel
+   )
+);
+
+DEFINE_EVENT(xhci_log_free_virt_dev, xhci_free_virt_device,
+   TP_PROTO(struct xhci_virt_device *vdev),
+   TP_ARGS(vdev)
+);
+
 DECLARE_EVENT_CLASS(xhci_log_virt_dev,
TP_PROTO(struct xhci_virt_device *vdev),
TP_ARGS(vdev),
@@ -208,11 +239,6 @@ DEFINE_EVENT(xhci_log_virt_dev, xhci_alloc_virt_device,
TP_ARGS(vdev)
 );
 
-DEFINE_EVENT(xhci_log_virt_dev, xhci_free_virt_de

[PATCH 5/5] usb: xhci: increase CRS timeout value

2018-06-21 Thread Mathias Nyman
From: Ajay Gupta 

Some controllers take almost 55ms to complete controller
restore state (CRS).
There is no timeout limit mentioned in xhci specification so
fixing the issue by increasing the timeout limit to 100ms

[reformat code comment -Mathias]
Signed-off-by: Ajay Gupta 
Signed-off-by: Nagaraj Annaiah 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index f11ec61..2f4850f 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1078,8 +1078,13 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
command = readl(>op_regs->command);
command |= CMD_CRS;
writel(command, >op_regs->command);
+   /*
+* Some controllers take up to 55+ ms to complete the controller
+* restore so setting the timeout to 100ms. Xhci specification
+* doesn't mention any timeout value.
+*/
if (xhci_handshake(>op_regs->status,
- STS_RESTORE, 0, 10 * 1000)) {
+ STS_RESTORE, 0, 100 * 1000)) {
xhci_warn(xhci, "WARN: xHC restore state timeout\n");
spin_unlock_irq(>lock);
return -ETIMEDOUT;
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 4/5] usb: xhci: tegra: fix runtime PM error handling

2018-06-21 Thread Mathias Nyman
From: Stefan Agner 

The address-of operator will always evaluate to true. However,
power should be explicitly disabled if no power domain is used.

Remove the address-of operator.

Fixes: 58c38116c6cc ("usb: xhci: tegra: Add support for managing powergates")
Signed-off-by: Stefan Agner 
Acked-by: Jon Hunter 
Signed-off-by: Mathias Nyman 
---
 drivers/usb/host/xhci-tegra.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index d50549f..4b463e5 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -1223,10 +1223,10 @@ static int tegra_xusb_probe(struct platform_device 
*pdev)
pm_runtime_disable(>dev);
usb_put_hcd(tegra->hcd);
 disable_xusbc:
-   if (!>dev.pm_domain)
+   if (!pdev->dev.pm_domain)
tegra_powergate_power_off(TEGRA_POWERGATE_XUSBC);
 disable_xusba:
-   if (!>dev.pm_domain)
+   if (!pdev->dev.pm_domain)
tegra_powergate_power_off(TEGRA_POWERGATE_XUSBA);
 put_padctl:
tegra_xusb_padctl_put(tegra->padctl);
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3] usb: xhci: increase CRS timeout value

2018-06-19 Thread Mathias Nyman

On 12.06.2018 00:10, Ajay Gupta wrote:

Some controllers take almost 55ms to complete controller
restore state (CRS).
There is no timeout limit mentioned in xhci specification so
fixing the issue by increasing the timeout limit to 100ms

Signed-off-by: Ajay Gupta 
Signed-off-by: Nagaraj Annaiah 
---
Changes from v2->v3
Updated commit message for timeout value to 100ms

Changes from v1->v2
Updated timeout value from 55 to 100ms and added a comment.
  drivers/usb/host/xhci.c | 7 ++-
  1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 8c8da2d..fa7bd71 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -1043,8 +1043,13 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
command = readl(>op_regs->command);
command |= CMD_CRS;
writel(command, >op_regs->command);
+   /* Some controllers take upto 55+ ms to complete
+* the controller restore so setting the timeout to
+* 100ms. Xhci specification doesn't mention any
+* timeout value.
+*/
if (xhci_handshake(>op_regs->status,
- STS_RESTORE, 0, 10 * 1000)) {
+ STS_RESTORE, 0, 100 * 1000)) {
xhci_warn(xhci, "WARN: xHC restore state timeout\n");
spin_unlock_irq(>lock);
return -ETIMEDOUT;



Thanks,
Patch looks good, I did however do a minor reformat of comment part.

I'm running this patch together with other 4.18-rc1 fixes through internal 
first.
I'll send it forward soon (0-2 days)

-Mathias
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


  1   2   3   4   5   6   7   8   9   10   >