aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorAndy Whitcroft <apw@canonical.com>2009-12-24 02:09:03 +0000
committerAndy Whitcroft <apw@canonical.com>2012-01-05 11:08:15 +0000
commit226399b4c37dbb9873a2db128ae4344096ad5f59 (patch)
treeecabf355ece9aefe10b004323b563618da034b54 /drivers
parente601d47eeabf8d55b07c1d522a33cce9c34e4b58 (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.c39
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;
}