From 1d1343e8149e1c9a788a815aeccfe844ba5abe93 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Wed, 5 Sep 2012 13:44:33 +0800 Subject: [PATCH] --- yaml --- r: 325861 b: refs/heads/master c: d557542421da643358201664903e67fd01dfca1a h: refs/heads/master i: 325859: 1f0c0dfd216082f95124decc952f898746d048d8 v: v3 --- [refs] | 2 +- trunk/drivers/usb/core/hub.c | 18 +++++++++ trunk/drivers/usb/core/usb-acpi.c | 67 ++++++++++++++++++++++++------- trunk/drivers/usb/core/usb.h | 9 +++++ 4 files changed, 80 insertions(+), 16 deletions(-) diff --git a/[refs] b/[refs] index e7ce45b9141a..2106333884f8 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: ff823c79a5c33194c2e5594f7c4686ea3547910c +refs/heads/master: d557542421da643358201664903e67fd01dfca1a diff --git a/trunk/drivers/usb/core/hub.c b/trunk/drivers/usb/core/hub.c index cdbade148995..3341b55f495c 100644 --- a/trunk/drivers/usb/core/hub.c +++ b/trunk/drivers/usb/core/hub.c @@ -5077,3 +5077,21 @@ struct usb_device *usb_hub_find_child(struct usb_device *hdev, return hub->ports[port1 - 1]->child; } EXPORT_SYMBOL_GPL(usb_hub_find_child); + +#ifdef CONFIG_ACPI +/** + * usb_get_hub_port_acpi_handle - Get the usb port's acpi handle + * @hdev: USB device belonging to the usb hub + * @port1: port num of the port + * + * Return port's acpi handle if successful, NULL if params are + * invaild. + */ +acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev, + int port1) +{ + struct usb_hub *hub = hdev_to_hub(hdev); + + return DEVICE_ACPI_HANDLE(&hub->ports[port1 - 1]->dev); +} +#endif diff --git a/trunk/drivers/usb/core/usb-acpi.c b/trunk/drivers/usb/core/usb-acpi.c index 8947b203d5a4..47197bf0b28d 100644 --- a/trunk/drivers/usb/core/usb-acpi.c +++ b/trunk/drivers/usb/core/usb-acpi.c @@ -70,22 +70,59 @@ static int usb_acpi_check_pld(struct usb_device *udev, acpi_handle handle) static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) { struct usb_device *udev; - struct device *parent; acpi_handle *parent_handle; + int port_num; - if (!is_usb_device(dev)) - return -ENODEV; - - udev = to_usb_device(dev); - parent = dev->parent; - parent_handle = DEVICE_ACPI_HANDLE(parent); - - if (!parent_handle) - return -ENODEV; - - *handle = acpi_get_child(parent_handle, udev->portnum); - - if (!*handle) + /* + * In the ACPI DSDT table, only usb root hub and usb ports are + * acpi device nodes. The hierarchy like following. + * Device (EHC1) + * Device (HUBN) + * Device (PR01) + * Device (PR11) + * Device (PR12) + * Device (PR13) + * ... + * So all binding process is divided into two parts. binding + * root hub and usb ports. + */ + if (is_usb_device(dev)) { + udev = to_usb_device(dev); + if (udev->parent) + return -ENODEV; + /* root hub's parent is the usb hcd. */ + parent_handle = DEVICE_ACPI_HANDLE(dev->parent); + *handle = acpi_get_child(parent_handle, udev->portnum); + if (!*handle) + return -ENODEV; + return 0; + } else if (is_usb_port(dev)) { + sscanf(dev_name(dev), "port%d", &port_num); + /* Get the struct usb_device point of port's hub */ + udev = to_usb_device(dev->parent->parent); + + /* + * The root hub ports' parent is the root hub. The non-root-hub + * ports' parent is the parent hub port which the hub is + * connected to. + */ + if (!udev->parent) { + *handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev), + port_num); + if (!*handle) + return -ENODEV; + } else { + parent_handle = + usb_get_hub_port_acpi_handle(udev->parent, + udev->portnum); + if (!parent_handle) + return -ENODEV; + + *handle = acpi_get_child(parent_handle, port_num); + if (!*handle) + return -ENODEV; + } + } else return -ENODEV; /* @@ -102,7 +139,7 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) static struct acpi_bus_type usb_acpi_bus = { .bus = &usb_bus_type, - .find_bridge = NULL, + .find_bridge = usb_acpi_find_device, .find_device = usb_acpi_find_device, }; diff --git a/trunk/drivers/usb/core/usb.h b/trunk/drivers/usb/core/usb.h index acb103c5c391..1633f6e99e35 100644 --- a/trunk/drivers/usb/core/usb.h +++ b/trunk/drivers/usb/core/usb.h @@ -1,4 +1,5 @@ #include +#include struct dev_state; @@ -115,6 +116,7 @@ extern struct bus_type usb_bus_type; extern struct device_type usb_device_type; extern struct device_type usb_if_device_type; extern struct device_type usb_ep_device_type; +extern struct device_type usb_port_device_type; extern struct usb_device_driver usb_generic_driver; static inline int is_usb_device(const struct device *dev) @@ -132,6 +134,11 @@ static inline int is_usb_endpoint(const struct device *dev) return dev->type == &usb_ep_device_type; } +static inline int is_usb_port(const struct device *dev) +{ + return dev->type == &usb_port_device_type; +} + /* Do the same for device drivers and interface drivers. */ static inline int is_usb_device_driver(struct device_driver *drv) @@ -166,6 +173,8 @@ extern void usb_notify_remove_bus(struct usb_bus *ubus); #ifdef CONFIG_ACPI extern int usb_acpi_register(void); extern void usb_acpi_unregister(void); +extern acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev, + int port1); #else static inline int usb_acpi_register(void) { return 0; }; static inline void usb_acpi_unregister(void) { };