diff options
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.patch | 170 |
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 @@ | |||
1 | From 6455e1a5be4eb27a1587322e0ed3a7ff6c3d8e4f Mon Sep 17 00:00:00 2001 | ||
2 | From: Stanislaw Ledwon <staszek.ledwon@linux.jf.intel.com> | ||
3 | Date: Mon, 18 Jun 2012 15:20:00 +0200 | ||
4 | Subject: [PATCH 026/109] usb: Add support for root hub port status CAS | ||
5 | |||
6 | commit 8bea2bd37df08aaa599aa361a9f8b836ba98e554 upstream. | ||
7 | |||
8 | The host controller port status register supports CAS (Cold Attach | ||
9 | Status) bit. This bit could be set when USB3.0 device is connected | ||
10 | when system is in Sx state. When the system wakes to S0 this port | ||
11 | status with CAS bit is reported and this port can't be used by any | ||
12 | device. | ||
13 | |||
14 | When CAS bit is set the port should be reset by warm reset. This | ||
15 | was not supported by xhci driver. | ||
16 | |||
17 | The issue was found when pendrive was connected to suspended | ||
18 | platform. The link state of "Compliance Mode" was reported together | ||
19 | with CAS bit. This link state was also not supported by xhci and | ||
20 | core/hub.c. | ||
21 | |||
22 | The CAS bit is defined only for xhci root hub port and it is | ||
23 | not supported on regular hubs. The link status is used to force | ||
24 | warm reset on port. Make the USB core issue a warm reset when port | ||
25 | is in ether the 'inactive' or 'compliance mode'. Change the xHCI driver | ||
26 | to report 'compliance mode' when the CAS is set. This force warm reset | ||
27 | on the root hub port. | ||
28 | |||
29 | This patch should be backported to stable kernels as old as 3.2, that | ||
30 | contain the commit 10d674a82e553cb8a1f41027bb3c3e309b3f6804 "USB: When | ||
31 | hot reset for USB3 fails, try warm reset." | ||
32 | |||
33 | Signed-off-by: Stanislaw Ledwon <staszek.ledwon@linux.intel.com> | ||
34 | Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> | ||
35 | Acked-by: Andiry Xu <andiry.xu@amd.com> | ||
36 | Signed-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 | |||
43 | diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c | ||
44 | index 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); | ||
88 | diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c | ||
89 | index 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; | ||
151 | diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h | ||
152 | index 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 | -- | ||
169 | 1.7.7.6 | ||
170 | |||