Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 289440
b: refs/heads/master
c: 4296c70
h: refs/heads/master
v: v3
  • Loading branch information
Sarah Sharp committed Feb 14, 2012
1 parent 02cb5b4 commit b2216f7
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3b9b6acd4798aafe9b9f64ccb7e8eb76f27f904a
refs/heads/master: 4296c70a5ec316903ef037ed15f154dd3d354ad7
12 changes: 12 additions & 0 deletions trunk/drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -2731,6 +2731,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
struct usb_hub *hub = usb_get_intfdata (intf);
struct usb_device *hdev = hub->hdev;
unsigned port1;
int status;

/* Warn if children aren't already suspended */
for (port1 = 1; port1 <= hdev->maxchild; port1++) {
Expand All @@ -2743,6 +2744,17 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
return -EBUSY;
}
}
if (hub_is_superspeed(hdev) && hdev->do_remote_wakeup) {
/* Enable hub to send remote wakeup for all ports. */
for (port1 = 1; port1 <= hdev->maxchild; port1++) {
status = set_port_feature(hdev,
port1 |
USB_PORT_FEAT_REMOTE_WAKE_CONNECT |
USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT |
USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT,
USB_PORT_FEAT_REMOTE_WAKE_MASK);
}
}

dev_dbg(&intf->dev, "%s\n", __func__);

Expand Down
41 changes: 41 additions & 0 deletions trunk/drivers/usb/host/xhci-hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,32 @@ void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array,
xhci_writel(xhci, temp, port_array[port_id]);
}

void xhci_set_remote_wake_mask(struct xhci_hcd *xhci,
__le32 __iomem **port_array, int port_id, u16 wake_mask)
{
u32 temp;

temp = xhci_readl(xhci, port_array[port_id]);
temp = xhci_port_state_to_neutral(temp);

if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_CONNECT)
temp |= PORT_WKCONN_E;
else
temp &= ~PORT_WKCONN_E;

if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT)
temp |= PORT_WKDISC_E;
else
temp &= ~PORT_WKDISC_E;

if (wake_mask & USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT)
temp |= PORT_WKOC_E;
else
temp &= ~PORT_WKOC_E;

xhci_writel(xhci, temp, port_array[port_id]);
}

/* Test and clear port RWC bit */
void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,
int port_id, u32 port_bit)
Expand All @@ -448,6 +474,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
int slot_id;
struct xhci_bus_state *bus_state;
u16 link_state = 0;
u16 wake_mask = 0;

max_ports = xhci_get_ports(hcd, &port_array);
bus_state = &xhci->bus_state[hcd_index(hcd)];
Expand Down Expand Up @@ -593,6 +620,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
case SetPortFeature:
if (wValue == USB_PORT_FEAT_LINK_STATE)
link_state = (wIndex & 0xff00) >> 3;
if (wValue == USB_PORT_FEAT_REMOTE_WAKE_MASK)
wake_mask = wIndex & 0xff00;
wIndex &= 0xff;
if (!wIndex || wIndex > max_ports)
goto error;
Expand Down Expand Up @@ -703,6 +732,14 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
temp = xhci_readl(xhci, port_array[wIndex]);
xhci_dbg(xhci, "set port reset, actual port %d status = 0x%x\n", wIndex, temp);
break;
case USB_PORT_FEAT_REMOTE_WAKE_MASK:
xhci_set_remote_wake_mask(xhci, port_array,
wIndex, wake_mask);
temp = xhci_readl(xhci, port_array[wIndex]);
xhci_dbg(xhci, "set port remote wake mask, "
"actual port %d status = 0x%x\n",
wIndex, temp);
break;
case USB_PORT_FEAT_BH_PORT_RESET:
temp |= PORT_WR;
xhci_writel(xhci, temp, port_array[wIndex]);
Expand Down Expand Up @@ -883,6 +920,10 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
t2 |= PORT_LINK_STROBE | XDEV_U3;
set_bit(port_index, &bus_state->bus_suspended);
}
/* USB core sets remote wake mask for USB 3.0 hubs,
* including the USB 3.0 roothub, but only if CONFIG_USB_SUSPEND
* is enabled, so also enable remote wake here.
*/
if (hcd->self.root_hub->do_remote_wakeup) {
if (t1 & PORT_CONNECT) {
t2 |= PORT_WKOC_E | PORT_WKDISC_E;
Expand Down
5 changes: 5 additions & 0 deletions trunk/include/linux/usb/ch11.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@
#define USB_PORT_FEAT_C_BH_PORT_RESET 29
#define USB_PORT_FEAT_FORCE_LINKPM_ACCEPT 30

/* USB 3.0 hub remote wake mask bits, see table 10-14 */
#define USB_PORT_FEAT_REMOTE_WAKE_CONNECT (1 << 8)
#define USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT (1 << 9)
#define USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT (1 << 10)

/*
* Hub Status and Hub Change results
* See USB 2.0 spec Table 11-19 and Table 11-20
Expand Down

0 comments on commit b2216f7

Please sign in to comment.