From a1f0eff21edac1bd87e397f56c4258b9611b5a50 Mon Sep 17 00:00:00 2001 From: Vladimir Lebedev Date: Tue, 20 Feb 2007 15:48:06 +0300 Subject: [PATCH 1/5] ACPI: battery: make internal names consistent with battery "state" Cleanup -- No functional changes. Battery state is currently exported in a proc "state" file. Update associated #defines and routines to be consistent. Signed-off-by: Vladimir Lebedev Signed-off-by: Len Brown --- drivers/acpi/battery.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index e64c76c8b726..df04f87dd491 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -44,7 +44,7 @@ #define ACPI_BATTERY_HID "PNP0C0A" #define ACPI_BATTERY_DEVICE_NAME "Battery" #define ACPI_BATTERY_FILE_INFO "info" -#define ACPI_BATTERY_FILE_STATUS "state" +#define ACPI_BATTERY_FILE_STATE "state" #define ACPI_BATTERY_FILE_ALARM "alarm" #define ACPI_BATTERY_NOTIFY_STATUS 0x80 #define ACPI_BATTERY_NOTIFY_INFO 0x81 @@ -76,7 +76,7 @@ static struct acpi_driver acpi_battery_driver = { }, }; -struct acpi_battery_status { +struct acpi_battery_state { acpi_integer state; acpi_integer present_rate; acpi_integer remaining_capacity; @@ -183,8 +183,8 @@ acpi_battery_get_info(struct acpi_battery *battery, } static int -acpi_battery_get_status(struct acpi_battery *battery, - struct acpi_battery_status **bst) +acpi_battery_get_state(struct acpi_battery *battery, + struct acpi_battery_state **bst) { int result = 0; acpi_status status = 0; @@ -425,7 +425,7 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) { int result = 0; struct acpi_battery *battery = seq->private; - struct acpi_battery_status *bst = NULL; + struct acpi_battery_state *bst = NULL; char *units = "?"; @@ -449,9 +449,9 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) /* Battery Status (_BST) */ - result = acpi_battery_get_status(battery, &bst); + result = acpi_battery_get_state(battery, &bst); if (result || !bst) { - seq_printf(seq, "ERROR: Unable to read battery status\n"); + seq_printf(seq, "ERROR: Unable to read battery state\n"); goto end; } @@ -621,7 +621,7 @@ static int acpi_battery_add_fs(struct acpi_device *device) } /* 'status' [R] */ - entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS, + entry = create_proc_entry(ACPI_BATTERY_FILE_STATE, S_IRUGO, acpi_device_dir(device)); if (!entry) return -ENODEV; @@ -652,7 +652,7 @@ static int acpi_battery_remove_fs(struct acpi_device *device) if (acpi_device_dir(device)) { remove_proc_entry(ACPI_BATTERY_FILE_ALARM, acpi_device_dir(device)); - remove_proc_entry(ACPI_BATTERY_FILE_STATUS, + remove_proc_entry(ACPI_BATTERY_FILE_STATE, acpi_device_dir(device)); remove_proc_entry(ACPI_BATTERY_FILE_INFO, acpi_device_dir(device)); From b6ce4083ed8e2a01a3a59301eabe0fc1e68a8a84 Mon Sep 17 00:00:00 2001 From: Vladimir Lebedev Date: Tue, 20 Feb 2007 15:48:06 +0300 Subject: [PATCH 2/5] ACPI: Cache battery status instead of re-evaluating AML /proc exports _BST in a single file, and _BST is re-evaulated whenever that file is read. Sometimes user-space reads this file frequently, and on some systems _BST takes a long time to evaluate due to a slow EC. Further, when we move to sysfs, the values returned from _BST will be in multiple files, and evaluating _BST for each file read would make matters worse. Here code is added to support caching the results of _BST. A new module parameter "update_time" tells how many seconds the cached _BST should be used before it is re-evaluated. Currently, update_time defaults to 0, and so the existing behaviour of re-evaluating on each read retained. Signed-off-by: Vladimir Lebedev Signed-off-by: Len Brown --- drivers/acpi/battery.c | 643 +++++++++++++++++++++++++++++------------ 1 file changed, 456 insertions(+), 187 deletions(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index df04f87dd491..f3b0024e5760 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -52,12 +52,24 @@ #define ACPI_BATTERY_UNITS_AMPS "mA" #define _COMPONENT ACPI_BATTERY_COMPONENT + +#define ACPI_BATTERY_UPDATE_TIME 0 + +#define ACPI_BATTERY_NONE_UPDATE 0 +#define ACPI_BATTERY_EASY_UPDATE 1 +#define ACPI_BATTERY_INIT_UPDATE 2 + ACPI_MODULE_NAME("battery"); MODULE_AUTHOR("Paul Diefenbaugh"); MODULE_DESCRIPTION("ACPI Battery Driver"); MODULE_LICENSE("GPL"); +static unsigned int update_time = ACPI_BATTERY_UPDATE_TIME; + +/* 0 - every time, > 0 - by update_time */ +module_param(update_time, uint, 0644); + extern struct proc_dir_entry *acpi_lock_battery_dir(void); extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); @@ -100,32 +112,117 @@ struct acpi_battery_info { }; struct acpi_battery_flags { - u8 present:1; /* Bay occupied? */ - u8 power_unit:1; /* 0=watts, 1=apms */ - u8 alarm:1; /* _BTP present? */ - u8 reserved:5; -}; - -struct acpi_battery_trips { - unsigned long warning; - unsigned long low; + u8 battery_present_prev; + u8 alarm_present; + u8 init_update; + u8 info_update; + u8 state_update; + u8 alarm_update; + u8 power_unit; }; struct acpi_battery { + struct mutex mutex; struct acpi_device * device; struct acpi_battery_flags flags; - struct acpi_battery_trips trips; + struct acpi_buffer bif_data; + struct acpi_buffer bst_data; unsigned long alarm; - struct acpi_battery_info *info; + unsigned long info_update_time; + unsigned long state_update_time; + unsigned long alarm_update_time; }; +#define acpi_battery_present(battery) battery->device->status.battery_present +#define acpi_battery_present_prev(battery) battery->flags.battery_present_prev +#define acpi_battery_alarm_present(battery) battery->flags.alarm_present +#define acpi_battery_init_update_flag(battery) battery->flags.init_update +#define acpi_battery_info_update_flag(battery) battery->flags.info_update +#define acpi_battery_state_update_flag(battery) battery->flags.state_update +#define acpi_battery_alarm_update_flag(battery) battery->flags.alarm_update +#define acpi_battery_power_units(battery) battery->flags.power_unit ? \ + ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS +#define acpi_battery_handle(battery) battery->device->handle +#define acpi_battery_inserted(battery) (!acpi_battery_present_prev(battery) & acpi_battery_present(battery)) +#define acpi_battery_removed(battery) (acpi_battery_present_prev(battery) & !acpi_battery_present(battery)) +#define acpi_battery_bid(battery) acpi_device_bid(battery->device) +#define acpi_battery_status_str(battery) acpi_battery_present(battery) ? "present" : "absent" + /* -------------------------------------------------------------------------- Battery Management -------------------------------------------------------------------------- */ -static int -acpi_battery_get_info(struct acpi_battery *battery, - struct acpi_battery_info **bif) +static void acpi_battery_mutex_lock(struct acpi_battery *battery) +{ + mutex_lock(&battery->mutex); +} + +static void acpi_battery_mutex_unlock(struct acpi_battery *battery) +{ + mutex_unlock(&battery->mutex); +} + +static void acpi_battery_check_result(struct acpi_battery *battery, int result) +{ + if (!battery) + return; + + if (result) { + acpi_battery_init_update_flag(battery) = 1; + } +} + +static int acpi_battery_extract_package(struct acpi_battery *battery, + union acpi_object *package, + struct acpi_buffer *format, + struct acpi_buffer *data, + char *package_name) +{ + acpi_status status = AE_OK; + struct acpi_buffer data_null = { 0, NULL }; + + status = acpi_extract_package(package, format, &data_null); + if (status != AE_BUFFER_OVERFLOW) { + ACPI_EXCEPTION((AE_INFO, status, "Extracting size %s", + package_name)); + return -ENODEV; + } + + if (data_null.length != data->length) { + if (data->pointer) { + kfree(data->pointer); + } + data->pointer = kzalloc(data_null.length, GFP_KERNEL); + if (!data->pointer) { + ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "kzalloc()")); + return -ENOMEM; + } + data->length = data_null.length; + } + + status = acpi_extract_package(package, format, data); + if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Extracting %s", + package_name)); + return -ENODEV; + } + + return 0; +} + +static int acpi_battery_get_status(struct acpi_battery *battery) +{ + int result = 0; + + result = acpi_bus_get_status(battery->device); + if (result) { + ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA")); + return -ENODEV; + } + return result; +} + +static int acpi_battery_get_info(struct acpi_battery *battery) { int result = 0; acpi_status status = 0; @@ -133,16 +230,18 @@ acpi_battery_get_info(struct acpi_battery *battery, struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF), ACPI_BATTERY_FORMAT_BIF }; - struct acpi_buffer data = { 0, NULL }; union acpi_object *package = NULL; + struct acpi_buffer *data = NULL; + struct acpi_battery_info *bif = NULL; + battery->info_update_time = get_seconds(); - if (!battery || !bif) - return -EINVAL; + if (!acpi_battery_present(battery)) + return 0; /* Evalute _BIF */ - status = acpi_evaluate_object(battery->device->handle, "_BIF", NULL, &buffer); + status = acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL, &buffer); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); return -ENODEV; @@ -150,41 +249,29 @@ acpi_battery_get_info(struct acpi_battery *battery, package = buffer.pointer; + data = &battery->bif_data; + /* Extract Package Data */ - status = acpi_extract_package(package, &format, &data); - if (status != AE_BUFFER_OVERFLOW) { - ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF")); - result = -ENODEV; + result = acpi_battery_extract_package(battery, package, &format, data, "_BIF"); + if (result) goto end; - } - - data.pointer = kzalloc(data.length, GFP_KERNEL); - if (!data.pointer) { - result = -ENOMEM; - goto end; - } - - status = acpi_extract_package(package, &format, &data); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF")); - kfree(data.pointer); - result = -ENODEV; - goto end; - } end: - kfree(buffer.pointer); - if (!result) - (*bif) = data.pointer; + if (buffer.pointer) { + kfree(buffer.pointer); + } + + if (!result) { + bif = data->pointer; + battery->flags.power_unit = bif->power_unit; + } return result; } -static int -acpi_battery_get_state(struct acpi_battery *battery, - struct acpi_battery_state **bst) +static int acpi_battery_get_state(struct acpi_battery *battery) { int result = 0; acpi_status status = 0; @@ -192,16 +279,17 @@ acpi_battery_get_state(struct acpi_battery *battery, struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST), ACPI_BATTERY_FORMAT_BST }; - struct acpi_buffer data = { 0, NULL }; union acpi_object *package = NULL; + struct acpi_buffer *data = NULL; + battery->state_update_time = get_seconds(); - if (!battery || !bst) - return -EINVAL; + if (!acpi_battery_present(battery)) + return 0; /* Evalute _BST */ - status = acpi_evaluate_object(battery->device->handle, "_BST", NULL, &buffer); + status = acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL, &buffer); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST")); return -ENODEV; @@ -209,55 +297,46 @@ acpi_battery_get_state(struct acpi_battery *battery, package = buffer.pointer; + data = &battery->bst_data; + /* Extract Package Data */ - status = acpi_extract_package(package, &format, &data); - if (status != AE_BUFFER_OVERFLOW) { - ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST")); - result = -ENODEV; + result = acpi_battery_extract_package(battery, package, &format, data, "_BST"); + if (result) goto end; - } - - data.pointer = kzalloc(data.length, GFP_KERNEL); - if (!data.pointer) { - result = -ENOMEM; - goto end; - } - - status = acpi_extract_package(package, &format, &data); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST")); - kfree(data.pointer); - result = -ENODEV; - goto end; - } end: - kfree(buffer.pointer); - - if (!result) - (*bst) = data.pointer; + if (buffer.pointer) { + kfree(buffer.pointer); + } return result; } -static int -acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm) +static int acpi_battery_get_alarm(struct acpi_battery *battery) +{ + battery->alarm_update_time = get_seconds(); + + return 0; +} + +static int acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm) { acpi_status status = 0; union acpi_object arg0 = { ACPI_TYPE_INTEGER }; struct acpi_object_list arg_list = { 1, &arg0 }; + battery->alarm_update_time = get_seconds(); - if (!battery) - return -EINVAL; + if (!acpi_battery_present(battery)) + return -ENODEV; - if (!battery->flags.alarm) + if (!acpi_battery_alarm_present(battery)) return -ENODEV; arg0.integer.value = alarm; - status = acpi_evaluate_object(battery->device->handle, "_BTP", &arg_list, NULL); + status = acpi_evaluate_object(acpi_battery_handle(battery), "_BTP", &arg_list, NULL); if (ACPI_FAILURE(status)) return -ENODEV; @@ -268,65 +347,110 @@ acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm) return 0; } -static int acpi_battery_check(struct acpi_battery *battery) +static int acpi_battery_init_alarm(struct acpi_battery *battery) { int result = 0; acpi_status status = AE_OK; acpi_handle handle = NULL; - struct acpi_device *device = NULL; - struct acpi_battery_info *bif = NULL; + struct acpi_battery_info *bif = battery->bif_data.pointer; + unsigned long alarm = battery->alarm; + /* See if alarms are supported, and if so, set default */ - if (!battery) - return -EINVAL; - - device = battery->device; - - result = acpi_bus_get_status(device); - if (result) - return result; - - /* Insertion? */ - - if (!battery->flags.present && device->status.battery_present) { - - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n")); - - /* Evalute _BIF to get certain static information */ - - result = acpi_battery_get_info(battery, &bif); - if (result) - return result; - - battery->flags.power_unit = bif->power_unit; - battery->trips.warning = bif->design_capacity_warning; - battery->trips.low = bif->design_capacity_low; - kfree(bif); - - /* See if alarms are supported, and if so, set default */ - - status = acpi_get_handle(battery->device->handle, "_BTP", &handle); - if (ACPI_SUCCESS(status)) { - battery->flags.alarm = 1; - acpi_battery_set_alarm(battery, battery->trips.warning); + status = acpi_get_handle(acpi_battery_handle(battery), "_BTP", &handle); + if (ACPI_SUCCESS(status)) { + acpi_battery_alarm_present(battery) = 1; + if (!alarm && bif) { + alarm = bif->design_capacity_warning; } + result = acpi_battery_set_alarm(battery, alarm); + if (result) + goto end; + } else { + acpi_battery_alarm_present(battery) = 0; } - /* Removal? */ - - else if (battery->flags.present && !device->status.battery_present) { - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n")); - } - - battery->flags.present = device->status.battery_present; + end: return result; } -static void acpi_battery_check_present(struct acpi_battery *battery) +static int acpi_battery_init_update(struct acpi_battery *battery) { - if (!battery->flags.present) { - acpi_battery_check(battery); + int result = 0; + + result = acpi_battery_get_status(battery); + if (result) + return result; + + acpi_battery_present_prev(battery) = acpi_battery_present(battery); + + if (acpi_battery_present(battery)) { + result = acpi_battery_get_info(battery); + if (result) + return result; + result = acpi_battery_get_state(battery); + if (result) + return result; + + acpi_battery_init_alarm(battery); + } + + return result; +} + +static int acpi_battery_update(struct acpi_battery *battery, + int update, int *update_result_ptr) +{ + int result = 0; + int update_result = ACPI_BATTERY_NONE_UPDATE; + + if (!acpi_battery_present(battery)) { + update = 1; + } + + if (acpi_battery_init_update_flag(battery)) { + result = acpi_battery_init_update(battery); + if (result) + goto end;; + update_result = ACPI_BATTERY_INIT_UPDATE; + } else if (update) { + result = acpi_battery_get_status(battery); + if (result) + goto end;; + if (acpi_battery_inserted(battery) || acpi_battery_removed(battery)) { + result = acpi_battery_init_update(battery); + if (result) + goto end;; + update_result = ACPI_BATTERY_INIT_UPDATE; + } else { + update_result = ACPI_BATTERY_EASY_UPDATE; + } + } + + end: + + acpi_battery_init_update_flag(battery) = (result != 0); + + *update_result_ptr = update_result; + + return result; +} + +static void acpi_battery_notify_update(struct acpi_battery *battery) +{ + acpi_battery_get_status(battery); + + if (acpi_battery_init_update_flag(battery)) { + return; + } + + if (acpi_battery_inserted(battery) || acpi_battery_removed(battery)) { + acpi_battery_init_update_flag(battery) = 1; + } else { + acpi_battery_info_update_flag(battery) = 1; + acpi_battery_state_update_flag(battery) = 1; + acpi_battery_alarm_update_flag(battery) = 1; } } @@ -335,37 +459,33 @@ static void acpi_battery_check_present(struct acpi_battery *battery) -------------------------------------------------------------------------- */ static struct proc_dir_entry *acpi_battery_dir; -static int acpi_battery_read_info(struct seq_file *seq, void *offset) + +static int acpi_battery_read_info_print(struct seq_file *seq, int result) { - int result = 0; struct acpi_battery *battery = seq->private; struct acpi_battery_info *bif = NULL; char *units = "?"; - - if (!battery) + if (result) goto end; - acpi_battery_check_present(battery); - - if (battery->flags.present) + if (acpi_battery_present(battery)) seq_printf(seq, "present: yes\n"); else { seq_printf(seq, "present: no\n"); goto end; } - /* Battery Info (_BIF) */ - - result = acpi_battery_get_info(battery, &bif); - if (result || !bif) { - seq_printf(seq, "ERROR: Unable to read battery information\n"); + bif = battery->bif_data.pointer; + if (!bif) { + ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BIF buffer is NULL")); + result = -ENODEV; goto end; } - units = - bif-> - power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; + /* Battery Units */ + + units = acpi_battery_power_units(battery); if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "design capacity: unknown\n"); @@ -396,7 +516,6 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset) else seq_printf(seq, "design voltage: %d mV\n", (u32) bif->design_voltage); - seq_printf(seq, "design capacity warning: %d %sh\n", (u32) bif->design_capacity_warning, units); seq_printf(seq, "design capacity low: %d %sh\n", @@ -411,9 +530,48 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset) seq_printf(seq, "OEM info: %s\n", bif->oem_info); end: - kfree(bif); - return 0; + if (result) + seq_printf(seq, "ERROR: Unable to read battery info\n"); + + return result; +} + +static int acpi_battery_read_info(struct seq_file *seq, void *offset) +{ + struct acpi_battery *battery = seq->private; + int result = 0; + int update_result = ACPI_BATTERY_NONE_UPDATE; + int update = 0; + + acpi_battery_mutex_lock(battery); + + update = (get_seconds() - battery->info_update_time >= update_time); + update = (update | acpi_battery_info_update_flag(battery)); + + result = acpi_battery_update(battery, update, &update_result); + if (result) + goto end; + + /* Battery Info (_BIF) */ + + if (update_result == ACPI_BATTERY_EASY_UPDATE) { + result = acpi_battery_get_info(battery); + if (result) + goto end; + } + + end: + + result = acpi_battery_read_info_print(seq, result); + + acpi_battery_check_result(battery, result); + + acpi_battery_info_update_flag(battery) = result; + + acpi_battery_mutex_unlock(battery); + + return result; } static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) @@ -421,40 +579,33 @@ static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) return single_open(file, acpi_battery_read_info, PDE(inode)->data); } -static int acpi_battery_read_state(struct seq_file *seq, void *offset) +static int acpi_battery_read_state_print(struct seq_file *seq, int result) { - int result = 0; struct acpi_battery *battery = seq->private; struct acpi_battery_state *bst = NULL; char *units = "?"; - - if (!battery) + if (result) goto end; - acpi_battery_check_present(battery); - - if (battery->flags.present) + if (acpi_battery_present(battery)) seq_printf(seq, "present: yes\n"); else { seq_printf(seq, "present: no\n"); goto end; } - /* Battery Units */ - - units = - battery->flags. - power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; - - /* Battery Status (_BST) */ - - result = acpi_battery_get_state(battery, &bst); - if (result || !bst) { - seq_printf(seq, "ERROR: Unable to read battery state\n"); + bst = battery->bst_data.pointer; + if (!bst) { + ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BST buffer is NULL")); + result = -ENODEV; goto end; } + /* Battery Units */ + + units = acpi_battery_power_units(battery); + if (!(bst->state & 0x04)) seq_printf(seq, "capacity state: ok\n"); else @@ -490,9 +641,49 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) (u32) bst->present_voltage); end: - kfree(bst); - return 0; + if (result) { + seq_printf(seq, "ERROR: Unable to read battery state\n"); + } + + return result; +} + +static int acpi_battery_read_state(struct seq_file *seq, void *offset) +{ + struct acpi_battery *battery = seq->private; + int result = 0; + int update_result = ACPI_BATTERY_NONE_UPDATE; + int update = 0; + + acpi_battery_mutex_lock(battery); + + update = (get_seconds() - battery->state_update_time >= update_time); + update = (update | acpi_battery_state_update_flag(battery)); + + result = acpi_battery_update(battery, update, &update_result); + if (result) + goto end; + + /* Battery State (_BST) */ + + if (update_result == ACPI_BATTERY_EASY_UPDATE) { + result = acpi_battery_get_state(battery); + if (result) + goto end; + } + + end: + + result = acpi_battery_read_state_print(seq, result); + + acpi_battery_check_result(battery, result); + + acpi_battery_state_update_flag(battery) = result; + + acpi_battery_mutex_unlock(battery); + + return result; } static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) @@ -500,38 +691,72 @@ static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) return single_open(file, acpi_battery_read_state, PDE(inode)->data); } -static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) +static int acpi_battery_read_alarm_print(struct seq_file *seq, int result) { struct acpi_battery *battery = seq->private; char *units = "?"; - - if (!battery) + if (result) goto end; - acpi_battery_check_present(battery); - - if (!battery->flags.present) { + if (!acpi_battery_present(battery)) { seq_printf(seq, "present: no\n"); goto end; } /* Battery Units */ - units = - battery->flags. - power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; - - /* Battery Alarm */ + units = acpi_battery_power_units(battery); seq_printf(seq, "alarm: "); if (!battery->alarm) seq_printf(seq, "unsupported\n"); else - seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units); + seq_printf(seq, "%lu %sh\n", battery->alarm, units); end: - return 0; + + if (result) + seq_printf(seq, "ERROR: Unable to read battery alarm\n"); + + return result; +} + +static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) +{ + struct acpi_battery *battery = seq->private; + int result = 0; + int update_result = ACPI_BATTERY_NONE_UPDATE; + int update = 0; + + acpi_battery_mutex_lock(battery); + + update = (get_seconds() - battery->alarm_update_time >= update_time); + update = (update | acpi_battery_alarm_update_flag(battery)); + + result = acpi_battery_update(battery, update, &update_result); + if (result) + goto end; + + /* Battery Alarm */ + + if (update_result == ACPI_BATTERY_EASY_UPDATE) { + result = acpi_battery_get_alarm(battery); + if (result) + goto end; + } + + end: + + result = acpi_battery_read_alarm_print(seq, result); + + acpi_battery_check_result(battery, result); + + acpi_battery_alarm_update_flag(battery) = result; + + acpi_battery_mutex_unlock(battery); + + return result; } static ssize_t @@ -543,27 +768,47 @@ acpi_battery_write_alarm(struct file *file, char alarm_string[12] = { '\0' }; struct seq_file *m = file->private_data; struct acpi_battery *battery = m->private; + int update_result = ACPI_BATTERY_NONE_UPDATE; if (!battery || (count > sizeof(alarm_string) - 1)) return -EINVAL; - acpi_battery_check_present(battery); + acpi_battery_mutex_lock(battery); - if (!battery->flags.present) - return -ENODEV; + result = acpi_battery_update(battery, 1, &update_result); + if (result) { + result = -ENODEV; + goto end; + } - if (copy_from_user(alarm_string, buffer, count)) - return -EFAULT; + if (!acpi_battery_present(battery)) { + result = -ENODEV; + goto end; + } + + if (copy_from_user(alarm_string, buffer, count)) { + result = -EFAULT; + goto end; + } alarm_string[count] = '\0'; result = acpi_battery_set_alarm(battery, simple_strtoul(alarm_string, NULL, 0)); if (result) - return result; + goto end; - return count; + end: + + acpi_battery_check_result(battery, result); + + if (!result) + result = count; + + acpi_battery_mutex_unlock(battery); + + return result; } static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) @@ -648,7 +893,6 @@ static int acpi_battery_add_fs(struct acpi_device *device) static int acpi_battery_remove_fs(struct acpi_device *device) { - if (acpi_device_dir(device)) { remove_proc_entry(ACPI_BATTERY_FILE_ALARM, acpi_device_dir(device)); @@ -684,8 +928,11 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) case ACPI_BATTERY_NOTIFY_INFO: case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_DEVICE_CHECK: - acpi_battery_check(battery); - acpi_bus_generate_event(device, event, battery->flags.present); + acpi_battery_mutex_lock(battery); + device = battery->device; + acpi_battery_notify_update(battery); + acpi_battery_mutex_unlock(battery); + acpi_bus_generate_event(device, event, acpi_battery_present(battery)); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -702,7 +949,6 @@ static int acpi_battery_add(struct acpi_device *device) acpi_status status = 0; struct acpi_battery *battery = NULL; - if (!device) return -EINVAL; @@ -710,15 +956,21 @@ static int acpi_battery_add(struct acpi_device *device) if (!battery) return -ENOMEM; + mutex_init(&battery->mutex); + + acpi_battery_mutex_lock(battery); + battery->device = device; strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); acpi_driver_data(device) = battery; - result = acpi_battery_check(battery); + result = acpi_battery_get_status(battery); if (result) goto end; + acpi_battery_init_update_flag(battery) = 1; + result = acpi_battery_add_fs(device); if (result) goto end; @@ -727,6 +979,7 @@ static int acpi_battery_add(struct acpi_device *device) ACPI_ALL_NOTIFY, acpi_battery_notify, battery); if (ACPI_FAILURE(status)) { + ACPI_EXCEPTION((AE_INFO, status, "Installing notify handler")); result = -ENODEV; goto end; } @@ -736,11 +989,14 @@ static int acpi_battery_add(struct acpi_device *device) device->status.battery_present ? "present" : "absent"); end: + if (result) { acpi_battery_remove_fs(device); kfree(battery); } + acpi_battery_mutex_unlock(battery); + return result; } @@ -749,18 +1005,29 @@ static int acpi_battery_remove(struct acpi_device *device, int type) acpi_status status = 0; struct acpi_battery *battery = NULL; - if (!device || !acpi_driver_data(device)) return -EINVAL; battery = acpi_driver_data(device); + acpi_battery_mutex_lock(battery); + status = acpi_remove_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_battery_notify); acpi_battery_remove_fs(device); + if (battery->bif_data.pointer) + kfree(battery->bif_data.pointer); + + if (battery->bst_data.pointer) + kfree(battery->bst_data.pointer); + + acpi_battery_mutex_unlock(battery); + + mutex_destroy(&battery->mutex); + kfree(battery); return 0; @@ -775,7 +1042,10 @@ static int acpi_battery_resume(struct acpi_device *device) return -EINVAL; battery = device->driver_data; - return acpi_battery_check(battery); + + acpi_battery_init_update_flag(battery) = 1; + + return 0; } static int __init acpi_battery_init(void) @@ -800,7 +1070,6 @@ static int __init acpi_battery_init(void) static void __exit acpi_battery_exit(void) { - acpi_bus_unregister_driver(&acpi_battery_driver); acpi_unlock_battery_dir(acpi_battery_dir); From 9ea7d57576f40c6af03c8c9fa7a069f2222b498b Mon Sep 17 00:00:00 2001 From: Vladimir Lebedev Date: Tue, 20 Feb 2007 15:48:06 +0300 Subject: [PATCH 3/5] ACPI: battery: Lindent Signed-off-by: Vladimir Lebedev Signed-off-by: Len Brown --- drivers/acpi/battery.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index f3b0024e5760..fc9c50ab5219 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -123,7 +123,7 @@ struct acpi_battery_flags { struct acpi_battery { struct mutex mutex; - struct acpi_device * device; + struct acpi_device *device; struct acpi_battery_flags flags; struct acpi_buffer bif_data; struct acpi_buffer bst_data; @@ -241,7 +241,9 @@ static int acpi_battery_get_info(struct acpi_battery *battery) /* Evalute _BIF */ - status = acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL, &buffer); + status = + acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL, + &buffer); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); return -ENODEV; @@ -253,7 +255,9 @@ static int acpi_battery_get_info(struct acpi_battery *battery) /* Extract Package Data */ - result = acpi_battery_extract_package(battery, package, &format, data, "_BIF"); + result = + acpi_battery_extract_package(battery, package, &format, data, + "_BIF"); if (result) goto end; @@ -289,7 +293,9 @@ static int acpi_battery_get_state(struct acpi_battery *battery) /* Evalute _BST */ - status = acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL, &buffer); + status = + acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL, + &buffer); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST")); return -ENODEV; @@ -301,7 +307,9 @@ static int acpi_battery_get_state(struct acpi_battery *battery) /* Extract Package Data */ - result = acpi_battery_extract_package(battery, package, &format, data, "_BST"); + result = + acpi_battery_extract_package(battery, package, &format, data, + "_BST"); if (result) goto end; @@ -320,7 +328,8 @@ static int acpi_battery_get_alarm(struct acpi_battery *battery) return 0; } -static int acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm) +static int acpi_battery_set_alarm(struct acpi_battery *battery, + unsigned long alarm) { acpi_status status = 0; union acpi_object arg0 = { ACPI_TYPE_INTEGER }; @@ -336,7 +345,9 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long al arg0.integer.value = alarm; - status = acpi_evaluate_object(acpi_battery_handle(battery), "_BTP", &arg_list, NULL); + status = + acpi_evaluate_object(acpi_battery_handle(battery), "_BTP", + &arg_list, NULL); if (ACPI_FAILURE(status)) return -ENODEV; @@ -400,7 +411,7 @@ static int acpi_battery_init_update(struct acpi_battery *battery) } static int acpi_battery_update(struct acpi_battery *battery, - int update, int *update_result_ptr) + int update, int *update_result_ptr) { int result = 0; int update_result = ACPI_BATTERY_NONE_UPDATE; @@ -418,7 +429,8 @@ static int acpi_battery_update(struct acpi_battery *battery, result = acpi_battery_get_status(battery); if (result) goto end;; - if (acpi_battery_inserted(battery) || acpi_battery_removed(battery)) { + if (acpi_battery_inserted(battery) + || acpi_battery_removed(battery)) { result = acpi_battery_init_update(battery); if (result) goto end;; @@ -770,7 +782,6 @@ acpi_battery_write_alarm(struct file *file, struct acpi_battery *battery = m->private; int update_result = ACPI_BATTERY_NONE_UPDATE; - if (!battery || (count > sizeof(alarm_string) - 1)) return -EINVAL; @@ -845,7 +856,6 @@ static int acpi_battery_add_fs(struct acpi_device *device) { struct proc_dir_entry *entry = NULL; - if (!acpi_device_dir(device)) { acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_battery_dir); @@ -917,7 +927,6 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) struct acpi_battery *battery = data; struct acpi_device *device = NULL; - if (!battery) return; @@ -932,7 +941,8 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) device = battery->device; acpi_battery_notify_update(battery); acpi_battery_mutex_unlock(battery); - acpi_bus_generate_event(device, event, acpi_battery_present(battery)); + acpi_bus_generate_event(device, event, + acpi_battery_present(battery)); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, From 6eedeef73e7fff32eb5fa25178c3c77b1db0ec0f Mon Sep 17 00:00:00 2001 From: Vladimir Lebedev Date: Sat, 21 Apr 2007 22:41:48 -0400 Subject: [PATCH 4/5] process reading battery status hangs http://bugzilla.kernel.org/show_bug.cgi?id=8351 Signed-off-by: Vladimir Lebedev Signed-off-by: Len Brown --- drivers/acpi/battery.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index fc9c50ab5219..b5df318978ed 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -937,10 +937,8 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) case ACPI_BATTERY_NOTIFY_INFO: case ACPI_NOTIFY_BUS_CHECK: case ACPI_NOTIFY_DEVICE_CHECK: - acpi_battery_mutex_lock(battery); device = battery->device; acpi_battery_notify_update(battery); - acpi_battery_mutex_unlock(battery); acpi_bus_generate_event(device, event, acpi_battery_present(battery)); break; From 78490d82129f7331d1366737c8704c1c053221a3 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Fri, 11 May 2007 13:18:55 -0400 Subject: [PATCH 5/5] ACPI: battery: syntax cleanup In response to review comments from Andrew Morton Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/battery.c | 420 +++++++++++++++++------------------------ 1 file changed, 173 insertions(+), 247 deletions(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index b5df318978ed..cad932de383d 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -43,9 +43,6 @@ #define ACPI_BATTERY_CLASS "battery" #define ACPI_BATTERY_HID "PNP0C0A" #define ACPI_BATTERY_DEVICE_NAME "Battery" -#define ACPI_BATTERY_FILE_INFO "info" -#define ACPI_BATTERY_FILE_STATE "state" -#define ACPI_BATTERY_FILE_ALARM "alarm" #define ACPI_BATTERY_NOTIFY_STATUS 0x80 #define ACPI_BATTERY_NOTIFY_INFO 0x81 #define ACPI_BATTERY_UNITS_WATTS "mW" @@ -111,13 +108,18 @@ struct acpi_battery_info { acpi_string oem_info; }; +enum acpi_battery_files{ + ACPI_BATTERY_INFO = 0, + ACPI_BATTERY_STATE, + ACPI_BATTERY_ALARM, + ACPI_BATTERY_NUMFILES, +}; + struct acpi_battery_flags { u8 battery_present_prev; u8 alarm_present; u8 init_update; - u8 info_update; - u8 state_update; - u8 alarm_update; + u8 update[ACPI_BATTERY_NUMFILES]; u8 power_unit; }; @@ -128,47 +130,37 @@ struct acpi_battery { struct acpi_buffer bif_data; struct acpi_buffer bst_data; unsigned long alarm; - unsigned long info_update_time; - unsigned long state_update_time; - unsigned long alarm_update_time; + unsigned long update_time[ACPI_BATTERY_NUMFILES]; }; -#define acpi_battery_present(battery) battery->device->status.battery_present -#define acpi_battery_present_prev(battery) battery->flags.battery_present_prev -#define acpi_battery_alarm_present(battery) battery->flags.alarm_present -#define acpi_battery_init_update_flag(battery) battery->flags.init_update -#define acpi_battery_info_update_flag(battery) battery->flags.info_update -#define acpi_battery_state_update_flag(battery) battery->flags.state_update -#define acpi_battery_alarm_update_flag(battery) battery->flags.alarm_update -#define acpi_battery_power_units(battery) battery->flags.power_unit ? \ - ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS -#define acpi_battery_handle(battery) battery->device->handle -#define acpi_battery_inserted(battery) (!acpi_battery_present_prev(battery) & acpi_battery_present(battery)) -#define acpi_battery_removed(battery) (acpi_battery_present_prev(battery) & !acpi_battery_present(battery)) -#define acpi_battery_bid(battery) acpi_device_bid(battery->device) -#define acpi_battery_status_str(battery) acpi_battery_present(battery) ? "present" : "absent" +inline int acpi_battery_present(struct acpi_battery *battery) +{ + return battery->device->status.battery_present; +} +inline char *acpi_battery_power_units(struct acpi_battery *battery) +{ + if (battery->flags.power_unit) + return ACPI_BATTERY_UNITS_AMPS; + else + return ACPI_BATTERY_UNITS_WATTS; +} + +inline acpi_handle acpi_battery_handle(struct acpi_battery *battery) +{ + return battery->device->handle; +} /* -------------------------------------------------------------------------- Battery Management -------------------------------------------------------------------------- */ -static void acpi_battery_mutex_lock(struct acpi_battery *battery) -{ - mutex_lock(&battery->mutex); -} - -static void acpi_battery_mutex_unlock(struct acpi_battery *battery) -{ - mutex_unlock(&battery->mutex); -} - static void acpi_battery_check_result(struct acpi_battery *battery, int result) { if (!battery) return; if (result) { - acpi_battery_init_update_flag(battery) = 1; + battery->flags.init_update = 1; } } @@ -189,9 +181,7 @@ static int acpi_battery_extract_package(struct acpi_battery *battery, } if (data_null.length != data->length) { - if (data->pointer) { - kfree(data->pointer); - } + kfree(data->pointer); data->pointer = kzalloc(data_null.length, GFP_KERNEL); if (!data->pointer) { ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "kzalloc()")); @@ -234,12 +224,12 @@ static int acpi_battery_get_info(struct acpi_battery *battery) struct acpi_buffer *data = NULL; struct acpi_battery_info *bif = NULL; - battery->info_update_time = get_seconds(); + battery->update_time[ACPI_BATTERY_INFO] = get_seconds(); if (!acpi_battery_present(battery)) return 0; - /* Evalute _BIF */ + /* Evaluate _BIF */ status = acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL, @@ -263,9 +253,7 @@ static int acpi_battery_get_info(struct acpi_battery *battery) end: - if (buffer.pointer) { - kfree(buffer.pointer); - } + kfree(buffer.pointer); if (!result) { bif = data->pointer; @@ -286,12 +274,12 @@ static int acpi_battery_get_state(struct acpi_battery *battery) union acpi_object *package = NULL; struct acpi_buffer *data = NULL; - battery->state_update_time = get_seconds(); + battery->update_time[ACPI_BATTERY_STATE] = get_seconds(); if (!acpi_battery_present(battery)) return 0; - /* Evalute _BST */ + /* Evaluate _BST */ status = acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL, @@ -314,16 +302,14 @@ static int acpi_battery_get_state(struct acpi_battery *battery) goto end; end: - if (buffer.pointer) { - kfree(buffer.pointer); - } + kfree(buffer.pointer); return result; } static int acpi_battery_get_alarm(struct acpi_battery *battery) { - battery->alarm_update_time = get_seconds(); + battery->update_time[ACPI_BATTERY_ALARM] = get_seconds(); return 0; } @@ -335,12 +321,12 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery, union acpi_object arg0 = { ACPI_TYPE_INTEGER }; struct acpi_object_list arg_list = { 1, &arg0 }; - battery->alarm_update_time = get_seconds(); + battery->update_time[ACPI_BATTERY_ALARM] = get_seconds(); if (!acpi_battery_present(battery)) return -ENODEV; - if (!acpi_battery_alarm_present(battery)) + if (!battery->flags.alarm_present) return -ENODEV; arg0.integer.value = alarm; @@ -370,7 +356,7 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery) status = acpi_get_handle(acpi_battery_handle(battery), "_BTP", &handle); if (ACPI_SUCCESS(status)) { - acpi_battery_alarm_present(battery) = 1; + battery->flags.alarm_present = 1; if (!alarm && bif) { alarm = bif->design_capacity_warning; } @@ -378,7 +364,7 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery) if (result) goto end; } else { - acpi_battery_alarm_present(battery) = 0; + battery->flags.alarm_present = 0; } end: @@ -394,7 +380,7 @@ static int acpi_battery_init_update(struct acpi_battery *battery) if (result) return result; - acpi_battery_present_prev(battery) = acpi_battery_present(battery); + battery->flags.battery_present_prev = acpi_battery_present(battery); if (acpi_battery_present(battery)) { result = acpi_battery_get_info(battery); @@ -420,20 +406,20 @@ static int acpi_battery_update(struct acpi_battery *battery, update = 1; } - if (acpi_battery_init_update_flag(battery)) { + if (battery->flags.init_update) { result = acpi_battery_init_update(battery); if (result) - goto end;; + goto end; update_result = ACPI_BATTERY_INIT_UPDATE; } else if (update) { result = acpi_battery_get_status(battery); if (result) - goto end;; - if (acpi_battery_inserted(battery) - || acpi_battery_removed(battery)) { + goto end; + if ((!battery->flags.battery_present_prev & acpi_battery_present(battery)) + || (battery->flags.battery_present_prev & !acpi_battery_present(battery))) { result = acpi_battery_init_update(battery); if (result) - goto end;; + goto end; update_result = ACPI_BATTERY_INIT_UPDATE; } else { update_result = ACPI_BATTERY_EASY_UPDATE; @@ -442,7 +428,7 @@ static int acpi_battery_update(struct acpi_battery *battery, end: - acpi_battery_init_update_flag(battery) = (result != 0); + battery->flags.init_update = (result != 0); *update_result_ptr = update_result; @@ -453,16 +439,19 @@ static void acpi_battery_notify_update(struct acpi_battery *battery) { acpi_battery_get_status(battery); - if (acpi_battery_init_update_flag(battery)) { + if (battery->flags.init_update) { return; } - if (acpi_battery_inserted(battery) || acpi_battery_removed(battery)) { - acpi_battery_init_update_flag(battery) = 1; + if ((!battery->flags.battery_present_prev & + acpi_battery_present(battery)) || + (battery->flags.battery_present_prev & + !acpi_battery_present(battery))) { + battery->flags.init_update = 1; } else { - acpi_battery_info_update_flag(battery) = 1; - acpi_battery_state_update_flag(battery) = 1; - acpi_battery_alarm_update_flag(battery) = 1; + battery->flags.update[ACPI_BATTERY_INFO] = 1; + battery->flags.update[ACPI_BATTERY_STATE] = 1; + battery->flags.update[ACPI_BATTERY_ALARM] = 1; } } @@ -472,7 +461,7 @@ static void acpi_battery_notify_update(struct acpi_battery *battery) static struct proc_dir_entry *acpi_battery_dir; -static int acpi_battery_read_info_print(struct seq_file *seq, int result) +static int acpi_battery_print_info(struct seq_file *seq, int result) { struct acpi_battery *battery = seq->private; struct acpi_battery_info *bif = NULL; @@ -549,49 +538,7 @@ static int acpi_battery_read_info_print(struct seq_file *seq, int result) return result; } -static int acpi_battery_read_info(struct seq_file *seq, void *offset) -{ - struct acpi_battery *battery = seq->private; - int result = 0; - int update_result = ACPI_BATTERY_NONE_UPDATE; - int update = 0; - - acpi_battery_mutex_lock(battery); - - update = (get_seconds() - battery->info_update_time >= update_time); - update = (update | acpi_battery_info_update_flag(battery)); - - result = acpi_battery_update(battery, update, &update_result); - if (result) - goto end; - - /* Battery Info (_BIF) */ - - if (update_result == ACPI_BATTERY_EASY_UPDATE) { - result = acpi_battery_get_info(battery); - if (result) - goto end; - } - - end: - - result = acpi_battery_read_info_print(seq, result); - - acpi_battery_check_result(battery, result); - - acpi_battery_info_update_flag(battery) = result; - - acpi_battery_mutex_unlock(battery); - - return result; -} - -static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_battery_read_info, PDE(inode)->data); -} - -static int acpi_battery_read_state_print(struct seq_file *seq, int result) +static int acpi_battery_print_state(struct seq_file *seq, int result) { struct acpi_battery *battery = seq->private; struct acpi_battery_state *bst = NULL; @@ -661,49 +608,7 @@ static int acpi_battery_read_state_print(struct seq_file *seq, int result) return result; } -static int acpi_battery_read_state(struct seq_file *seq, void *offset) -{ - struct acpi_battery *battery = seq->private; - int result = 0; - int update_result = ACPI_BATTERY_NONE_UPDATE; - int update = 0; - - acpi_battery_mutex_lock(battery); - - update = (get_seconds() - battery->state_update_time >= update_time); - update = (update | acpi_battery_state_update_flag(battery)); - - result = acpi_battery_update(battery, update, &update_result); - if (result) - goto end; - - /* Battery State (_BST) */ - - if (update_result == ACPI_BATTERY_EASY_UPDATE) { - result = acpi_battery_get_state(battery); - if (result) - goto end; - } - - end: - - result = acpi_battery_read_state_print(seq, result); - - acpi_battery_check_result(battery, result); - - acpi_battery_state_update_flag(battery) = result; - - acpi_battery_mutex_unlock(battery); - - return result; -} - -static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_battery_read_state, PDE(inode)->data); -} - -static int acpi_battery_read_alarm_print(struct seq_file *seq, int result) +static int acpi_battery_print_alarm(struct seq_file *seq, int result) { struct acpi_battery *battery = seq->private; char *units = "?"; @@ -734,43 +639,6 @@ static int acpi_battery_read_alarm_print(struct seq_file *seq, int result) return result; } -static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) -{ - struct acpi_battery *battery = seq->private; - int result = 0; - int update_result = ACPI_BATTERY_NONE_UPDATE; - int update = 0; - - acpi_battery_mutex_lock(battery); - - update = (get_seconds() - battery->alarm_update_time >= update_time); - update = (update | acpi_battery_alarm_update_flag(battery)); - - result = acpi_battery_update(battery, update, &update_result); - if (result) - goto end; - - /* Battery Alarm */ - - if (update_result == ACPI_BATTERY_EASY_UPDATE) { - result = acpi_battery_get_alarm(battery); - if (result) - goto end; - } - - end: - - result = acpi_battery_read_alarm_print(seq, result); - - acpi_battery_check_result(battery, result); - - acpi_battery_alarm_update_flag(battery) = result; - - acpi_battery_mutex_unlock(battery); - - return result; -} - static ssize_t acpi_battery_write_alarm(struct file *file, const char __user * buffer, @@ -785,7 +653,7 @@ acpi_battery_write_alarm(struct file *file, if (!battery || (count > sizeof(alarm_string) - 1)) return -EINVAL; - acpi_battery_mutex_lock(battery); + mutex_lock(&battery->mutex); result = acpi_battery_update(battery, 1, &update_result); if (result) { @@ -817,44 +685,128 @@ acpi_battery_write_alarm(struct file *file, if (!result) result = count; - acpi_battery_mutex_unlock(battery); + mutex_unlock(&battery->mutex); return result; } +typedef int(*print_func)(struct seq_file *seq, int result); +typedef int(*get_func)(struct acpi_battery *battery); + +static struct acpi_read_mux { + print_func print; + get_func get; +} acpi_read_funcs[ACPI_BATTERY_NUMFILES] = { + {.get = acpi_battery_get_info, .print = acpi_battery_print_info}, + {.get = acpi_battery_get_state, .print = acpi_battery_print_state}, + {.get = acpi_battery_get_alarm, .print = acpi_battery_print_alarm}, +}; + +static int acpi_battery_read(int fid, struct seq_file *seq) +{ + struct acpi_battery *battery = seq->private; + int result = 0; + int update_result = ACPI_BATTERY_NONE_UPDATE; + int update = 0; + + mutex_lock(&battery->mutex); + + update = (get_seconds() - battery->update_time[fid] >= update_time); + update = (update | battery->flags.update[fid]); + + result = acpi_battery_update(battery, update, &update_result); + if (result) + goto end; + + if (update_result == ACPI_BATTERY_EASY_UPDATE) { + result = acpi_read_funcs[fid].get(battery); + if (result) + goto end; + } + + end: + result = acpi_read_funcs[fid].print(seq, result); + acpi_battery_check_result(battery, result); + battery->flags.update[fid] = result; + mutex_unlock(&battery->mutex); + return result; +} + +static int acpi_battery_read_info(struct seq_file *seq, void *offset) +{ + return acpi_battery_read(ACPI_BATTERY_INFO, seq); +} + +static int acpi_battery_read_state(struct seq_file *seq, void *offset) +{ + return acpi_battery_read(ACPI_BATTERY_STATE, seq); +} + +static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) +{ + return acpi_battery_read(ACPI_BATTERY_ALARM, seq); +} + +static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_battery_read_info, PDE(inode)->data); +} + +static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, acpi_battery_read_state, PDE(inode)->data); +} + static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) { return single_open(file, acpi_battery_read_alarm, PDE(inode)->data); } -static const struct file_operations acpi_battery_info_ops = { +static struct battery_file { + struct file_operations ops; + mode_t mode; + char *name; +} acpi_battery_file[] = { + { + .name = "info", + .mode = S_IRUGO, + .ops = { .open = acpi_battery_info_open_fs, .read = seq_read, .llseek = seq_lseek, .release = single_release, .owner = THIS_MODULE, -}; - -static const struct file_operations acpi_battery_state_ops = { + }, + }, + { + .name = "state", + .mode = S_IRUGO, + .ops = { .open = acpi_battery_state_open_fs, .read = seq_read, .llseek = seq_lseek, .release = single_release, .owner = THIS_MODULE, -}; - -static const struct file_operations acpi_battery_alarm_ops = { + }, + }, + { + .name = "alarm", + .mode = S_IFREG | S_IRUGO | S_IWUSR, + .ops = { .open = acpi_battery_alarm_open_fs, .read = seq_read, .write = acpi_battery_write_alarm, .llseek = seq_lseek, .release = single_release, .owner = THIS_MODULE, + }, + }, }; static int acpi_battery_add_fs(struct acpi_device *device) { struct proc_dir_entry *entry = NULL; + int i; if (!acpi_device_dir(device)) { acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), @@ -864,38 +816,16 @@ static int acpi_battery_add_fs(struct acpi_device *device) acpi_device_dir(device)->owner = THIS_MODULE; } - /* 'info' [R] */ - entry = create_proc_entry(ACPI_BATTERY_FILE_INFO, - S_IRUGO, acpi_device_dir(device)); - if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_battery_info_ops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } - - /* 'status' [R] */ - entry = create_proc_entry(ACPI_BATTERY_FILE_STATE, - S_IRUGO, acpi_device_dir(device)); - if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_battery_state_ops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; - } - - /* 'alarm' [R/W] */ - entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM, - S_IFREG | S_IRUGO | S_IWUSR, - acpi_device_dir(device)); - if (!entry) - return -ENODEV; - else { - entry->proc_fops = &acpi_battery_alarm_ops; - entry->data = acpi_driver_data(device); - entry->owner = THIS_MODULE; + for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) { + entry = create_proc_entry(acpi_battery_file[i].name, + acpi_battery_file[i].mode, acpi_device_dir(device)); + if (!entry) + return -ENODEV; + else { + entry->proc_fops = &acpi_battery_file[i].ops; + entry->data = acpi_driver_data(device); + entry->owner = THIS_MODULE; + } } return 0; @@ -903,14 +833,12 @@ static int acpi_battery_add_fs(struct acpi_device *device) static int acpi_battery_remove_fs(struct acpi_device *device) { + int i; if (acpi_device_dir(device)) { - remove_proc_entry(ACPI_BATTERY_FILE_ALARM, + for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) { + remove_proc_entry(acpi_battery_file[i].name, acpi_device_dir(device)); - remove_proc_entry(ACPI_BATTERY_FILE_STATE, - acpi_device_dir(device)); - remove_proc_entry(ACPI_BATTERY_FILE_INFO, - acpi_device_dir(device)); - + } remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); acpi_device_dir(device) = NULL; } @@ -966,7 +894,7 @@ static int acpi_battery_add(struct acpi_device *device) mutex_init(&battery->mutex); - acpi_battery_mutex_lock(battery); + mutex_lock(&battery->mutex); battery->device = device; strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); @@ -977,7 +905,7 @@ static int acpi_battery_add(struct acpi_device *device) if (result) goto end; - acpi_battery_init_update_flag(battery) = 1; + battery->flags.init_update = 1; result = acpi_battery_add_fs(device); if (result) @@ -1003,7 +931,7 @@ static int acpi_battery_add(struct acpi_device *device) kfree(battery); } - acpi_battery_mutex_unlock(battery); + mutex_unlock(&battery->mutex); return result; } @@ -1018,7 +946,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type) battery = acpi_driver_data(device); - acpi_battery_mutex_lock(battery); + mutex_lock(&battery->mutex); status = acpi_remove_notify_handler(device->handle, ACPI_ALL_NOTIFY, @@ -1026,13 +954,11 @@ static int acpi_battery_remove(struct acpi_device *device, int type) acpi_battery_remove_fs(device); - if (battery->bif_data.pointer) - kfree(battery->bif_data.pointer); + kfree(battery->bif_data.pointer); - if (battery->bst_data.pointer) - kfree(battery->bst_data.pointer); + kfree(battery->bst_data.pointer); - acpi_battery_mutex_unlock(battery); + mutex_unlock(&battery->mutex); mutex_destroy(&battery->mutex); @@ -1051,7 +977,7 @@ static int acpi_battery_resume(struct acpi_device *device) battery = device->driver_data; - acpi_battery_init_update_flag(battery) = 1; + battery->flags.init_update = 1; return 0; }