diff options
author | Andy Whitcroft <apw@canonical.com> | 2009-12-24 02:09:03 +0000 |
---|---|---|
committer | Andy Whitcroft <apw@canonical.com> | 2012-01-05 11:08:15 +0000 |
commit | 226399b4c37dbb9873a2db128ae4344096ad5f59 (patch) | |
tree | ecabf355ece9aefe10b004323b563618da034b54 /drivers | |
parent | e601d47eeabf8d55b07c1d522a33cce9c34e4b58 (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.c | 39 |
1 files changed, 26 insertions, 13 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 7711d94a040..eb18c44f209 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -968,6 +968,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; @@ -987,13 +999,16 @@ 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); - result = acpi_battery_update(battery); - if (result) - goto fail; + + /* 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) { + if (!result) { + async_schedule_domain(acpi_battery_update_async, device, &acpi_battery_domain); + + } else { #ifdef CONFIG_ACPI_PROCFS_POWER acpi_battery_remove_fs(device); #endif @@ -1023,6 +1038,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 @@ -1060,27 +1079,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; } |