summaryrefslogtreecommitdiffstats
path: root/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0026-usb-Add-support-for-root-hub-port-status-CAS.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0026-usb-Add-support-for-root-hub-port-status-CAS.patch')
-rw-r--r--recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0026-usb-Add-support-for-root-hub-port-status-CAS.patch170
1 files changed, 170 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0026-usb-Add-support-for-root-hub-port-status-CAS.patch b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0026-usb-Add-support-for-root-hub-port-status-CAS.patch
new file mode 100644
index 00000000..827fceca
--- /dev/null
+++ b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.24/0026-usb-Add-support-for-root-hub-port-status-CAS.patch
@@ -0,0 +1,170 @@
1From 6455e1a5be4eb27a1587322e0ed3a7ff6c3d8e4f Mon Sep 17 00:00:00 2001
2From: Stanislaw Ledwon <staszek.ledwon@linux.jf.intel.com>
3Date: Mon, 18 Jun 2012 15:20:00 +0200
4Subject: [PATCH 026/109] usb: Add support for root hub port status CAS
5
6commit 8bea2bd37df08aaa599aa361a9f8b836ba98e554 upstream.
7
8The host controller port status register supports CAS (Cold Attach
9Status) bit. This bit could be set when USB3.0 device is connected
10when system is in Sx state. When the system wakes to S0 this port
11status with CAS bit is reported and this port can't be used by any
12device.
13
14When CAS bit is set the port should be reset by warm reset. This
15was not supported by xhci driver.
16
17The issue was found when pendrive was connected to suspended
18platform. The link state of "Compliance Mode" was reported together
19with CAS bit. This link state was also not supported by xhci and
20core/hub.c.
21
22The CAS bit is defined only for xhci root hub port and it is
23not supported on regular hubs. The link status is used to force
24warm reset on port. Make the USB core issue a warm reset when port
25is in ether the 'inactive' or 'compliance mode'. Change the xHCI driver
26to report 'compliance mode' when the CAS is set. This force warm reset
27on the root hub port.
28
29This patch should be backported to stable kernels as old as 3.2, that
30contain the commit 10d674a82e553cb8a1f41027bb3c3e309b3f6804 "USB: When
31hot reset for USB3 fails, try warm reset."
32
33Signed-off-by: Stanislaw Ledwon <staszek.ledwon@linux.intel.com>
34Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
35Acked-by: Andiry Xu <andiry.xu@amd.com>
36Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
37---
38 drivers/usb/core/hub.c | 18 +++++++++-------
39 drivers/usb/host/xhci-hub.c | 44 +++++++++++++++++++++++++++++++++++++-----
40 drivers/usb/host/xhci.h | 6 ++++-
41 3 files changed, 53 insertions(+), 15 deletions(-)
42
43diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
44index 50cf41a..2bc736f 100644
45--- a/drivers/usb/core/hub.c
46+++ b/drivers/usb/core/hub.c
47@@ -2039,12 +2039,16 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
48 static int hub_port_reset(struct usb_hub *hub, int port1,
49 struct usb_device *udev, unsigned int delay, bool warm);
50
51-/* Is a USB 3.0 port in the Inactive state? */
52-static bool hub_port_inactive(struct usb_hub *hub, u16 portstatus)
53+/* Is a USB 3.0 port in the Inactive or Complinance Mode state?
54+ * Port worm reset is required to recover
55+ */
56+static bool hub_port_warm_reset_required(struct usb_hub *hub, u16 portstatus)
57 {
58 return hub_is_superspeed(hub->hdev) &&
59- (portstatus & USB_PORT_STAT_LINK_STATE) ==
60- USB_SS_PORT_LS_SS_INACTIVE;
61+ (((portstatus & USB_PORT_STAT_LINK_STATE) ==
62+ USB_SS_PORT_LS_SS_INACTIVE) ||
63+ ((portstatus & USB_PORT_STAT_LINK_STATE) ==
64+ USB_SS_PORT_LS_COMP_MOD)) ;
65 }
66
67 static int hub_port_wait_reset(struct usb_hub *hub, int port1,
68@@ -2080,7 +2084,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1,
69 *
70 * See https://bugzilla.kernel.org/show_bug.cgi?id=41752
71 */
72- if (hub_port_inactive(hub, portstatus)) {
73+ if (hub_port_warm_reset_required(hub, portstatus)) {
74 int ret;
75
76 if ((portchange & USB_PORT_STAT_C_CONNECTION))
77@@ -3646,9 +3650,7 @@ static void hub_events(void)
78 /* Warm reset a USB3 protocol port if it's in
79 * SS.Inactive state.
80 */
81- if (hub_is_superspeed(hub->hdev) &&
82- (portstatus & USB_PORT_STAT_LINK_STATE)
83- == USB_SS_PORT_LS_SS_INACTIVE) {
84+ if (hub_port_warm_reset_required(hub, portstatus)) {
85 dev_dbg(hub_dev, "warm reset port %d\n", i);
86 hub_port_reset(hub, i, NULL,
87 HUB_BH_RESET_TIME, true);
88diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
89index a8b2980..fd8a2c2 100644
90--- a/drivers/usb/host/xhci-hub.c
91+++ b/drivers/usb/host/xhci-hub.c
92@@ -438,6 +438,42 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,
93 }
94 }
95
96+/* Updates Link Status for super Speed port */
97+static void xhci_hub_report_link_state(u32 *status, u32 status_reg)
98+{
99+ u32 pls = status_reg & PORT_PLS_MASK;
100+
101+ /* resume state is a xHCI internal state.
102+ * Do not report it to usb core.
103+ */
104+ if (pls == XDEV_RESUME)
105+ return;
106+
107+ /* When the CAS bit is set then warm reset
108+ * should be performed on port
109+ */
110+ if (status_reg & PORT_CAS) {
111+ /* The CAS bit can be set while the port is
112+ * in any link state.
113+ * Only roothubs have CAS bit, so we
114+ * pretend to be in compliance mode
115+ * unless we're already in compliance
116+ * or the inactive state.
117+ */
118+ if (pls != USB_SS_PORT_LS_COMP_MOD &&
119+ pls != USB_SS_PORT_LS_SS_INACTIVE) {
120+ pls = USB_SS_PORT_LS_COMP_MOD;
121+ }
122+ /* Return also connection bit -
123+ * hub state machine resets port
124+ * when this bit is set.
125+ */
126+ pls |= USB_PORT_STAT_CONNECTION;
127+ }
128+ /* update status field */
129+ *status |= pls;
130+}
131+
132 int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
133 u16 wIndex, char *buf, u16 wLength)
134 {
135@@ -579,13 +615,9 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
136 else
137 status |= USB_PORT_STAT_POWER;
138 }
139- /* Port Link State */
140+ /* Update Port Link State for super speed ports*/
141 if (hcd->speed == HCD_USB3) {
142- /* resume state is a xHCI internal state.
143- * Do not report it to usb core.
144- */
145- if ((temp & PORT_PLS_MASK) != XDEV_RESUME)
146- status |= (temp & PORT_PLS_MASK);
147+ xhci_hub_report_link_state(&status, temp);
148 }
149 if (bus_state->port_c_suspend & (1 << wIndex))
150 status |= 1 << USB_PORT_FEAT_C_SUSPEND;
151diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
152index 363b141..7a56805 100644
153--- a/drivers/usb/host/xhci.h
154+++ b/drivers/usb/host/xhci.h
155@@ -341,7 +341,11 @@ struct xhci_op_regs {
156 #define PORT_PLC (1 << 22)
157 /* port configure error change - port failed to configure its link partner */
158 #define PORT_CEC (1 << 23)
159-/* bit 24 reserved */
160+/* Cold Attach Status - xHC can set this bit to report device attached during
161+ * Sx state. Warm port reset should be perfomed to clear this bit and move port
162+ * to connected state.
163+ */
164+#define PORT_CAS (1 << 24)
165 /* wake on connect (enable) */
166 #define PORT_WKCONN_E (1 << 25)
167 /* wake on disconnect (enable) */
168--
1691.7.7.6
170