Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 248796
b: refs/heads/master
c: 0ed9a57
h: refs/heads/master
v: v3
  • Loading branch information
Andiry Xu authored and Sarah Sharp committed May 2, 2011
1 parent 26c4bc5 commit 000c30b
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 28 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2c44178032b046c4113c40d0d459a0d36e39b920
refs/heads/master: 0ed9a57e052a3d20df052a2ff12a3b42380867aa
52 changes: 37 additions & 15 deletions trunk/drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,15 +379,6 @@ static int hub_port_status(struct usb_hub *hub, int port1,
*status = le16_to_cpu(hub->status->port.wPortStatus);
*change = le16_to_cpu(hub->status->port.wPortChange);

if ((hub->hdev->parent != NULL) &&
hub_is_superspeed(hub->hdev)) {
/* Translate the USB 3 port status */
u16 tmp = *status & USB_SS_PORT_STAT_MASK;
if (*status & USB_SS_PORT_STAT_POWER)
tmp |= USB_PORT_STAT_POWER;
*status = tmp;
}

ret = 0;
}
mutex_unlock(&hub->status_mutex);
Expand Down Expand Up @@ -2160,11 +2151,40 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
return status;
}

/* Check if a port is power on */
static int port_is_power_on(struct usb_hub *hub, unsigned portstatus)
{
int ret = 0;

if (hub_is_superspeed(hub->hdev)) {
if (portstatus & USB_SS_PORT_STAT_POWER)
ret = 1;
} else {
if (portstatus & USB_PORT_STAT_POWER)
ret = 1;
}

return ret;
}

#ifdef CONFIG_PM

#define MASK_BITS (USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION | \
USB_PORT_STAT_SUSPEND)
#define WANT_BITS (USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION)
/* Check if a port is suspended(USB2.0 port) or in U3 state(USB3.0 port) */
static int port_is_suspended(struct usb_hub *hub, unsigned portstatus)
{
int ret = 0;

if (hub_is_superspeed(hub->hdev)) {
if ((portstatus & USB_PORT_STAT_LINK_STATE)
== USB_SS_PORT_LS_U3)
ret = 1;
} else {
if (portstatus & USB_PORT_STAT_SUSPEND)
ret = 1;
}

return ret;
}

/* Determine whether the device on a port is ready for a normal resume,
* is ready for a reset-resume, or should be disconnected.
Expand All @@ -2174,7 +2194,9 @@ static int check_port_resume_type(struct usb_device *udev,
int status, unsigned portchange, unsigned portstatus)
{
/* Is the device still present? */
if (status || (portstatus & MASK_BITS) != WANT_BITS) {
if (status || port_is_suspended(hub, portstatus) ||
!port_is_power_on(hub, portstatus) ||
!(portstatus & USB_PORT_STAT_CONNECTION)) {
if (status >= 0)
status = -ENODEV;
}
Expand Down Expand Up @@ -2439,7 +2461,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg)

/* Skip the initial Clear-Suspend step for a remote wakeup */
status = hub_port_status(hub, port1, &portstatus, &portchange);
if (status == 0 && !(portstatus & USB_PORT_STAT_SUSPEND))
if (status == 0 && !port_is_suspended(hub, portstatus))
goto SuspendCleared;

// dev_dbg(hub->intfdev, "resume port %d\n", port1);
Expand Down Expand Up @@ -3147,7 +3169,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,

/* maybe switch power back on (e.g. root hub was reset) */
if ((wHubCharacteristics & HUB_CHAR_LPSM) < 2
&& !(portstatus & USB_PORT_STAT_POWER))
&& !port_is_power_on(hub, portstatus))
set_port_feature(hdev, port1, USB_PORT_FEAT_POWER);

if (portstatus & USB_PORT_STAT_ENABLE)
Expand Down
41 changes: 29 additions & 12 deletions trunk/drivers/usb/host/xhci-hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,23 +431,28 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
}
xhci_dbg(xhci, "get port status, actual port %d status = 0x%x\n", wIndex, temp);

/* FIXME - should we return a port status value like the USB
* 3.0 external hubs do?
*/
/* wPortChange bits */
if (temp & PORT_CSC)
status |= USB_PORT_STAT_C_CONNECTION << 16;
if (temp & PORT_PEC)
status |= USB_PORT_STAT_C_ENABLE << 16;
if ((temp & PORT_OCC))
status |= USB_PORT_STAT_C_OVERCURRENT << 16;
/*
* FIXME ignoring reset and USB 2.1/3.0 specific
* changes
*/
if ((temp & PORT_PLS_MASK) == XDEV_U3
&& (temp & PORT_POWER))
status |= 1 << USB_PORT_FEAT_SUSPEND;
if ((temp & PORT_RC))
status |= USB_PORT_STAT_C_RESET << 16;
/* USB3.0 only */
if (hcd->speed == HCD_USB3) {
if ((temp & PORT_PLC))
status |= USB_PORT_STAT_C_LINK_STATE << 16;
if ((temp & PORT_WRC))
status |= USB_PORT_STAT_C_BH_RESET << 16;
}

if (hcd->speed != HCD_USB3) {
if ((temp & PORT_PLS_MASK) == XDEV_U3
&& (temp & PORT_POWER))
status |= USB_PORT_STAT_SUSPEND;
}
if ((temp & PORT_PLS_MASK) == XDEV_RESUME) {
if ((temp & PORT_RESET) || !(temp & PORT_PE))
goto error;
Expand Down Expand Up @@ -490,8 +495,20 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
status |= USB_PORT_STAT_OVERCURRENT;
if (temp & PORT_RESET)
status |= USB_PORT_STAT_RESET;
if (temp & PORT_POWER)
status |= USB_PORT_STAT_POWER;
if (temp & PORT_POWER) {
if (hcd->speed == HCD_USB3)
status |= USB_SS_PORT_STAT_POWER;
else
status |= USB_PORT_STAT_POWER;
}
/* Port Link State */
if (hcd->speed == HCD_USB3) {
/* resume state is a xHCI internal state.
* Do not report it to usb core.
*/
if ((temp & PORT_PLS_MASK) != XDEV_RESUME)
status |= (temp & PORT_PLS_MASK);
}
if (bus_state->port_c_suspend & (1 << wIndex))
status |= 1 << USB_PORT_FEAT_C_SUSPEND;
xhci_dbg(xhci, "Get port status returned 0x%x\n", status);
Expand Down

0 comments on commit 000c30b

Please sign in to comment.