aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Whitcroft <apw@canonical.com>2009-12-24 02:09:03 +0000
committerJohn Rigby <john.rigby@linaro.org>2012-06-25 15:02:08 -0600
commit64f24f9412b69b31ccdd757c510b046f1d048f17 (patch)
tree3d0d89aaf6655896f7272e776e607fd84dc81166
parente536dfa3965b63f1b0b1a2b43084b389142d0a7a (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>
-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 7dd3f9fb9f3..f22741069ad 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -976,6 +976,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;
@@ -995,13 +1007,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
@@ -1031,6 +1046,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
@@ -1068,27 +1087,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;
}