aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAndy Whitcroft <apw@canonical.com>2009-12-24 02:09:03 +0000
committerJohn Rigby <john.rigby@linaro.org>2011-08-21 21:28:37 -0600
commit42c5c4e30c3947d89c0b7a024d02e22c0ccf0e29 (patch)
treea7ba0a1f0164e9da91603aa12e914bb73c7a335f /drivers
parent83bdb665b573d277e895892e574c3b6240c859a8 (diff)
UBUNTU: SAUCE: acpi battery -- move first lookup asynchronous
BugLink: http://bugs.launchpad.net/bugs/507211 When instantiating the battery object on to the acpi bus in the kernel we talk to the BIOS to get the current battery state. This can take a long time and holds the acpi bus object locked for the duration. This leads to any other object wishing to add itself that bus blocking. This leads to unpredicatable delays of up to .3s when initialising the hpet during boot depending on execution order. Make the first update of the battery asynchronous. Move the acpi bus handling back synchronous. Signed-off-by: Andy Whitcroft <apw@canonical.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/battery.c36
1 files changed, 23 insertions, 13 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index fcc13ac0aa1..929f5e8fa96 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -957,6 +957,18 @@ static int battery_notify(struct notifier_block *nb,
return 0;
}
+static LIST_HEAD(acpi_battery_domain);
+
+static void acpi_battery_update_async(struct acpi_device *device, async_cookie_t cookie)
+{
+ struct acpi_battery *battery = acpi_driver_data(device);
+
+ acpi_battery_update(battery);
+ printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
+ ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
+ device->status.battery_present ? "present" : "absent");
+}
+
static int acpi_battery_add(struct acpi_device *device)
{
int result = 0;
@@ -975,14 +987,14 @@ static int acpi_battery_add(struct acpi_device *device)
if (ACPI_SUCCESS(acpi_get_handle(battery->device->handle,
"_BIX", &handle)))
set_bit(ACPI_BATTERY_XINFO_PRESENT, &battery->flags);
- acpi_battery_update(battery);
+ /* Mark the battery for update at first access. */
+ battery->update_time = 0;
#ifdef CONFIG_ACPI_PROCFS_POWER
result = acpi_battery_add_fs(device);
#endif
if (!result) {
- printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
- ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
- device->status.battery_present ? "present" : "absent");
+ async_schedule_domain(acpi_battery_update_async, device, &acpi_battery_domain);
+
} else {
#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_battery_remove_fs(device);
@@ -1002,6 +1014,10 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
if (!device || !acpi_driver_data(device))
return -EINVAL;
+
+ /* Ensure all async updates are complete before freeing the battery. */
+ async_synchronize_full_domain(&acpi_battery_domain);
+
battery = acpi_driver_data(device);
unregister_pm_notifier(&battery->pm_nb);
#ifdef CONFIG_ACPI_PROCFS_POWER
@@ -1038,27 +1054,21 @@ static struct acpi_driver acpi_battery_driver = {
},
};
-static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
+static int __init acpi_battery_init(void)
{
if (acpi_disabled)
return;
#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_battery_dir = acpi_lock_battery_dir();
if (!acpi_battery_dir)
- return;
+ return -1;
#endif
if (acpi_bus_register_driver(&acpi_battery_driver) < 0) {
#ifdef CONFIG_ACPI_PROCFS_POWER
acpi_unlock_battery_dir(acpi_battery_dir);
#endif
- return;
+ return -1;
}
- return;
-}
-
-static int __init acpi_battery_init(void)
-{
- async_schedule(acpi_battery_init_async, NULL);
return 0;
}