diff options
author | Matthew Garrett <mjg@redhat.com> | 2012-05-11 04:08:27 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-05-11 20:06:13 -0400 |
commit | da0af6e78ef311d97754aa03e10eade82cc99e16 (patch) | |
tree | 52d904e831d619452299844c7f55b61be2d62a53 | |
parent | 38ac0f1b90dc9486cc039f1a4d8b0202813e5b67 (diff) |
usb: Bind devices to ACPI devices when possible
Built-in USB devices will typically have a representation in the system
ACPI tables. Add support for binding the two together so the USB code can
make use of the associated methods.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
Signed-off-by: Lan Tianyu <tianyu.lan@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/usb/core/Makefile | 1 | ||||
-rw-r--r-- | drivers/usb/core/usb-acpi.c | 60 | ||||
-rw-r--r-- | drivers/usb/core/usb.c | 6 | ||||
-rw-r--r-- | drivers/usb/core/usb.h | 7 |
4 files changed, 74 insertions, 0 deletions
diff --git a/drivers/usb/core/Makefile b/drivers/usb/core/Makefile index c4ea846d3c0..26059b93dbf 100644 --- a/drivers/usb/core/Makefile +++ b/drivers/usb/core/Makefile | |||
@@ -9,5 +9,6 @@ usbcore-y += config.o file.o buffer.o sysfs.o endpoint.o | |||
9 | usbcore-y += devio.o notify.o generic.o quirks.o devices.o | 9 | usbcore-y += devio.o notify.o generic.o quirks.o devices.o |
10 | 10 | ||
11 | usbcore-$(CONFIG_PCI) += hcd-pci.o | 11 | usbcore-$(CONFIG_PCI) += hcd-pci.o |
12 | usbcore-$(CONFIG_ACPI) += usb-acpi.o | ||
12 | 13 | ||
13 | obj-$(CONFIG_USB) += usbcore.o | 14 | obj-$(CONFIG_USB) += usbcore.o |
diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c new file mode 100644 index 00000000000..cab5cb7c256 --- /dev/null +++ b/drivers/usb/core/usb-acpi.c | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * USB-ACPI glue code | ||
3 | * | ||
4 | * Copyright 2012 Red Hat <mjg@redhat.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the Free | ||
8 | * Software Foundation, version 2. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/usb.h> | ||
13 | #include <linux/device.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/acpi.h> | ||
17 | #include <linux/pci.h> | ||
18 | #include <acpi/acpi_bus.h> | ||
19 | |||
20 | #include "usb.h" | ||
21 | |||
22 | static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) | ||
23 | { | ||
24 | struct usb_device *udev; | ||
25 | struct device *parent; | ||
26 | acpi_handle *parent_handle; | ||
27 | |||
28 | if (!is_usb_device(dev)) | ||
29 | return -ENODEV; | ||
30 | |||
31 | udev = to_usb_device(dev); | ||
32 | parent = dev->parent; | ||
33 | parent_handle = DEVICE_ACPI_HANDLE(parent); | ||
34 | |||
35 | if (!parent_handle) | ||
36 | return -ENODEV; | ||
37 | |||
38 | *handle = acpi_get_child(parent_handle, udev->portnum); | ||
39 | |||
40 | if (!*handle) | ||
41 | return -ENODEV; | ||
42 | |||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | static struct acpi_bus_type usb_acpi_bus = { | ||
47 | .bus = &usb_bus_type, | ||
48 | .find_bridge = NULL, | ||
49 | .find_device = usb_acpi_find_device, | ||
50 | }; | ||
51 | |||
52 | int usb_acpi_register(void) | ||
53 | { | ||
54 | return register_acpi_bus_type(&usb_acpi_bus); | ||
55 | } | ||
56 | |||
57 | void usb_acpi_unregister(void) | ||
58 | { | ||
59 | unregister_acpi_bus_type(&usb_acpi_bus); | ||
60 | } | ||
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 0ce862bfdd7..7998a67503c 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c | |||
@@ -1015,6 +1015,9 @@ static int __init usb_init(void) | |||
1015 | if (retval) | 1015 | if (retval) |
1016 | goto out; | 1016 | goto out; |
1017 | 1017 | ||
1018 | retval = usb_acpi_register(); | ||
1019 | if (retval) | ||
1020 | goto acpi_register_failed; | ||
1018 | retval = bus_register(&usb_bus_type); | 1021 | retval = bus_register(&usb_bus_type); |
1019 | if (retval) | 1022 | if (retval) |
1020 | goto bus_register_failed; | 1023 | goto bus_register_failed; |
@@ -1049,6 +1052,8 @@ major_init_failed: | |||
1049 | bus_notifier_failed: | 1052 | bus_notifier_failed: |
1050 | bus_unregister(&usb_bus_type); | 1053 | bus_unregister(&usb_bus_type); |
1051 | bus_register_failed: | 1054 | bus_register_failed: |
1055 | usb_acpi_unregister(); | ||
1056 | acpi_register_failed: | ||
1052 | usb_debugfs_cleanup(); | 1057 | usb_debugfs_cleanup(); |
1053 | out: | 1058 | out: |
1054 | return retval; | 1059 | return retval; |
@@ -1070,6 +1075,7 @@ static void __exit usb_exit(void) | |||
1070 | usb_hub_cleanup(); | 1075 | usb_hub_cleanup(); |
1071 | bus_unregister_notifier(&usb_bus_type, &usb_bus_nb); | 1076 | bus_unregister_notifier(&usb_bus_type, &usb_bus_nb); |
1072 | bus_unregister(&usb_bus_type); | 1077 | bus_unregister(&usb_bus_type); |
1078 | usb_acpi_unregister(); | ||
1073 | usb_debugfs_cleanup(); | 1079 | usb_debugfs_cleanup(); |
1074 | } | 1080 | } |
1075 | 1081 | ||
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 71648dcbe43..5c5c538ea73 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h | |||
@@ -156,3 +156,10 @@ extern void usb_notify_remove_device(struct usb_device *udev); | |||
156 | extern void usb_notify_add_bus(struct usb_bus *ubus); | 156 | extern void usb_notify_add_bus(struct usb_bus *ubus); |
157 | extern void usb_notify_remove_bus(struct usb_bus *ubus); | 157 | extern void usb_notify_remove_bus(struct usb_bus *ubus); |
158 | 158 | ||
159 | #ifdef CONFIG_ACPI | ||
160 | extern int usb_acpi_register(void); | ||
161 | extern void usb_acpi_unregister(void); | ||
162 | #else | ||
163 | static inline int usb_acpi_register(void) { return 0; }; | ||
164 | static inline void usb_acpi_unregister(void) { }; | ||
165 | #endif | ||