Skip to content

Commit

Permalink
USB: Set usb port's DeviceRemovable according acpi information
Browse files Browse the repository at this point in the history
ACPI provide "_PLD" and "_UPC" aml methods to describe usb port
visibility and connectability. This patch is to add usb_hub_adjust_DeviceRemovable()
to adjust usb hub port's DeviceRemovable according ACPI information and invoke it in
the rh_call_control(). When hub descriptor request is issued at first time,
usb port device isn't created and usb port is not bound with acpi. So first
hub descriptor request is not changed based on ACPI information. After usb
port devices being created, call usb_hub_adjust_DeviceRemovable in the hub_configure()
and then set hub port's DeviceRemovable according ACPI information and this also works
for non-root hub.

Acked-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Lan Tianyu <tianyu.lan@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Lan Tianyu authored and Greg Kroah-Hartman committed Jan 21, 2013
1 parent 5c6e9bf commit d2123fd
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 0 deletions.
4 changes: 4 additions & 0 deletions drivers/usb/core/hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -619,6 +619,10 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb)
status = hcd->driver->hub_control (hcd,
typeReq, wValue, wIndex,
tbuf, wLength);

if (typeReq == GetHubDescriptor)
usb_hub_adjust_deviceremovable(hcd->self.root_hub,
(struct usb_hub_descriptor *)tbuf);
break;
error:
/* "protocol stall" on error */
Expand Down
43 changes: 43 additions & 0 deletions drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -1513,6 +1513,8 @@ static int hub_configure(struct usb_hub *hub,
dev_err(hub->intfdev,
"couldn't create port%d device.\n", i + 1);

usb_hub_adjust_deviceremovable(hdev, hub->descriptor);

hub_activate(hub, HUB_INIT);
return 0;

Expand Down Expand Up @@ -5219,6 +5221,47 @@ usb_get_hub_port_connect_type(struct usb_device *hdev, int port1)
return hub->ports[port1 - 1]->connect_type;
}

void usb_hub_adjust_deviceremovable(struct usb_device *hdev,
struct usb_hub_descriptor *desc)
{
enum usb_port_connect_type connect_type;
int i;

if (!hub_is_superspeed(hdev)) {
for (i = 1; i <= hdev->maxchild; i++) {
connect_type = usb_get_hub_port_connect_type(hdev, i);

if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) {
u8 mask = 1 << (i%8);

if (!(desc->u.hs.DeviceRemovable[i/8] & mask)) {
dev_dbg(&hdev->dev, "usb port%d's DeviceRemovable is changed to 1 according to platform information.\n",
i);
desc->u.hs.DeviceRemovable[i/8] |= mask;
}
}
}
} else {
u16 port_removable = le16_to_cpu(desc->u.ss.DeviceRemovable);

for (i = 1; i <= hdev->maxchild; i++) {
connect_type = usb_get_hub_port_connect_type(hdev, i);

if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) {
u16 mask = 1 << i;

if (!(port_removable & mask)) {
dev_dbg(&hdev->dev, "usb port%d's DeviceRemovable is changed to 1 according to platform information.\n",
i);
port_removable |= mask;
}
}
}

desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable);
}
}

#ifdef CONFIG_ACPI
/**
* usb_get_hub_port_acpi_handle - Get the usb port's acpi handle
Expand Down
3 changes: 3 additions & 0 deletions drivers/usb/core/usb.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include <linux/pm.h>
#include <linux/acpi.h>

struct usb_hub_descriptor;
struct dev_state;

/* Functions local to drivers/usb/core/ */
Expand Down Expand Up @@ -182,6 +183,8 @@ extern enum usb_port_connect_type
usb_get_hub_port_connect_type(struct usb_device *hdev, int port1);
extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1,
enum usb_port_connect_type type);
extern void usb_hub_adjust_deviceremovable(struct usb_device *hdev,
struct usb_hub_descriptor *desc);

#ifdef CONFIG_ACPI
extern int usb_acpi_register(void);
Expand Down

0 comments on commit d2123fd

Please sign in to comment.