Commit 53540098 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

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: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Acked-by: default avatarYinghai Lu <yinghai@kernel.org>
Acked-by: default avatarJeff Garzik <jgarzik@pobox.com>
parent 9b27516f
...@@ -36,12 +36,11 @@ int register_acpi_bus_type(struct acpi_bus_type *type) ...@@ -36,12 +36,11 @@ int register_acpi_bus_type(struct acpi_bus_type *type)
{ {
if (acpi_disabled) if (acpi_disabled)
return -ENODEV; return -ENODEV;
if (type && type->bus && type->find_device) { if (type && type->match && type->find_device) {
down_write(&bus_type_sem); down_write(&bus_type_sem);
list_add_tail(&type->list, &bus_type_list); list_add_tail(&type->list, &bus_type_list);
up_write(&bus_type_sem); up_write(&bus_type_sem);
printk(KERN_INFO PREFIX "bus type %s registered\n", printk(KERN_INFO PREFIX "bus type %s registered\n", type->name);
type->bus->name);
return 0; return 0;
} }
return -ENODEV; return -ENODEV;
...@@ -56,24 +55,21 @@ int unregister_acpi_bus_type(struct acpi_bus_type *type) ...@@ -56,24 +55,21 @@ int unregister_acpi_bus_type(struct acpi_bus_type *type)
down_write(&bus_type_sem); down_write(&bus_type_sem);
list_del_init(&type->list); list_del_init(&type->list);
up_write(&bus_type_sem); up_write(&bus_type_sem);
printk(KERN_INFO PREFIX "ACPI bus type %s unregistered\n", printk(KERN_INFO PREFIX "bus type %s unregistered\n",
type->bus->name); type->name);
return 0; return 0;
} }
return -ENODEV; return -ENODEV;
} }
EXPORT_SYMBOL_GPL(unregister_acpi_bus_type); 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; struct acpi_bus_type *tmp, *ret = NULL;
if (!type)
return NULL;
down_read(&bus_type_sem); down_read(&bus_type_sem);
list_for_each_entry(tmp, &bus_type_list, list) { list_for_each_entry(tmp, &bus_type_list, list) {
if (tmp->bus == type) { if (tmp->match(dev)) {
ret = tmp; ret = tmp;
break; break;
} }
...@@ -261,26 +257,17 @@ static int acpi_unbind_one(struct device *dev) ...@@ -261,26 +257,17 @@ static int acpi_unbind_one(struct device *dev)
static int acpi_platform_notify(struct device *dev) 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; acpi_handle handle;
int ret; int ret;
ret = acpi_bind_one(dev, NULL); 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 (ret) {
if (!type || !type->find_device) { if (!type) {
DBG("No ACPI bus support for %s\n", dev_name(dev)); ret = acpi_find_bridge_device(dev, &handle);
ret = -EINVAL; if (!ret)
ret = acpi_bind_one(dev, handle);
goto out; goto out;
} }
...@@ -316,7 +303,7 @@ static int acpi_platform_notify_remove(struct device *dev) ...@@ -316,7 +303,7 @@ static int acpi_platform_notify_remove(struct device *dev)
{ {
struct acpi_bus_type *type; struct acpi_bus_type *type;
type = acpi_get_bus_type(dev->bus); type = acpi_get_bus_type(dev);
if (type && type->cleanup) if (type && type->cleanup)
type->cleanup(dev); type->cleanup(dev);
......
...@@ -1150,6 +1150,7 @@ static int ata_acpi_find_dummy(struct device *dev, acpi_handle *handle) ...@@ -1150,6 +1150,7 @@ static int ata_acpi_find_dummy(struct device *dev, acpi_handle *handle)
} }
static struct acpi_bus_type ata_acpi_bus = { static struct acpi_bus_type ata_acpi_bus = {
.name = "ATA",
.find_bridge = ata_acpi_find_dummy, .find_bridge = ata_acpi_find_dummy,
.find_device = ata_acpi_find_device, .find_device = ata_acpi_find_device,
}; };
......
...@@ -331,8 +331,14 @@ static void pci_acpi_cleanup(struct device *dev) ...@@ -331,8 +331,14 @@ static void pci_acpi_cleanup(struct device *dev)
} }
} }
static bool pci_acpi_bus_match(struct device *dev)
{
return dev->bus == &pci_bus_type;
}
static struct acpi_bus_type acpi_pci_bus = { static struct acpi_bus_type acpi_pci_bus = {
.bus = &pci_bus_type, .name = "PCI",
.match = pci_acpi_bus_match,
.find_device = acpi_pci_find_device, .find_device = acpi_pci_find_device,
.setup = pci_acpi_setup, .setup = pci_acpi_setup,
.cleanup = pci_acpi_cleanup, .cleanup = pci_acpi_cleanup,
......
...@@ -353,8 +353,14 @@ static int __init acpi_pnp_find_device(struct device *dev, acpi_handle * handle) ...@@ -353,8 +353,14 @@ static int __init acpi_pnp_find_device(struct device *dev, acpi_handle * handle)
/* complete initialization of a PNPACPI device includes having /* complete initialization of a PNPACPI device includes having
* pnpdev->dev.archdata.acpi_handle point to its ACPI sibling. * pnpdev->dev.archdata.acpi_handle point to its ACPI sibling.
*/ */
static bool acpi_pnp_bus_match(struct device *dev)
{
return dev->bus == &pnp_bus_type;
}
static struct acpi_bus_type __initdata acpi_pnp_bus = { static struct acpi_bus_type __initdata acpi_pnp_bus = {
.bus = &pnp_bus_type, .name = "PNP",
.match = acpi_pnp_bus_match,
.find_device = acpi_pnp_find_device, .find_device = acpi_pnp_find_device,
}; };
......
...@@ -71,9 +71,14 @@ struct kmem_cache *scsi_sdb_cache; ...@@ -71,9 +71,14 @@ struct kmem_cache *scsi_sdb_cache;
#ifdef CONFIG_ACPI #ifdef CONFIG_ACPI
#include <acpi/acpi_bus.h> #include <acpi/acpi_bus.h>
static bool acpi_scsi_bus_match(struct device *dev)
{
return dev->bus == &scsi_bus_type;
}
int scsi_register_acpi_bus_type(struct acpi_bus_type *bus) int scsi_register_acpi_bus_type(struct acpi_bus_type *bus)
{ {
bus->bus = &scsi_bus_type; bus->match = acpi_scsi_bus_match;
return register_acpi_bus_type(bus); return register_acpi_bus_type(bus);
} }
EXPORT_SYMBOL_GPL(scsi_register_acpi_bus_type); EXPORT_SYMBOL_GPL(scsi_register_acpi_bus_type);
......
...@@ -210,9 +210,14 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) ...@@ -210,9 +210,14 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)
return 0; return 0;
} }
static bool usb_acpi_bus_match(struct device *dev)
{
return is_usb_device(dev) || is_usb_port(dev);
}
static struct acpi_bus_type usb_acpi_bus = { static struct acpi_bus_type usb_acpi_bus = {
.bus = &usb_bus_type, .name = "USB",
.find_bridge = usb_acpi_find_device, .match = usb_acpi_bus_match,
.find_device = usb_acpi_find_device, .find_device = usb_acpi_find_device,
}; };
......
...@@ -437,7 +437,8 @@ void acpi_remove_dir(struct acpi_device *); ...@@ -437,7 +437,8 @@ void acpi_remove_dir(struct acpi_device *);
*/ */
struct acpi_bus_type { struct acpi_bus_type {
struct list_head list; struct list_head list;
struct bus_type *bus; const char *name;
bool (*match)(struct device *dev);
/* For general devices under the bus */ /* For general devices under the bus */
int (*find_device) (struct device *, acpi_handle *); int (*find_device) (struct device *, acpi_handle *);
/* For bridges, such as PCI root bridge, IDE controller */ /* For bridges, such as PCI root bridge, IDE controller */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment