summaryrefslogtreecommitdiff
path: root/drivers/acpi
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-03-03 22:35:20 +0100
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2013-03-04 14:23:40 +0100
commit53540098b23c3884b4a0b4f220b9d977bc496af3 (patch)
treefe86061c4772efaa92fbe68920f803ae4280b2d0 /drivers/acpi
parent9b27516fcd7ab7dc416edf418446c24c61729938 (diff)
downloadlwn-53540098b23c3884b4a0b4f220b9d977bc496af3.tar.gz
lwn-53540098b23c3884b4a0b4f220b9d977bc496af3.zip
ACPI / glue: Add .match() callback to struct acpi_bus_type
USB uses the .find_bridge() callback from struct acpi_bus_type incorrectly, because as a result of the way it is used by USB every device in the system that doesn't have a bus type or parent is passed to usb_acpi_find_device() for inspection. What USB actually needs, though, is to call usb_acpi_find_device() for USB ports that don't have a bus type defined, but have usb_port_device_type as their device type, as well as for USB devices. To fix that replace the struct bus_type pointer in struct acpi_bus_type used for matching devices to specific subsystems with a .match() callback to be used for this purpose and update the users of struct acpi_bus_type, including USB, accordingly. Define the .match() callback routine for USB, usb_acpi_bus_match(), in such a way that it will cover both USB devices and USB ports and remove the now redundant .find_bridge() callback pointer from usb_acpi_bus. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Acked-by: Yinghai Lu <yinghai@kernel.org> Acked-by: Jeff Garzik <jgarzik@pobox.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/glue.c39
1 files changed, 13 insertions, 26 deletions
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index ef6f155469b5..b94d14721af3 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -36,12 +36,11 @@ int register_acpi_bus_type(struct acpi_bus_type *type)
{
if (acpi_disabled)
return -ENODEV;
- if (type && type->bus && type->find_device) {
+ if (type && type->match && type->find_device) {
down_write(&bus_type_sem);
list_add_tail(&type->list, &bus_type_list);
up_write(&bus_type_sem);
- printk(KERN_INFO PREFIX "bus type %s registered\n",
- type->bus->name);
+ printk(KERN_INFO PREFIX "bus type %s registered\n", type->name);
return 0;
}
return -ENODEV;
@@ -56,24 +55,21 @@ int unregister_acpi_bus_type(struct acpi_bus_type *type)
down_write(&bus_type_sem);
list_del_init(&type->list);
up_write(&bus_type_sem);
- printk(KERN_INFO PREFIX "ACPI bus type %s unregistered\n",
- type->bus->name);
+ printk(KERN_INFO PREFIX "bus type %s unregistered\n",
+ type->name);
return 0;
}
return -ENODEV;
}
EXPORT_SYMBOL_GPL(unregister_acpi_bus_type);
-static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type)
+static struct acpi_bus_type *acpi_get_bus_type(struct device *dev)
{
struct acpi_bus_type *tmp, *ret = NULL;
- if (!type)
- return NULL;
-
down_read(&bus_type_sem);
list_for_each_entry(tmp, &bus_type_list, list) {
- if (tmp->bus == type) {
+ if (tmp->match(dev)) {
ret = tmp;
break;
}
@@ -261,26 +257,17 @@ err:
static int acpi_platform_notify(struct device *dev)
{
- struct acpi_bus_type *type;
+ struct acpi_bus_type *type = acpi_get_bus_type(dev);
acpi_handle handle;
int ret;
ret = acpi_bind_one(dev, NULL);
- if (ret && (!dev->bus || !dev->parent)) {
- /* bridge devices genernally haven't bus or parent */
- ret = acpi_find_bridge_device(dev, &handle);
- if (!ret) {
- ret = acpi_bind_one(dev, handle);
- if (ret)
- goto out;
- }
- }
-
- type = acpi_get_bus_type(dev->bus);
if (ret) {
- if (!type || !type->find_device) {
- DBG("No ACPI bus support for %s\n", dev_name(dev));
- ret = -EINVAL;
+ if (!type) {
+ ret = acpi_find_bridge_device(dev, &handle);
+ if (!ret)
+ ret = acpi_bind_one(dev, handle);
+
goto out;
}
@@ -316,7 +303,7 @@ static int acpi_platform_notify_remove(struct device *dev)
{
struct acpi_bus_type *type;
- type = acpi_get_bus_type(dev->bus);
+ type = acpi_get_bus_type(dev);
if (type && type->cleanup)
type->cleanup(dev);