aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
authorAndiry Xu <andiry.xu@amd.com>2011-04-27 06:07:43 -0400
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2011-05-02 19:42:53 -0400
commit0ed9a57e052a3d20df052a2ff12a3b42380867aa (patch)
tree3e9f2abb102045cbd162a7ebe8563d4e9ee47148 /drivers/usb/core
parent2c44178032b046c4113c40d0d459a0d36e39b920 (diff)
xHCI: report USB3.0 portstatus comply with USB3.0 specification
USB3.0 specification has different wPortStatus and wPortChange definitions from USB2.0 specification. Since USB3 root hub and USB2 root hub are split now and USB3 hub only has USB3 protocol ports, we should modify the portstatus and portchange report of USB3 ports to comply with USB3.0 specification. Signed-off-by: Andiry Xu <andiry.xu@amd.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/hub.c52
1 files changed, 37 insertions, 15 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 93720bdc9ef..dcd78c15f8c 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -379,15 +379,6 @@ static int hub_port_status(struct usb_hub *hub, int port1,
379 *status = le16_to_cpu(hub->status->port.wPortStatus); 379 *status = le16_to_cpu(hub->status->port.wPortStatus);
380 *change = le16_to_cpu(hub->status->port.wPortChange); 380 *change = le16_to_cpu(hub->status->port.wPortChange);
381 381
382 if ((hub->hdev->parent != NULL) &&
383 hub_is_superspeed(hub->hdev)) {
384 /* Translate the USB 3 port status */
385 u16 tmp = *status & USB_SS_PORT_STAT_MASK;
386 if (*status & USB_SS_PORT_STAT_POWER)
387 tmp |= USB_PORT_STAT_POWER;
388 *status = tmp;
389 }
390
391 ret = 0; 382 ret = 0;
392 } 383 }
393 mutex_unlock(&hub->status_mutex); 384 mutex_unlock(&hub->status_mutex);
@@ -2160,11 +2151,40 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
2160 return status; 2151 return status;
2161} 2152}
2162 2153
2154/* Check if a port is power on */
2155static int port_is_power_on(struct usb_hub *hub, unsigned portstatus)
2156{
2157 int ret = 0;
2158
2159 if (hub_is_superspeed(hub->hdev)) {
2160 if (portstatus & USB_SS_PORT_STAT_POWER)
2161 ret = 1;
2162 } else {
2163 if (portstatus & USB_PORT_STAT_POWER)
2164 ret = 1;
2165 }
2166
2167 return ret;
2168}
2169
2163#ifdef CONFIG_PM 2170#ifdef CONFIG_PM
2164 2171
2165#define MASK_BITS (USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION | \ 2172/* Check if a port is suspended(USB2.0 port) or in U3 state(USB3.0 port) */
2166 USB_PORT_STAT_SUSPEND) 2173static int port_is_suspended(struct usb_hub *hub, unsigned portstatus)
2167#define WANT_BITS (USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION) 2174{
2175 int ret = 0;
2176
2177 if (hub_is_superspeed(hub->hdev)) {
2178 if ((portstatus & USB_PORT_STAT_LINK_STATE)
2179 == USB_SS_PORT_LS_U3)
2180 ret = 1;
2181 } else {
2182 if (portstatus & USB_PORT_STAT_SUSPEND)
2183 ret = 1;
2184 }
2185
2186 return ret;
2187}
2168 2188
2169/* Determine whether the device on a port is ready for a normal resume, 2189/* Determine whether the device on a port is ready for a normal resume,
2170 * is ready for a reset-resume, or should be disconnected. 2190 * is ready for a reset-resume, or should be disconnected.
@@ -2174,7 +2194,9 @@ static int check_port_resume_type(struct usb_device *udev,
2174 int status, unsigned portchange, unsigned portstatus) 2194 int status, unsigned portchange, unsigned portstatus)
2175{ 2195{
2176 /* Is the device still present? */ 2196 /* Is the device still present? */
2177 if (status || (portstatus & MASK_BITS) != WANT_BITS) { 2197 if (status || port_is_suspended(hub, portstatus) ||
2198 !port_is_power_on(hub, portstatus) ||
2199 !(portstatus & USB_PORT_STAT_CONNECTION)) {
2178 if (status >= 0) 2200 if (status >= 0)
2179 status = -ENODEV; 2201 status = -ENODEV;
2180 } 2202 }
@@ -2439,7 +2461,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)
2439 2461
2440 /* Skip the initial Clear-Suspend step for a remote wakeup */ 2462 /* Skip the initial Clear-Suspend step for a remote wakeup */
2441 status = hub_port_status(hub, port1, &portstatus, &portchange); 2463 status = hub_port_status(hub, port1, &portstatus, &portchange);
2442 if (status == 0 && !(portstatus & USB_PORT_STAT_SUSPEND)) 2464 if (status == 0 && !port_is_suspended(hub, portstatus))
2443 goto SuspendCleared; 2465 goto SuspendCleared;
2444 2466
2445 // dev_dbg(hub->intfdev, "resume port %d\n", port1); 2467 // dev_dbg(hub->intfdev, "resume port %d\n", port1);
@@ -3147,7 +3169,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
3147 3169
3148 /* maybe switch power back on (e.g. root hub was reset) */ 3170 /* maybe switch power back on (e.g. root hub was reset) */
3149 if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2 3171 if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
3150 && !(portstatus & USB_PORT_STAT_POWER)) 3172 && !port_is_power_on(hub, portstatus))
3151 set_port_feature(hdev, port1, USB_PORT_FEAT_POWER); 3173 set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);
3152 3174
3153 if (portstatus & USB_PORT_STAT_ENABLE) 3175 if (portstatus & USB_PORT_STAT_ENABLE)