aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLan Tianyu <tianyu.lan@intel.com>2012-09-05 01:44:33 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-09-10 16:02:02 -0400
commitd557542421da643358201664903e67fd01dfca1a (patch)
treed52248ce52d1f5c5f7223c5700f727f1a1a721f4
parentff823c79a5c33194c2e5594f7c4686ea3547910c (diff)
usb/acpi: Bind ACPI node to USB port, not usb_device.
In the ACPI DSDT table, only usb root hub and usb ports are ACPI device nodes. Originally, we bound the usb port's ACPI node to the usb device attached to the port. However, we want to access those ACPI port methods when the port is empty, and there's no usb_device associated with that port. Now that the usb port is a real device, we can bind the port's ACPI node to struct usb_port instead. 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>
-rw-r--r--drivers/usb/core/hub.c18
-rw-r--r--drivers/usb/core/usb-acpi.c67
-rw-r--r--drivers/usb/core/usb.h9
3 files changed, 79 insertions, 15 deletions
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index cdbade148995..3341b55f495c 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -5077,3 +5077,21 @@ struct usb_device *usb_hub_find_child(struct usb_device *hdev,
5077 return hub->ports[port1 - 1]->child; 5077 return hub->ports[port1 - 1]->child;
5078} 5078}
5079EXPORT_SYMBOL_GPL(usb_hub_find_child); 5079EXPORT_SYMBOL_GPL(usb_hub_find_child);
5080
5081#ifdef CONFIG_ACPI
5082/**
5083 * usb_get_hub_port_acpi_handle - Get the usb port's acpi handle
5084 * @hdev: USB device belonging to the usb hub
5085 * @port1: port num of the port
5086 *
5087 * Return port's acpi handle if successful, NULL if params are
5088 * invaild.
5089 */
5090acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev,
5091 int port1)
5092{
5093 struct usb_hub *hub = hdev_to_hub(hdev);
5094
5095 return DEVICE_ACPI_HANDLE(&hub->ports[port1 - 1]->dev);
5096}
5097#endif
diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c
index 8947b203d5a4..47197bf0b28d 100644
--- a/drivers/usb/core/usb-acpi.c
+++ b/drivers/usb/core/usb-acpi.c
@@ -70,22 +70,59 @@ static int usb_acpi_check_pld(struct usb_device *udev, acpi_handle handle)
70static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) 70static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)
71{ 71{
72 struct usb_device *udev; 72 struct usb_device *udev;
73 struct device *parent;
74 acpi_handle *parent_handle; 73 acpi_handle *parent_handle;
74 int port_num;
75 75
76 if (!is_usb_device(dev)) 76 /*
77 return -ENODEV; 77 * In the ACPI DSDT table, only usb root hub and usb ports are
78 78 * acpi device nodes. The hierarchy like following.
79 udev = to_usb_device(dev); 79 * Device (EHC1)
80 parent = dev->parent; 80 * Device (HUBN)
81 parent_handle = DEVICE_ACPI_HANDLE(parent); 81 * Device (PR01)
82 82 * Device (PR11)
83 if (!parent_handle) 83 * Device (PR12)
84 return -ENODEV; 84 * Device (PR13)
85 85 * ...
86 *handle = acpi_get_child(parent_handle, udev->portnum); 86 * So all binding process is divided into two parts. binding
87 87 * root hub and usb ports.
88 if (!*handle) 88 */
89 if (is_usb_device(dev)) {
90 udev = to_usb_device(dev);
91 if (udev->parent)
92 return -ENODEV;
93 /* root hub's parent is the usb hcd. */
94 parent_handle = DEVICE_ACPI_HANDLE(dev->parent);
95 *handle = acpi_get_child(parent_handle, udev->portnum);
96 if (!*handle)
97 return -ENODEV;
98 return 0;
99 } else if (is_usb_port(dev)) {
100 sscanf(dev_name(dev), "port%d", &port_num);
101 /* Get the struct usb_device point of port's hub */
102 udev = to_usb_device(dev->parent->parent);
103
104 /*
105 * The root hub ports' parent is the root hub. The non-root-hub
106 * ports' parent is the parent hub port which the hub is
107 * connected to.
108 */
109 if (!udev->parent) {
110 *handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev),
111 port_num);
112 if (!*handle)
113 return -ENODEV;
114 } else {
115 parent_handle =
116 usb_get_hub_port_acpi_handle(udev->parent,
117 udev->portnum);
118 if (!parent_handle)
119 return -ENODEV;
120
121 *handle = acpi_get_child(parent_handle, port_num);
122 if (!*handle)
123 return -ENODEV;
124 }
125 } else
89 return -ENODEV; 126 return -ENODEV;
90 127
91 /* 128 /*
@@ -102,7 +139,7 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)
102 139
103static struct acpi_bus_type usb_acpi_bus = { 140static struct acpi_bus_type usb_acpi_bus = {
104 .bus = &usb_bus_type, 141 .bus = &usb_bus_type,
105 .find_bridge = NULL, 142 .find_bridge = usb_acpi_find_device,
106 .find_device = usb_acpi_find_device, 143 .find_device = usb_acpi_find_device,
107}; 144};
108 145
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index acb103c5c391..1633f6e99e35 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -1,4 +1,5 @@
1#include <linux/pm.h> 1#include <linux/pm.h>
2#include <linux/acpi.h>
2 3
3struct dev_state; 4struct dev_state;
4 5
@@ -115,6 +116,7 @@ extern struct bus_type usb_bus_type;
115extern struct device_type usb_device_type; 116extern struct device_type usb_device_type;
116extern struct device_type usb_if_device_type; 117extern struct device_type usb_if_device_type;
117extern struct device_type usb_ep_device_type; 118extern struct device_type usb_ep_device_type;
119extern struct device_type usb_port_device_type;
118extern struct usb_device_driver usb_generic_driver; 120extern struct usb_device_driver usb_generic_driver;
119 121
120static inline int is_usb_device(const struct device *dev) 122static inline int is_usb_device(const struct device *dev)
@@ -132,6 +134,11 @@ static inline int is_usb_endpoint(const struct device *dev)
132 return dev->type == &usb_ep_device_type; 134 return dev->type == &usb_ep_device_type;
133} 135}
134 136
137static inline int is_usb_port(const struct device *dev)
138{
139 return dev->type == &usb_port_device_type;
140}
141
135/* Do the same for device drivers and interface drivers. */ 142/* Do the same for device drivers and interface drivers. */
136 143
137static inline int is_usb_device_driver(struct device_driver *drv) 144static inline int is_usb_device_driver(struct device_driver *drv)
@@ -166,6 +173,8 @@ extern void usb_notify_remove_bus(struct usb_bus *ubus);
166#ifdef CONFIG_ACPI 173#ifdef CONFIG_ACPI
167extern int usb_acpi_register(void); 174extern int usb_acpi_register(void);
168extern void usb_acpi_unregister(void); 175extern void usb_acpi_unregister(void);
176extern acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev,
177 int port1);
169#else 178#else
170static inline int usb_acpi_register(void) { return 0; }; 179static inline int usb_acpi_register(void) { return 0; };
171static inline void usb_acpi_unregister(void) { }; 180static inline void usb_acpi_unregister(void) { };