From: Matthew Garrett Date: Fri, 11 May 2012 08:08:27 +0000 (+0800) Subject: usb: Bind devices to ACPI devices when possible X-Git-Tag: v3.5-rc1~149^2~61 X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=da0af6e78ef311d97754aa03e10eade82cc99e16;p=~emulex%2Finfiniband.git 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 Signed-off-by: Lan Tianyu Signed-off-by: Greg Kroah-Hartman --- 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 usbcore-y += devio.o notify.o generic.o quirks.o devices.o usbcore-$(CONFIG_PCI) += hcd-pci.o +usbcore-$(CONFIG_ACPI) += usb-acpi.o 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 @@ +/* + * USB-ACPI glue code + * + * Copyright 2012 Red Hat + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation, version 2. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "usb.h" + +static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) +{ + struct usb_device *udev; + struct device *parent; + acpi_handle *parent_handle; + + 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) + return -ENODEV; + + return 0; +} + +static struct acpi_bus_type usb_acpi_bus = { + .bus = &usb_bus_type, + .find_bridge = NULL, + .find_device = usb_acpi_find_device, +}; + +int usb_acpi_register(void) +{ + return register_acpi_bus_type(&usb_acpi_bus); +} + +void usb_acpi_unregister(void) +{ + unregister_acpi_bus_type(&usb_acpi_bus); +} 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) if (retval) goto out; + retval = usb_acpi_register(); + if (retval) + goto acpi_register_failed; retval = bus_register(&usb_bus_type); if (retval) goto bus_register_failed; @@ -1049,6 +1052,8 @@ major_init_failed: bus_notifier_failed: bus_unregister(&usb_bus_type); bus_register_failed: + usb_acpi_unregister(); +acpi_register_failed: usb_debugfs_cleanup(); out: return retval; @@ -1070,6 +1075,7 @@ static void __exit usb_exit(void) usb_hub_cleanup(); bus_unregister_notifier(&usb_bus_type, &usb_bus_nb); bus_unregister(&usb_bus_type); + usb_acpi_unregister(); usb_debugfs_cleanup(); } 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); extern void usb_notify_add_bus(struct usb_bus *ubus); 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); +#else +static inline int usb_acpi_register(void) { return 0; }; +static inline void usb_acpi_unregister(void) { }; +#endif