Commit 11909ca1 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

ACPI: Add .setup() and .cleanup() callbacks to struct acpi_bus_type

Add two new callbacks,.setup() and .cleanup(), struct acpi_bus_type
and modify acpi_platform_notify() to call .setup() after executing
acpi_bind_one() successfully and acpi_platform_notify_remove() to
call .cleanup() before running acpi_unbind_one().  This will allow
the users of struct acpi_bus_type, PCI in particular, to specify
operations to be executed right after the given device has been
associated with a companion struct acpi_device and right before
it's going to be detached from that companion, respectively.

The main motivation is to be able to get rid of acpi_pci_bind()
and acpi_pci_unbind(), which are horrible horrible stuff.  [In short,
there are three problems with them: The way they populate the .bind()
and .unbind() callbacks of ACPI devices is rather less than
straightforward, they require special hotplug-specific paths to be
present in the ACPI namespace scanning code and by the time
acpi_pci_unbind() is called the PCI device object in question may
not exist any more.]
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Acked-by: default avatarYinghai Lu <yinghai@kernel.org>
Acked-by: default avatarToshi Kani <toshi.kani@hp.com>
parent 0cd6ac52
...@@ -63,6 +63,9 @@ static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type) ...@@ -63,6 +63,9 @@ static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type)
{ {
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->bus == type) {
...@@ -264,28 +267,39 @@ static int acpi_platform_notify(struct device *dev) ...@@ -264,28 +267,39 @@ static int acpi_platform_notify(struct device *dev)
{ {
struct acpi_bus_type *type; struct acpi_bus_type *type;
acpi_handle handle; acpi_handle handle;
int ret = -EINVAL; int ret;
ret = acpi_bind_one(dev, NULL); ret = acpi_bind_one(dev, NULL);
if (!ret) if (ret && (!dev->bus || !dev->parent)) {
goto out;
if (!dev->bus || !dev->parent) {
/* bridge devices genernally haven't bus or parent */ /* bridge devices genernally haven't bus or parent */
ret = acpi_find_bridge_device(dev, &handle); ret = acpi_find_bridge_device(dev, &handle);
goto end; if (!ret) {
ret = acpi_bind_one(dev, handle);
if (ret)
goto out;
}
} }
type = acpi_get_bus_type(dev->bus); type = acpi_get_bus_type(dev->bus);
if (!type) { if (ret) {
DBG("No ACPI bus support for %s\n", dev_name(dev)); if (!type || !type->find_device) {
ret = -EINVAL; DBG("No ACPI bus support for %s\n", dev_name(dev));
goto end; ret = -EINVAL;
goto out;
}
ret = type->find_device(dev, &handle);
if (ret) {
DBG("Unable to get handle for %s\n", dev_name(dev));
goto out;
}
ret = acpi_bind_one(dev, handle);
if (ret)
goto out;
} }
if ((ret = type->find_device(dev, &handle)) != 0)
DBG("Can't get handler for %s\n", dev_name(dev)); if (type && type->setup)
end: type->setup(dev);
if (!ret)
acpi_bind_one(dev, handle);
out: out:
#if ACPI_GLUE_DEBUG #if ACPI_GLUE_DEBUG
...@@ -304,6 +318,12 @@ static int acpi_platform_notify(struct device *dev) ...@@ -304,6 +318,12 @@ static int acpi_platform_notify(struct device *dev)
static int acpi_platform_notify_remove(struct device *dev) static int acpi_platform_notify_remove(struct device *dev)
{ {
struct acpi_bus_type *type;
type = acpi_get_bus_type(dev->bus);
if (type && type->cleanup)
type->cleanup(dev);
acpi_unbind_one(dev); acpi_unbind_one(dev);
return 0; return 0;
} }
......
...@@ -383,6 +383,8 @@ struct acpi_bus_type { ...@@ -383,6 +383,8 @@ struct acpi_bus_type {
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 */
int (*find_bridge) (struct device *, acpi_handle *); int (*find_bridge) (struct device *, acpi_handle *);
void (*setup)(struct device *);
void (*cleanup)(struct device *);
}; };
int register_acpi_bus_type(struct acpi_bus_type *); int register_acpi_bus_type(struct acpi_bus_type *);
int unregister_acpi_bus_type(struct acpi_bus_type *); int unregister_acpi_bus_type(struct acpi_bus_type *);
......
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