Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+13 −26
Original line number Diff line number Diff line
@@ -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 @@ static int acpi_unbind_one(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;
	int ret;

	ret = acpi_bind_one(dev, NULL);
	if (ret && (!dev->bus || !dev->parent)) {
		/* bridge devices genernally haven't bus or parent */
	if (ret) {
		if (!type) {
			ret = acpi_find_bridge_device(dev, &handle);
		if (!ret) {
			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;
			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);

+1 −0
Original line number Diff line number Diff line
@@ -1150,6 +1150,7 @@ static int ata_acpi_find_dummy(struct device *dev, acpi_handle *handle)
}

static struct acpi_bus_type ata_acpi_bus = {
	.name = "ATA",
	.find_bridge = ata_acpi_find_dummy,
	.find_device = ata_acpi_find_device,
};
+7 −1
Original line number Diff line number Diff line
@@ -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 = {
	.bus = &pci_bus_type,
	.name = "PCI",
	.match = pci_acpi_bus_match,
	.find_device = acpi_pci_find_device,
	.setup = pci_acpi_setup,
	.cleanup = pci_acpi_cleanup,
+7 −1
Original line number Diff line number Diff line
@@ -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
 * 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 = {
	.bus	     = &pnp_bus_type,
	.name	     = "PNP",
	.match	     = acpi_pnp_bus_match,
	.find_device = acpi_pnp_find_device,
};

+6 −1
Original line number Diff line number Diff line
@@ -71,9 +71,14 @@ struct kmem_cache *scsi_sdb_cache;
#ifdef CONFIG_ACPI
#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)
{
        bus->bus = &scsi_bus_type;
        bus->match = acpi_scsi_bus_match;
        return register_acpi_bus_type(bus);
}
EXPORT_SYMBOL_GPL(scsi_register_acpi_bus_type);
Loading