summaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-02-10 18:35:46 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-02-10 18:35:46 -0500
commit9cb32acf095e806e864c29d060dd79580fcd3d4f (patch)
tree5e60c07a4a793f9a15ffa347ba2b93f907f7d17a /drivers/acpi
parent2d984ad132a87ca2112f81f21039493176a8bca0 (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.c12
-rw-r--r--drivers/acpi/scan.c9
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);
287static int acpi_platform_notify(struct device *dev) 287static 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
325static int acpi_platform_notify_remove(struct device *dev) 331static 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;