ACPI / scan: Add bind/unbind callbacks to struct acpi_scan_handler
In some cases it may be necessary to perform certain setup/cleanup operations on a device object representing a physical device after it has been associated with an ACPI companion by acpi_bind_one() or before disassociating it from that companion by acpi_unbind_one(), respectively. If there is a struct acpi_bus_type object for the given device's bus type, the .setup()/.cleanup() callbacks from there are executed for these purposes. However, an analogous mechanism will be necessary for devices whose bus types don't have corresponding struct acpi_bus_type objects and that have specific ACPI scan handlers. For those devices, add new .bind() and .unbind() callbacks to struct acpi_scan_handler that will be executed by acpi_platform_notify() right after the given device has been associated with an ACPI comapnion and by acpi_platform_notify_remove() right before calling acpi_unbind_one() for that device, respectively. To make that work for scan handlers registering new devices in their .attach() callbacks, modify acpi_scan_attach_handler() to set the ACPI device object's handler field before calling .attach() from the scan handler at hand. This changeset includes a fix from Mika Westerberg. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
parent
2d984ad132
commit
9cb32acf09
3 changed files with 19 additions and 4 deletions
|
@ -287,6 +287,7 @@ EXPORT_SYMBOL_GPL(acpi_unbind_one);
|
||||||
static int acpi_platform_notify(struct device *dev)
|
static int acpi_platform_notify(struct device *dev)
|
||||||
{
|
{
|
||||||
struct acpi_bus_type *type = acpi_get_bus_type(dev);
|
struct acpi_bus_type *type = acpi_get_bus_type(dev);
|
||||||
|
struct acpi_device *adev;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = acpi_bind_one(dev, NULL);
|
ret = acpi_bind_one(dev, NULL);
|
||||||
|
@ -303,9 +304,14 @@ static int acpi_platform_notify(struct device *dev)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
adev = ACPI_COMPANION(dev);
|
||||||
|
if (!adev)
|
||||||
|
goto out;
|
||||||
|
|
||||||
if (type && type->setup)
|
if (type && type->setup)
|
||||||
type->setup(dev);
|
type->setup(dev);
|
||||||
|
else if (adev->handler && adev->handler->bind)
|
||||||
|
adev->handler->bind(dev);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
#if ACPI_GLUE_DEBUG
|
#if ACPI_GLUE_DEBUG
|
||||||
|
@ -324,11 +330,17 @@ 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_device *adev = ACPI_COMPANION(dev);
|
||||||
struct acpi_bus_type *type;
|
struct acpi_bus_type *type;
|
||||||
|
|
||||||
|
if (!adev)
|
||||||
|
return 0;
|
||||||
|
|
||||||
type = acpi_get_bus_type(dev);
|
type = acpi_get_bus_type(dev);
|
||||||
if (type && type->cleanup)
|
if (type && type->cleanup)
|
||||||
type->cleanup(dev);
|
type->cleanup(dev);
|
||||||
|
else if (adev->handler && adev->handler->unbind)
|
||||||
|
adev->handler->unbind(dev);
|
||||||
|
|
||||||
acpi_unbind_one(dev);
|
acpi_unbind_one(dev);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -2015,13 +2015,14 @@ static int acpi_scan_attach_handler(struct acpi_device *device)
|
||||||
|
|
||||||
handler = acpi_scan_match_handler(hwid->id, &devid);
|
handler = acpi_scan_match_handler(hwid->id, &devid);
|
||||||
if (handler) {
|
if (handler) {
|
||||||
|
device->handler = handler;
|
||||||
ret = handler->attach(device, devid);
|
ret = handler->attach(device, devid);
|
||||||
if (ret > 0) {
|
if (ret > 0)
|
||||||
device->handler = handler;
|
|
||||||
break;
|
break;
|
||||||
} else if (ret < 0) {
|
|
||||||
|
device->handler = NULL;
|
||||||
|
if (ret < 0)
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -133,6 +133,8 @@ struct acpi_scan_handler {
|
||||||
struct list_head list_node;
|
struct list_head list_node;
|
||||||
int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
|
int (*attach)(struct acpi_device *dev, const struct acpi_device_id *id);
|
||||||
void (*detach)(struct acpi_device *dev);
|
void (*detach)(struct acpi_device *dev);
|
||||||
|
void (*bind)(struct device *phys_dev);
|
||||||
|
void (*unbind)(struct device *phys_dev);
|
||||||
struct acpi_hotplug_profile hotplug;
|
struct acpi_hotplug_profile hotplug;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue