diff options
author | Lan Tianyu <tianyu.lan@intel.com> | 2012-09-05 07:44:36 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-09-10 22:04:01 +0200 |
commit | f7ac7787ad361e31a7972e2854ed8dc2eedfac3b (patch) | |
tree | 370b620b012a42f0890c829793dcc6f705c39cad /drivers/usb/host | |
parent | xhci: Handle clear PORT_POWER feature. (diff) | |
download | linux-f7ac7787ad361e31a7972e2854ed8dc2eedfac3b.tar.xz linux-f7ac7787ad361e31a7972e2854ed8dc2eedfac3b.zip |
usb/acpi: Use ACPI methods to power off ports.
Upcoming Intel systems will have an ACPI method to control whether a USB
port can be completely powered off. The implication of powering off a
USB port is that the device and host sees a physical disconnect, and
subsequent port connections and remote wakeups will be lost.
Add a new function, usb_acpi_power_manageable(), that can be used to
find whether the usb port has ACPI power resources that can be used to
power on and off the port on these machines. Also add a new function
called usb_acpi_set_power_state() that controls the port power via these
ACPI methods.
When the USB core calls into the xHCI hub driver to power off a port,
check whether the port can be completely powered off via this new ACPI
mechanism. If so, call into these new ACPI methods. Also use the ACPI
methods when the USB core asks to power on a port.
Signed-off-by: Lan Tianyu <tianyu.lan@intel.com>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host')
-rw-r--r-- | drivers/usb/host/xhci-hub.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 03032b3e6ed2..630e9e6e06b5 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -766,6 +766,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = xhci_readl(xhci, port_array[wIndex]); xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n", wIndex, temp); + + temp = usb_acpi_power_manageable(hcd->self.root_hub, + wIndex); + if (temp) + usb_acpi_set_power_state(hcd->self.root_hub, + wIndex, true); break; case USB_PORT_FEAT_RESET: temp = (temp | PORT_RESET); @@ -868,6 +874,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, case USB_PORT_FEAT_POWER: xhci_writel(xhci, temp & ~PORT_POWER, port_array[wIndex]); + + temp = usb_acpi_power_manageable(hcd->self.root_hub, + wIndex); + if (temp) + usb_acpi_set_power_state(hcd->self.root_hub, + wIndex, false); break; default: goto error; |