diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-02-10 18:35:46 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-02-10 18:35:46 -0500 |
commit | 9cb32acf095e806e864c29d060dd79580fcd3d4f (patch) | |
tree | 5e60c07a4a793f9a15ffa347ba2b93f907f7d17a /drivers/acpi | |
parent | 2d984ad132a87ca2112f81f21039493176a8bca0 (diff) |
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>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/glue.c | 12 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 9 |
2 files changed, 17 insertions, 4 deletions
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 0c789224d40d..f774c65ecb8b 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -287,6 +287,7 @@ EXPORT_SYMBOL_GPL(acpi_unbind_one); | |||
287 | static int acpi_platform_notify(struct device *dev) | 287 | static int acpi_platform_notify(struct device *dev) |
288 | { | 288 | { |
289 | struct acpi_bus_type *type = acpi_get_bus_type(dev); | 289 | struct acpi_bus_type *type = acpi_get_bus_type(dev); |
290 | struct acpi_device *adev; | ||
290 | int ret; | 291 | int ret; |
291 | 292 | ||
292 | ret = acpi_bind_one(dev, NULL); | 293 | ret = acpi_bind_one(dev, NULL); |
@@ -303,9 +304,14 @@ static int acpi_platform_notify(struct device *dev) | |||
303 | if (ret) | 304 | if (ret) |
304 | goto out; | 305 | goto out; |
305 | } | 306 | } |
307 | adev = ACPI_COMPANION(dev); | ||
308 | if (!adev) | ||
309 | goto out; | ||
306 | 310 | ||
307 | if (type && type->setup) | 311 | if (type && type->setup) |
308 | type->setup(dev); | 312 | type->setup(dev); |
313 | else if (adev->handler && adev->handler->bind) | ||
314 | adev->handler->bind(dev); | ||
309 | 315 | ||
310 | out: | 316 | out: |
311 | #if ACPI_GLUE_DEBUG | 317 | #if ACPI_GLUE_DEBUG |
@@ -324,11 +330,17 @@ static int acpi_platform_notify(struct device *dev) | |||
324 | 330 | ||
325 | static int acpi_platform_notify_remove(struct device *dev) | 331 | static int acpi_platform_notify_remove(struct device *dev) |
326 | { | 332 | { |
333 | struct acpi_device *adev = ACPI_COMPANION(dev); | ||
327 | struct acpi_bus_type *type; | 334 | struct acpi_bus_type *type; |
328 | 335 | ||
336 | if (!adev) | ||
337 | return 0; | ||
338 | |||
329 | type = acpi_get_bus_type(dev); | 339 | type = acpi_get_bus_type(dev); |
330 | if (type && type->cleanup) | 340 | if (type && type->cleanup) |
331 | type->cleanup(dev); | 341 | type->cleanup(dev); |
342 | else if (adev->handler && adev->handler->unbind) | ||
343 | adev->handler->unbind(dev); | ||
332 | 344 | ||
333 | acpi_unbind_one(dev); | 345 | acpi_unbind_one(dev); |
334 | return 0; | 346 | return 0; |
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 57b053f424d1..9c4581fd5827 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -2015,13 +2015,14 @@ static int acpi_scan_attach_handler(struct acpi_device *device) | |||
2015 | 2015 | ||
2016 | handler = acpi_scan_match_handler(hwid->id, &devid); | 2016 | handler = acpi_scan_match_handler(hwid->id, &devid); |
2017 | if (handler) { | 2017 | if (handler) { |
2018 | device->handler = handler; | ||
2018 | ret = handler->attach(device, devid); | 2019 | ret = handler->attach(device, devid); |
2019 | if (ret > 0) { | 2020 | if (ret > 0) |
2020 | device->handler = handler; | ||
2021 | break; | 2021 | break; |
2022 | } else if (ret < 0) { | 2022 | |
2023 | device->handler = NULL; | ||
2024 | if (ret < 0) | ||
2023 | break; | 2025 | break; |
2024 | } | ||
2025 | } | 2026 | } |
2026 | } | 2027 | } |
2027 | return ret; | 2028 | return ret; |