aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
authorLan Tianyu <tianyu.lan@intel.com>2013-01-21 09:18:00 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-01-21 16:22:03 -0500
commitd2123fd9e1a56b8006986ed37e0aaf93ef0dd978 (patch)
tree2c48de8b3450bda69a6926e9e7e53b551a74a1b4 /drivers/usb/core
parent5c6e9bf011bca072648017477b0fe36402be1415 (diff)
USB: Set usb port's DeviceRemovable according acpi information
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>
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/hcd.c4
-rw-r--r--drivers/usb/core/hub.c43
-rw-r--r--drivers/usb/core/usb.h3
3 files changed, 50 insertions, 0 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 5f6da8b2d6a1..2459896d040a 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -619,6 +619,10 @@ nongeneric:
619 status = hcd->driver->hub_control (hcd, 619 status = hcd->driver->hub_control (hcd,
620 typeReq, wValue, wIndex, 620 typeReq, wValue, wIndex,
621 tbuf, wLength); 621 tbuf, wLength);
622
623 if (typeReq == GetHubDescriptor)
624 usb_hub_adjust_deviceremovable(hcd->self.root_hub,
625 (struct usb_hub_descriptor *)tbuf);
622 break; 626 break;
623error: 627error:
624 /* "protocol stall" on error */ 628 /* "protocol stall" on error */
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index cfdd4eecc5a9..29ca6ed3bea8 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1513,6 +1513,8 @@ static int hub_configure(struct usb_hub *hub,
1513 dev_err(hub->intfdev, 1513 dev_err(hub->intfdev,
1514 "couldn't create port%d device.\n", i + 1); 1514 "couldn't create port%d device.\n", i + 1);
1515 1515
1516 usb_hub_adjust_deviceremovable(hdev, hub->descriptor);
1517
1516 hub_activate(hub, HUB_INIT); 1518 hub_activate(hub, HUB_INIT);
1517 return 0; 1519 return 0;
1518 1520
@@ -5219,6 +5221,47 @@ usb_get_hub_port_connect_type(struct usb_device *hdev, int port1)
5219 return hub->ports[port1 - 1]->connect_type; 5221 return hub->ports[port1 - 1]->connect_type;
5220} 5222}
5221 5223
5224void usb_hub_adjust_deviceremovable(struct usb_device *hdev,
5225 struct usb_hub_descriptor *desc)
5226{
5227 enum usb_port_connect_type connect_type;
5228 int i;
5229
5230 if (!hub_is_superspeed(hdev)) {
5231 for (i = 1; i <= hdev->maxchild; i++) {
5232 connect_type = usb_get_hub_port_connect_type(hdev, i);
5233
5234 if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) {
5235 u8 mask = 1 << (i%8);
5236
5237 if (!(desc->u.hs.DeviceRemovable[i/8] & mask)) {
5238 dev_dbg(&hdev->dev, "usb port%d's DeviceRemovable is changed to 1 according to platform information.\n",
5239 i);
5240 desc->u.hs.DeviceRemovable[i/8] |= mask;
5241 }
5242 }
5243 }
5244 } else {
5245 u16 port_removable = le16_to_cpu(desc->u.ss.DeviceRemovable);
5246
5247 for (i = 1; i <= hdev->maxchild; i++) {
5248 connect_type = usb_get_hub_port_connect_type(hdev, i);
5249
5250 if (connect_type == USB_PORT_CONNECT_TYPE_HARD_WIRED) {
5251 u16 mask = 1 << i;
5252
5253 if (!(port_removable & mask)) {
5254 dev_dbg(&hdev->dev, "usb port%d's DeviceRemovable is changed to 1 according to platform information.\n",
5255 i);
5256 port_removable |= mask;
5257 }
5258 }
5259 }
5260
5261 desc->u.ss.DeviceRemovable = cpu_to_le16(port_removable);
5262 }
5263}
5264
5222#ifdef CONFIG_ACPI 5265#ifdef CONFIG_ACPI
5223/** 5266/**
5224 * usb_get_hub_port_acpi_handle - Get the usb port's acpi handle 5267 * usb_get_hub_port_acpi_handle - Get the usb port's acpi handle
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index fb7d8fcb4551..a7f20bde0e5e 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -1,6 +1,7 @@
1#include <linux/pm.h> 1#include <linux/pm.h>
2#include <linux/acpi.h> 2#include <linux/acpi.h>
3 3
4struct usb_hub_descriptor;
4struct dev_state; 5struct dev_state;
5 6
6/* Functions local to drivers/usb/core/ */ 7/* Functions local to drivers/usb/core/ */
@@ -182,6 +183,8 @@ extern enum usb_port_connect_type
182 usb_get_hub_port_connect_type(struct usb_device *hdev, int port1); 183 usb_get_hub_port_connect_type(struct usb_device *hdev, int port1);
183extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, 184extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1,
184 enum usb_port_connect_type type); 185 enum usb_port_connect_type type);
186extern void usb_hub_adjust_deviceremovable(struct usb_device *hdev,
187 struct usb_hub_descriptor *desc);
185 188
186#ifdef CONFIG_ACPI 189#ifdef CONFIG_ACPI
187extern int usb_acpi_register(void); 190extern int usb_acpi_register(void);