From 038fdea2960be53f82353fd409526fb77a558c52 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 26 Sep 2007 19:42:46 +0400 Subject: ACPI: Battery: don't use acpi_extract_package() acpi_extract_package() creates more problems with memory management than it solves as helper for package handling. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/battery.c | 359 +++++++++++++++++++------------------------------ 1 file changed, 139 insertions(+), 220 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 9b2c0f7..de506f3 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -36,9 +36,6 @@ #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF -#define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS" -#define ACPI_BATTERY_FORMAT_BST "NNNN" - #define ACPI_BATTERY_COMPONENT 0x00040000 #define ACPI_BATTERY_CLASS "battery" #define ACPI_BATTERY_DEVICE_NAME "Battery" @@ -90,61 +87,49 @@ static struct acpi_driver acpi_battery_driver = { }, }; -struct acpi_battery_state { - acpi_integer state; - acpi_integer present_rate; - acpi_integer remaining_capacity; - acpi_integer present_voltage; -}; - -struct acpi_battery_info { - acpi_integer power_unit; - acpi_integer design_capacity; - acpi_integer last_full_capacity; - acpi_integer battery_technology; - acpi_integer design_voltage; - acpi_integer design_capacity_warning; - acpi_integer design_capacity_low; - acpi_integer battery_capacity_granularity_1; - acpi_integer battery_capacity_granularity_2; - acpi_string model_number; - acpi_string serial_number; - acpi_string battery_type; - acpi_string oem_info; -}; - -enum acpi_battery_files{ +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 update[ACPI_BATTERY_NUMFILES]; - u8 power_unit; -}; - struct acpi_battery { - struct mutex mutex; struct acpi_device *device; - struct acpi_battery_flags flags; - struct acpi_buffer bif_data; - struct acpi_buffer bst_data; + struct mutex lock; unsigned long alarm; unsigned long update_time[ACPI_BATTERY_NUMFILES]; + int state; + int present_rate; + int remaining_capacity; + int present_voltage; + int power_unit; + int design_capacity; + int last_full_capacity; + int technology; + int design_voltage; + int design_capacity_warning; + int design_capacity_low; + int capacity_granularity_1; + int capacity_granularity_2; + char model_number[32]; + char serial_number[32]; + char type[32]; + char oem_info[32]; + u8 present_prev; + u8 alarm_present; + u8 init_update; + u8 update[ACPI_BATTERY_NUMFILES]; }; 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) + if (battery->power_unit) return ACPI_BATTERY_UNITS_AMPS; else return ACPI_BATTERY_UNITS_WATTS; @@ -165,43 +150,63 @@ static void acpi_battery_check_result(struct acpi_battery *battery, int result) return; if (result) { - battery->flags.init_update = 1; + battery->init_update = 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 }; +struct acpi_offsets { + size_t offset; /* offset inside struct acpi_sbs_battery */ + u8 mode; /* int or string? */ +}; - 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; - } +static struct acpi_offsets state_offsets[] = { + {offsetof(struct acpi_battery, state), 0}, + {offsetof(struct acpi_battery, present_rate), 0}, + {offsetof(struct acpi_battery, remaining_capacity), 0}, + {offsetof(struct acpi_battery, present_voltage), 0}, +}; - if (data_null.length != data->length) { - 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; - } +static struct acpi_offsets info_offsets[] = { + {offsetof(struct acpi_battery, power_unit), 0}, + {offsetof(struct acpi_battery, design_capacity), 0}, + {offsetof(struct acpi_battery, last_full_capacity), 0}, + {offsetof(struct acpi_battery, technology), 0}, + {offsetof(struct acpi_battery, design_voltage), 0}, + {offsetof(struct acpi_battery, design_capacity_warning), 0}, + {offsetof(struct acpi_battery, design_capacity_low), 0}, + {offsetof(struct acpi_battery, capacity_granularity_1), 0}, + {offsetof(struct acpi_battery, capacity_granularity_2), 0}, + {offsetof(struct acpi_battery, model_number), 1}, + {offsetof(struct acpi_battery, serial_number), 1}, + {offsetof(struct acpi_battery, type), 1}, + {offsetof(struct acpi_battery, oem_info), 1}, +}; - status = acpi_extract_package(package, format, data); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Extracting %s", - package_name)); - return -ENODEV; +static int extract_package(struct acpi_battery *battery, + union acpi_object *package, + struct acpi_offsets *offsets, int num) +{ + int i, *x; + union acpi_object *element; + if (package->type != ACPI_TYPE_PACKAGE) + return -EFAULT; + for (i = 0; i < num; ++i) { + if (package->package.count <= i) + return -EFAULT; + element = &package->package.elements[i]; + if (offsets[i].mode) { + if (element->type != ACPI_TYPE_STRING && + element->type != ACPI_TYPE_BUFFER) + return -EFAULT; + strncpy((u8 *)battery + offsets[i].offset, + element->string.pointer, 32); + } else { + if (element->type != ACPI_TYPE_INTEGER) + return -EFAULT; + x = (int *)((u8 *)battery + offsets[i].offset); + *x = element->integer.value; + } } - return 0; } @@ -222,49 +227,21 @@ static int acpi_battery_get_info(struct acpi_battery *battery) int result = 0; acpi_status status = 0; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF), - ACPI_BATTERY_FORMAT_BIF - }; - union acpi_object *package = NULL; - struct acpi_buffer *data = NULL; - struct acpi_battery_info *bif = NULL; battery->update_time[ACPI_BATTERY_INFO] = get_seconds(); - if (!acpi_battery_present(battery)) return 0; - - /* Evaluate _BIF */ - - status = - acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL, - &buffer); + mutex_lock(&battery->lock); + status = acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", + NULL, &buffer); + mutex_unlock(&battery->lock); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); return -ENODEV; } - - package = buffer.pointer; - - data = &battery->bif_data; - - /* Extract Package Data */ - - result = - acpi_battery_extract_package(battery, package, &format, data, - "_BIF"); - if (result) - goto end; - - end: - + result = extract_package(battery, buffer.pointer, + info_offsets, ARRAY_SIZE(info_offsets)); kfree(buffer.pointer); - - if (!result) { - bif = data->pointer; - battery->flags.power_unit = bif->power_unit; - } - return result; } @@ -273,42 +250,24 @@ static int acpi_battery_get_state(struct acpi_battery *battery) int result = 0; acpi_status status = 0; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST), - ACPI_BATTERY_FORMAT_BST - }; - union acpi_object *package = NULL; - struct acpi_buffer *data = NULL; battery->update_time[ACPI_BATTERY_STATE] = get_seconds(); if (!acpi_battery_present(battery)) return 0; - /* Evaluate _BST */ + mutex_lock(&battery->lock); + status = acpi_evaluate_object(acpi_battery_handle(battery), "_BST", + NULL, &buffer); + mutex_unlock(&battery->lock); - status = - acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL, - &buffer); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST")); return -ENODEV; } - - package = buffer.pointer; - - data = &battery->bst_data; - - /* Extract Package Data */ - - result = - acpi_battery_extract_package(battery, package, &format, data, - "_BST"); - if (result) - goto end; - - end: + result = extract_package(battery, buffer.pointer, + state_offsets, ARRAY_SIZE(state_offsets)); kfree(buffer.pointer); - return result; } @@ -331,14 +290,15 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery, if (!acpi_battery_present(battery)) return -ENODEV; - if (!battery->flags.alarm_present) + if (!battery->alarm_present) return -ENODEV; arg0.integer.value = alarm; - status = - acpi_evaluate_object(acpi_battery_handle(battery), "_BTP", - &arg_list, NULL); + mutex_lock(&battery->lock); + status = acpi_evaluate_object(acpi_battery_handle(battery), "_BTP", + &arg_list, NULL); + mutex_unlock(&battery->lock); if (ACPI_FAILURE(status)) return -ENODEV; @@ -354,22 +314,21 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery) int result = 0; acpi_status status = AE_OK; acpi_handle handle = 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 */ status = acpi_get_handle(acpi_battery_handle(battery), "_BTP", &handle); if (ACPI_SUCCESS(status)) { - battery->flags.alarm_present = 1; - if (!alarm && bif) { - alarm = bif->design_capacity_warning; + battery->alarm_present = 1; + if (!alarm) { + alarm = battery->design_capacity_warning; } result = acpi_battery_set_alarm(battery, alarm); if (result) goto end; } else { - battery->flags.alarm_present = 0; + battery->alarm_present = 0; } end: @@ -385,7 +344,7 @@ static int acpi_battery_init_update(struct acpi_battery *battery) if (result) return result; - battery->flags.battery_present_prev = acpi_battery_present(battery); + battery->present_prev = acpi_battery_present(battery); if (acpi_battery_present(battery)) { result = acpi_battery_get_info(battery); @@ -411,7 +370,7 @@ static int acpi_battery_update(struct acpi_battery *battery, update = 1; } - if (battery->flags.init_update) { + if (battery->init_update) { result = acpi_battery_init_update(battery); if (result) goto end; @@ -420,8 +379,8 @@ static int acpi_battery_update(struct acpi_battery *battery, result = acpi_battery_get_status(battery); if (result) goto end; - if ((!battery->flags.battery_present_prev & acpi_battery_present(battery)) - || (battery->flags.battery_present_prev & !acpi_battery_present(battery))) { + if ((!battery->present_prev & acpi_battery_present(battery)) + || (battery->present_prev & !acpi_battery_present(battery))) { result = acpi_battery_init_update(battery); if (result) goto end; @@ -433,7 +392,7 @@ static int acpi_battery_update(struct acpi_battery *battery, end: - battery->flags.init_update = (result != 0); + battery->init_update = (result != 0); *update_result_ptr = update_result; @@ -444,19 +403,19 @@ static void acpi_battery_notify_update(struct acpi_battery *battery) { acpi_battery_get_status(battery); - if (battery->flags.init_update) { + if (battery->init_update) { return; } - if ((!battery->flags.battery_present_prev & + if ((!battery->present_prev & acpi_battery_present(battery)) || - (battery->flags.battery_present_prev & + (battery->present_prev & !acpi_battery_present(battery))) { - battery->flags.init_update = 1; + battery->init_update = 1; } else { - battery->flags.update[ACPI_BATTERY_INFO] = 1; - battery->flags.update[ACPI_BATTERY_STATE] = 1; - battery->flags.update[ACPI_BATTERY_ALARM] = 1; + battery->update[ACPI_BATTERY_INFO] = 1; + battery->update[ACPI_BATTERY_STATE] = 1; + battery->update[ACPI_BATTERY_ALARM] = 1; } } @@ -469,7 +428,6 @@ static struct proc_dir_entry *acpi_battery_dir; static int acpi_battery_print_info(struct seq_file *seq, int result) { struct acpi_battery *battery = seq->private; - struct acpi_battery_info *bif = NULL; char *units = "?"; if (result) @@ -482,30 +440,23 @@ static int acpi_battery_print_info(struct seq_file *seq, int result) goto end; } - bif = battery->bif_data.pointer; - if (!bif) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BIF buffer is NULL")); - result = -ENODEV; - goto end; - } - /* Battery Units */ units = acpi_battery_power_units(battery); - if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "design capacity: unknown\n"); else seq_printf(seq, "design capacity: %d %sh\n", - (u32) bif->design_capacity, units); + (u32) battery->design_capacity, units); - if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + if (battery->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "last full capacity: unknown\n"); else seq_printf(seq, "last full capacity: %d %sh\n", - (u32) bif->last_full_capacity, units); + (u32) battery->last_full_capacity, units); - switch ((u32) bif->battery_technology) { + switch ((u32) battery->technology) { case 0: seq_printf(seq, "battery technology: non-rechargeable\n"); break; @@ -517,23 +468,23 @@ static int acpi_battery_print_info(struct seq_file *seq, int result) break; } - if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) + if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "design voltage: unknown\n"); else seq_printf(seq, "design voltage: %d mV\n", - (u32) bif->design_voltage); + (u32) battery->design_voltage); seq_printf(seq, "design capacity warning: %d %sh\n", - (u32) bif->design_capacity_warning, units); + (u32) battery->design_capacity_warning, units); seq_printf(seq, "design capacity low: %d %sh\n", - (u32) bif->design_capacity_low, units); + (u32) battery->design_capacity_low, units); seq_printf(seq, "capacity granularity 1: %d %sh\n", - (u32) bif->battery_capacity_granularity_1, units); + (u32) battery->capacity_granularity_1, units); seq_printf(seq, "capacity granularity 2: %d %sh\n", - (u32) bif->battery_capacity_granularity_2, units); - seq_printf(seq, "model number: %s\n", bif->model_number); - seq_printf(seq, "serial number: %s\n", bif->serial_number); - seq_printf(seq, "battery type: %s\n", bif->battery_type); - seq_printf(seq, "OEM info: %s\n", bif->oem_info); + (u32) battery->capacity_granularity_2, units); + seq_printf(seq, "model number: %s\n", battery->model_number); + seq_printf(seq, "serial number: %s\n", battery->serial_number); + seq_printf(seq, "battery type: %s\n", battery->type); + seq_printf(seq, "OEM info: %s\n", battery->oem_info); end: @@ -546,7 +497,6 @@ static int acpi_battery_print_info(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; char *units = "?"; if (result) @@ -559,50 +509,43 @@ static int acpi_battery_print_state(struct seq_file *seq, int result) goto end; } - 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)) + if (!(battery->state & 0x04)) seq_printf(seq, "capacity state: ok\n"); else seq_printf(seq, "capacity state: critical\n"); - if ((bst->state & 0x01) && (bst->state & 0x02)) { + if ((battery->state & 0x01) && (battery->state & 0x02)) { seq_printf(seq, "charging state: charging/discharging\n"); - } else if (bst->state & 0x01) + } else if (battery->state & 0x01) seq_printf(seq, "charging state: discharging\n"); - else if (bst->state & 0x02) + else if (battery->state & 0x02) seq_printf(seq, "charging state: charging\n"); else { seq_printf(seq, "charging state: charged\n"); } - if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN) + if (battery->present_rate == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "present rate: unknown\n"); else seq_printf(seq, "present rate: %d %s\n", - (u32) bst->present_rate, units); + (u32) battery->present_rate, units); - if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + if (battery->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "remaining capacity: unknown\n"); else seq_printf(seq, "remaining capacity: %d %sh\n", - (u32) bst->remaining_capacity, units); + (u32) battery->remaining_capacity, units); - if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN) + if (battery->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "present voltage: unknown\n"); else seq_printf(seq, "present voltage: %d mV\n", - (u32) bst->present_voltage); + (u32) battery->present_voltage); end: @@ -658,8 +601,6 @@ acpi_battery_write_alarm(struct file *file, if (!battery || (count > sizeof(alarm_string) - 1)) return -EINVAL; - mutex_lock(&battery->mutex); - result = acpi_battery_update(battery, 1, &update_result); if (result) { result = -ENODEV; @@ -689,9 +630,6 @@ acpi_battery_write_alarm(struct file *file, if (!result) result = count; - - mutex_unlock(&battery->mutex); - return result; } @@ -714,10 +652,8 @@ static int acpi_battery_read(int fid, struct seq_file *seq) 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]); + update = (update | battery->update[fid]); result = acpi_battery_update(battery, update, &update_result); if (result) @@ -732,8 +668,7 @@ static int acpi_battery_read(int fid, struct seq_file *seq) end: result = acpi_read_funcs[fid].print(seq, result); acpi_battery_check_result(battery, result); - battery->flags.update[fid] = result; - mutex_unlock(&battery->mutex); + battery->update[fid] = result; return result; } @@ -900,20 +835,16 @@ static int acpi_battery_add(struct acpi_device *device) if (!battery) return -ENOMEM; - mutex_init(&battery->mutex); - - mutex_lock(&battery->mutex); - 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; - + mutex_init(&battery->lock); result = acpi_battery_get_status(battery); if (result) goto end; - battery->flags.init_update = 1; + battery->init_update = 1; result = acpi_battery_add_fs(device); if (result) @@ -939,8 +870,6 @@ static int acpi_battery_add(struct acpi_device *device) kfree(battery); } - mutex_unlock(&battery->mutex); - return result; } @@ -954,22 +883,12 @@ static int acpi_battery_remove(struct acpi_device *device, int type) battery = acpi_driver_data(device); - mutex_lock(&battery->mutex); - status = acpi_remove_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_battery_notify); acpi_battery_remove_fs(device); - - kfree(battery->bif_data.pointer); - - kfree(battery->bst_data.pointer); - - mutex_unlock(&battery->mutex); - - mutex_destroy(&battery->mutex); - + mutex_destroy(&battery->lock); kfree(battery); return 0; @@ -985,7 +904,7 @@ static int acpi_battery_resume(struct acpi_device *device) battery = device->driver_data; - battery->flags.init_update = 1; + battery->init_update = 1; return 0; } -- cgit v1.1 From f1d4661abe05d0a2c014166042d15ed8b69ae8f2 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 26 Sep 2007 19:42:52 +0400 Subject: ACPI: Battery: simplify update scheme Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/battery.c | 280 ++++++++++--------------------------------------- 1 file changed, 57 insertions(+), 223 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index de506f3..faa70a5 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -41,27 +42,18 @@ #define ACPI_BATTERY_DEVICE_NAME "Battery" #define ACPI_BATTERY_NOTIFY_STATUS 0x80 #define ACPI_BATTERY_NOTIFY_INFO 0x81 -#define ACPI_BATTERY_UNITS_WATTS "mW" -#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); +static unsigned int cache_time = 1000; +module_param(cache_time, uint, 0644); +MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); extern struct proc_dir_entry *acpi_lock_battery_dir(void); extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); @@ -95,15 +87,12 @@ enum acpi_battery_files { }; struct acpi_battery { - struct acpi_device *device; struct mutex lock; - unsigned long alarm; - unsigned long update_time[ACPI_BATTERY_NUMFILES]; - int state; + struct acpi_device *device; + unsigned long update_time; int present_rate; int remaining_capacity; int present_voltage; - int power_unit; int design_capacity; int last_full_capacity; int technology; @@ -112,14 +101,14 @@ struct acpi_battery { int design_capacity_low; int capacity_granularity_1; int capacity_granularity_2; + int alarm; char model_number[32]; char serial_number[32]; char type[32]; char oem_info[32]; - u8 present_prev; + int state; + int power_unit; u8 alarm_present; - u8 init_update; - u8 update[ACPI_BATTERY_NUMFILES]; }; inline int acpi_battery_present(struct acpi_battery *battery) @@ -127,33 +116,15 @@ 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) +inline char *acpi_battery_units(struct acpi_battery *battery) { - if (battery->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; + return (battery->power_unit)?"mA":"mW"; } /* -------------------------------------------------------------------------- Battery Management -------------------------------------------------------------------------- */ -static void acpi_battery_check_result(struct acpi_battery *battery, int result) -{ - if (!battery) - return; - - if (result) { - battery->init_update = 1; - } -} - struct acpi_offsets { size_t offset; /* offset inside struct acpi_sbs_battery */ u8 mode; /* int or string? */ @@ -228,11 +199,10 @@ static int acpi_battery_get_info(struct acpi_battery *battery) acpi_status status = 0; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - battery->update_time[ACPI_BATTERY_INFO] = get_seconds(); if (!acpi_battery_present(battery)) return 0; mutex_lock(&battery->lock); - status = acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", + status = acpi_evaluate_object(battery->device->handle, "_BIF", NULL, &buffer); mutex_unlock(&battery->lock); if (ACPI_FAILURE(status)) { @@ -251,13 +221,16 @@ static int acpi_battery_get_state(struct acpi_battery *battery) acpi_status status = 0; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - battery->update_time[ACPI_BATTERY_STATE] = get_seconds(); - if (!acpi_battery_present(battery)) return 0; + if (battery->update_time && + time_before(jiffies, battery->update_time + + msecs_to_jiffies(cache_time))) + return 0; + mutex_lock(&battery->lock); - status = acpi_evaluate_object(acpi_battery_handle(battery), "_BST", + status = acpi_evaluate_object(battery->device->handle, "_BST", NULL, &buffer); mutex_unlock(&battery->lock); @@ -267,14 +240,13 @@ static int acpi_battery_get_state(struct acpi_battery *battery) } result = extract_package(battery, buffer.pointer, state_offsets, ARRAY_SIZE(state_offsets)); + battery->update_time = jiffies; kfree(buffer.pointer); return result; } static int acpi_battery_get_alarm(struct acpi_battery *battery) { - battery->update_time[ACPI_BATTERY_ALARM] = get_seconds(); - return 0; } @@ -285,8 +257,6 @@ 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->update_time[ACPI_BATTERY_ALARM] = get_seconds(); - if (!acpi_battery_present(battery)) return -ENODEV; @@ -296,8 +266,8 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery, arg0.integer.value = alarm; mutex_lock(&battery->lock); - status = acpi_evaluate_object(acpi_battery_handle(battery), "_BTP", - &arg_list, NULL); + status = acpi_evaluate_object(battery->device->handle, "_BTP", + &arg_list, NULL); mutex_unlock(&battery->lock); if (ACPI_FAILURE(status)) return -ENODEV; @@ -311,112 +281,36 @@ static int acpi_battery_set_alarm(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; - unsigned long alarm = battery->alarm; /* See if alarms are supported, and if so, set default */ - - status = acpi_get_handle(acpi_battery_handle(battery), "_BTP", &handle); - if (ACPI_SUCCESS(status)) { - battery->alarm_present = 1; - if (!alarm) { - alarm = battery->design_capacity_warning; - } - result = acpi_battery_set_alarm(battery, alarm); - if (result) - goto end; - } else { + status = acpi_get_handle(battery->device->handle, "_BTP", &handle); + if (ACPI_FAILURE(status)) { battery->alarm_present = 0; + return 0; } - - end: - - return result; + battery->alarm_present = 1; + if (!battery->alarm) + battery->alarm = battery->design_capacity_warning; + return acpi_battery_set_alarm(battery, battery->alarm); } -static int acpi_battery_init_update(struct acpi_battery *battery) +static int acpi_battery_update(struct acpi_battery *battery) { - int result = 0; - - result = acpi_battery_get_status(battery); - if (result) + int saved_present = acpi_battery_present(battery); + int result = acpi_battery_get_status(battery); + if (result || !acpi_battery_present(battery)) return result; - - battery->present_prev = acpi_battery_present(battery); - - if (acpi_battery_present(battery)) { + if (saved_present != acpi_battery_present(battery) || + !battery->update_time) { + battery->update_time = 0; 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 (battery->init_update) { - 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 ((!battery->present_prev & acpi_battery_present(battery)) - || (battery->present_prev & !acpi_battery_present(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: - - battery->init_update = (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 (battery->init_update) { - return; - } - - if ((!battery->present_prev & - acpi_battery_present(battery)) || - (battery->present_prev & - !acpi_battery_present(battery))) { - battery->init_update = 1; - } else { - battery->update[ACPI_BATTERY_INFO] = 1; - battery->update[ACPI_BATTERY_STATE] = 1; - battery->update[ACPI_BATTERY_ALARM] = 1; - } + return acpi_battery_get_state(battery); } /* -------------------------------------------------------------------------- @@ -442,7 +336,7 @@ static int acpi_battery_print_info(struct seq_file *seq, int result) /* Battery Units */ - units = acpi_battery_power_units(battery); + units = acpi_battery_units(battery); if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "design capacity: unknown\n"); @@ -511,7 +405,7 @@ static int acpi_battery_print_state(struct seq_file *seq, int result) /* Battery Units */ - units = acpi_battery_power_units(battery); + units = acpi_battery_units(battery); if (!(battery->state & 0x04)) seq_printf(seq, "capacity state: ok\n"); @@ -571,13 +465,13 @@ static int acpi_battery_print_alarm(struct seq_file *seq, int result) /* Battery Units */ - units = acpi_battery_power_units(battery); + units = acpi_battery_units(battery); seq_printf(seq, "alarm: "); if (!battery->alarm) seq_printf(seq, "unsupported\n"); else - seq_printf(seq, "%lu %sh\n", battery->alarm, units); + seq_printf(seq, "%u %sh\n", battery->alarm, units); end: @@ -587,49 +481,35 @@ static int acpi_battery_print_alarm(struct seq_file *seq, int result) return result; } -static ssize_t -acpi_battery_write_alarm(struct file *file, - const char __user * buffer, - size_t count, loff_t * ppos) +static ssize_t acpi_battery_write_alarm(struct file *file, + const char __user * buffer, + size_t count, loff_t * ppos) { int result = 0; 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; - - result = acpi_battery_update(battery, 1, &update_result); if (result) { result = -ENODEV; goto end; } - 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) - goto end; - + battery->alarm = simple_strtol(alarm_string, NULL, 0); + result = acpi_battery_set_alarm(battery, battery->alarm); end: - - acpi_battery_check_result(battery, result); - if (!result) - result = count; + return count; return result; } @@ -648,28 +528,8 @@ static struct acpi_read_mux { 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; - - update = (get_seconds() - battery->update_time[fid] >= update_time); - update = (update | battery->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->update[fid] = result; - return result; + int result = acpi_battery_update(battery); + return acpi_read_funcs[fid].print(seq, result); } static int acpi_battery_read_info(struct seq_file *seq, void *offset) @@ -793,33 +653,16 @@ static int acpi_battery_remove_fs(struct acpi_device *device) static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) { struct acpi_battery *battery = data; - struct acpi_device *device = NULL; - + struct acpi_device *device; if (!battery) return; - device = battery->device; - - switch (event) { - case ACPI_BATTERY_NOTIFY_STATUS: - case ACPI_BATTERY_NOTIFY_INFO: - case ACPI_NOTIFY_BUS_CHECK: - case ACPI_NOTIFY_DEVICE_CHECK: - device = battery->device; - acpi_battery_notify_update(battery); - acpi_bus_generate_proc_event(device, event, + acpi_battery_update(battery); + acpi_bus_generate_proc_event(device, event, + acpi_battery_present(battery)); + acpi_bus_generate_netlink_event(device->pnp.device_class, + device->dev.bus_id, event, acpi_battery_present(battery)); - acpi_bus_generate_netlink_event(device->pnp.device_class, - device->dev.bus_id, event, - acpi_battery_present(battery)); - break; - default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Unsupported event [0x%x]\n", event)); - break; - } - - return; } static int acpi_battery_add(struct acpi_device *device) @@ -840,12 +683,7 @@ static int acpi_battery_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); acpi_driver_data(device) = battery; mutex_init(&battery->lock); - result = acpi_battery_get_status(battery); - if (result) - goto end; - - battery->init_update = 1; - + acpi_battery_update(battery); result = acpi_battery_add_fs(device); if (result) goto end; @@ -898,14 +736,10 @@ static int acpi_battery_remove(struct acpi_device *device, int type) static int acpi_battery_resume(struct acpi_device *device) { struct acpi_battery *battery; - if (!device) return -EINVAL; - - battery = device->driver_data; - - battery->init_update = 1; - + battery = acpi_driver_data(device); + battery->update_time = 0; return 0; } -- cgit v1.1 From aa650bbdcb94bde4292eabc44490970825c98669 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 26 Sep 2007 19:42:58 +0400 Subject: ACPI: Battery: Misc clean-ups, no functional changes Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/battery.c | 342 ++++++++++++++++++------------------------------- 1 file changed, 125 insertions(+), 217 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index faa70a5..db725bf 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -1,6 +1,8 @@ /* - * acpi_battery.c - ACPI Battery Driver ($Revision: 37 $) + * battery.c - ACPI Battery Driver (Revision: 2.0) * + * Copyright (C) 2007 Alexey Starikovskiy + * Copyright (C) 2004-2007 Vladimir Lebedev * Copyright (C) 2001, 2002 Andy Grover * Copyright (C) 2001, 2002 Paul Diefenbaugh * @@ -48,6 +50,7 @@ ACPI_MODULE_NAME("battery"); MODULE_AUTHOR("Paul Diefenbaugh"); +MODULE_AUTHOR("Alexey Starikovskiy "); MODULE_DESCRIPTION("ACPI Battery Driver"); MODULE_LICENSE("GPL"); @@ -58,31 +61,17 @@ MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); extern struct proc_dir_entry *acpi_lock_battery_dir(void); extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); -static int acpi_battery_add(struct acpi_device *device); -static int acpi_battery_remove(struct acpi_device *device, int type); -static int acpi_battery_resume(struct acpi_device *device); - static const struct acpi_device_id battery_device_ids[] = { {"PNP0C0A", 0}, {"", 0}, }; -MODULE_DEVICE_TABLE(acpi, battery_device_ids); -static struct acpi_driver acpi_battery_driver = { - .name = "battery", - .class = ACPI_BATTERY_CLASS, - .ids = battery_device_ids, - .ops = { - .add = acpi_battery_add, - .resume = acpi_battery_resume, - .remove = acpi_battery_remove, - }, -}; +MODULE_DEVICE_TABLE(acpi, battery_device_ids); enum acpi_battery_files { - ACPI_BATTERY_INFO = 0, - ACPI_BATTERY_STATE, - ACPI_BATTERY_ALARM, + info_tag = 0, + state_tag, + alarm_tag, ACPI_BATTERY_NUMFILES, }; @@ -124,7 +113,6 @@ inline char *acpi_battery_units(struct acpi_battery *battery) /* -------------------------------------------------------------------------- Battery Management -------------------------------------------------------------------------- */ - struct acpi_offsets { size_t offset; /* offset inside struct acpi_sbs_battery */ u8 mode; /* int or string? */ @@ -183,19 +171,16 @@ static int extract_package(struct acpi_battery *battery, static int acpi_battery_get_status(struct acpi_battery *battery) { - int result = 0; - - result = acpi_bus_get_status(battery->device); - if (result) { + if (acpi_bus_get_status(battery->device)) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA")); return -ENODEV; } - return result; + return 0; } static int acpi_battery_get_info(struct acpi_battery *battery) { - int result = 0; + int result = -EFAULT; acpi_status status = 0; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -205,10 +190,12 @@ static int acpi_battery_get_info(struct acpi_battery *battery) status = acpi_evaluate_object(battery->device->handle, "_BIF", NULL, &buffer); mutex_unlock(&battery->lock); + if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); return -ENODEV; } + result = extract_package(battery, buffer.pointer, info_offsets, ARRAY_SIZE(info_offsets)); kfree(buffer.pointer); @@ -238,6 +225,7 @@ static int acpi_battery_get_state(struct acpi_battery *battery) ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST")); return -ENODEV; } + result = extract_package(battery, buffer.pointer, state_offsets, ARRAY_SIZE(state_offsets)); battery->update_time = jiffies; @@ -245,37 +233,26 @@ static int acpi_battery_get_state(struct acpi_battery *battery) return result; } -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) { acpi_status status = 0; - union acpi_object arg0 = { ACPI_TYPE_INTEGER }; + union acpi_object arg0 = { .type = ACPI_TYPE_INTEGER }; struct acpi_object_list arg_list = { 1, &arg0 }; - if (!acpi_battery_present(battery)) - return -ENODEV; - - if (!battery->alarm_present) + if (!acpi_battery_present(battery)|| !battery->alarm_present) return -ENODEV; - arg0.integer.value = alarm; + arg0.integer.value = battery->alarm; mutex_lock(&battery->lock); status = acpi_evaluate_object(battery->device->handle, "_BTP", &arg_list, NULL); mutex_unlock(&battery->lock); + if (ACPI_FAILURE(status)) return -ENODEV; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", (u32) alarm)); - - battery->alarm = alarm; - + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", battery->alarm)); return 0; } @@ -293,7 +270,7 @@ static int acpi_battery_init_alarm(struct acpi_battery *battery) battery->alarm_present = 1; if (!battery->alarm) battery->alarm = battery->design_capacity_warning; - return acpi_battery_set_alarm(battery, battery->alarm); + return acpi_battery_set_alarm(battery); } static int acpi_battery_update(struct acpi_battery *battery) @@ -322,130 +299,101 @@ static struct proc_dir_entry *acpi_battery_dir; static int acpi_battery_print_info(struct seq_file *seq, int result) { struct acpi_battery *battery = seq->private; - char *units = "?"; if (result) goto end; - if (acpi_battery_present(battery)) - seq_printf(seq, "present: yes\n"); - else { - seq_printf(seq, "present: no\n"); + seq_printf(seq, "present: %s\n", + acpi_battery_present(battery)?"yes":"no"); + if (!acpi_battery_present(battery)) goto end; - } - - /* Battery Units */ - - units = acpi_battery_units(battery); - if (battery->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "design capacity: unknown\n"); else seq_printf(seq, "design capacity: %d %sh\n", - (u32) battery->design_capacity, units); + battery->design_capacity, + acpi_battery_units(battery)); if (battery->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "last full capacity: unknown\n"); else seq_printf(seq, "last full capacity: %d %sh\n", - (u32) battery->last_full_capacity, units); - - switch ((u32) battery->technology) { - case 0: - seq_printf(seq, "battery technology: non-rechargeable\n"); - break; - case 1: - seq_printf(seq, "battery technology: rechargeable\n"); - break; - default: - seq_printf(seq, "battery technology: unknown\n"); - break; - } + battery->last_full_capacity, + acpi_battery_units(battery)); + + seq_printf(seq, "battery technology: %srechargeable\n", + (!battery->technology)?"non-":""); if (battery->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "design voltage: unknown\n"); else seq_printf(seq, "design voltage: %d mV\n", - (u32) battery->design_voltage); + battery->design_voltage); seq_printf(seq, "design capacity warning: %d %sh\n", - (u32) battery->design_capacity_warning, units); + battery->design_capacity_warning, + acpi_battery_units(battery)); seq_printf(seq, "design capacity low: %d %sh\n", - (u32) battery->design_capacity_low, units); + battery->design_capacity_low, + acpi_battery_units(battery)); seq_printf(seq, "capacity granularity 1: %d %sh\n", - (u32) battery->capacity_granularity_1, units); + battery->capacity_granularity_1, + acpi_battery_units(battery)); seq_printf(seq, "capacity granularity 2: %d %sh\n", - (u32) battery->capacity_granularity_2, units); + battery->capacity_granularity_2, + acpi_battery_units(battery)); seq_printf(seq, "model number: %s\n", battery->model_number); seq_printf(seq, "serial number: %s\n", battery->serial_number); seq_printf(seq, "battery type: %s\n", battery->type); seq_printf(seq, "OEM info: %s\n", battery->oem_info); - end: - if (result) seq_printf(seq, "ERROR: Unable to read battery info\n"); - return result; } static int acpi_battery_print_state(struct seq_file *seq, int result) { struct acpi_battery *battery = seq->private; - char *units = "?"; if (result) goto end; - if (acpi_battery_present(battery)) - seq_printf(seq, "present: yes\n"); - else { - seq_printf(seq, "present: no\n"); + seq_printf(seq, "present: %s\n", + acpi_battery_present(battery)?"yes":"no"); + if (!acpi_battery_present(battery)) goto end; - } - - /* Battery Units */ - - units = acpi_battery_units(battery); - if (!(battery->state & 0x04)) - seq_printf(seq, "capacity state: ok\n"); - else - seq_printf(seq, "capacity state: critical\n"); - - if ((battery->state & 0x01) && (battery->state & 0x02)) { + seq_printf(seq, "capacity state: %s\n", + (battery->state & 0x04)?"critical":"ok"); + if ((battery->state & 0x01) && (battery->state & 0x02)) seq_printf(seq, "charging state: charging/discharging\n"); - } else if (battery->state & 0x01) + else if (battery->state & 0x01) seq_printf(seq, "charging state: discharging\n"); else if (battery->state & 0x02) seq_printf(seq, "charging state: charging\n"); - else { + else seq_printf(seq, "charging state: charged\n"); - } if (battery->present_rate == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "present rate: unknown\n"); else seq_printf(seq, "present rate: %d %s\n", - (u32) battery->present_rate, units); + battery->present_rate, acpi_battery_units(battery)); if (battery->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "remaining capacity: unknown\n"); else seq_printf(seq, "remaining capacity: %d %sh\n", - (u32) battery->remaining_capacity, units); - + battery->remaining_capacity, acpi_battery_units(battery)); if (battery->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "present voltage: unknown\n"); else seq_printf(seq, "present voltage: %d mV\n", - (u32) battery->present_voltage); - + battery->present_voltage); end: - - if (result) { + if (result) seq_printf(seq, "ERROR: Unable to read battery state\n"); - } return result; } @@ -453,7 +401,6 @@ static int acpi_battery_print_state(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 = "?"; if (result) goto end; @@ -462,22 +409,15 @@ static int acpi_battery_print_alarm(struct seq_file *seq, int result) seq_printf(seq, "present: no\n"); goto end; } - - /* Battery Units */ - - units = acpi_battery_units(battery); - seq_printf(seq, "alarm: "); if (!battery->alarm) seq_printf(seq, "unsupported\n"); else - seq_printf(seq, "%u %sh\n", battery->alarm, units); - + seq_printf(seq, "%u %sh\n", battery->alarm, + acpi_battery_units(battery)); end: - if (result) seq_printf(seq, "ERROR: Unable to read battery alarm\n"); - return result; } @@ -506,7 +446,7 @@ static ssize_t acpi_battery_write_alarm(struct file *file, } alarm_string[count] = '\0'; battery->alarm = simple_strtol(alarm_string, NULL, 0); - result = acpi_battery_set_alarm(battery, battery->alarm); + result = acpi_battery_set_alarm(battery); end: if (!result) return count; @@ -514,95 +454,76 @@ static ssize_t acpi_battery_write_alarm(struct file *file, } 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 print_func acpi_print_funcs[ACPI_BATTERY_NUMFILES] = { + acpi_battery_print_info, + acpi_battery_print_state, + acpi_battery_print_alarm, }; static int acpi_battery_read(int fid, struct seq_file *seq) { struct acpi_battery *battery = seq->private; int result = acpi_battery_update(battery); - return acpi_read_funcs[fid].print(seq, 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); + return acpi_print_funcs[fid](seq, 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); +#define DECLARE_FILE_FUNCTIONS(_name) \ +static int acpi_battery_read_##_name(struct seq_file *seq, void *offset) \ +{ \ + return acpi_battery_read(_name##_tag, seq); \ +} \ +static int acpi_battery_##_name##_open_fs(struct inode *inode, struct file *file) \ +{ \ + return single_open(file, acpi_battery_read_##_name, 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); -} +DECLARE_FILE_FUNCTIONS(info); +DECLARE_FILE_FUNCTIONS(state); +DECLARE_FILE_FUNCTIONS(alarm); + +#undef DECLARE_FILE_FUNCTIONS + +#define FILE_DESCRIPTION_RO(_name) \ + { \ + .name = __stringify(_name), \ + .mode = S_IRUGO, \ + .ops = { \ + .open = acpi_battery_##_name##_open_fs, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .release = single_release, \ + .owner = THIS_MODULE, \ + }, \ + } -static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_battery_read_alarm, PDE(inode)->data); -} +#define FILE_DESCRIPTION_RW(_name) \ + { \ + .name = __stringify(_name), \ + .mode = S_IFREG | S_IRUGO | S_IWUSR, \ + .ops = { \ + .open = acpi_battery_##_name##_open_fs, \ + .read = seq_read, \ + .llseek = seq_lseek, \ + .write = acpi_battery_write_##_name, \ + .release = single_release, \ + .owner = THIS_MODULE, \ + }, \ + } 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, - }, - }, - { - .name = "state", - .mode = S_IRUGO, - .ops = { - .open = acpi_battery_state_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .owner = THIS_MODULE, - }, - }, - { - .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, - }, - }, + FILE_DESCRIPTION_RO(info), + FILE_DESCRIPTION_RO(state), + FILE_DESCRIPTION_RW(alarm), }; +#undef FILE_DESCRIPTION_RO +#undef FILE_DESCRIPTION_RW + static int acpi_battery_add_fs(struct acpi_device *device) { struct proc_dir_entry *entry = NULL; @@ -627,23 +548,20 @@ static int acpi_battery_add_fs(struct acpi_device *device) entry->owner = THIS_MODULE; } } - return 0; } -static int acpi_battery_remove_fs(struct acpi_device *device) +static void acpi_battery_remove_fs(struct acpi_device *device) { int i; - if (acpi_device_dir(device)) { - for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) { - remove_proc_entry(acpi_battery_file[i].name, + if (!acpi_device_dir(device)) + return; + for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) + remove_proc_entry(acpi_battery_file[i].name, acpi_device_dir(device)); - } - remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); - acpi_device_dir(device) = NULL; - } - return 0; + remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); + acpi_device_dir(device) = NULL; } /* -------------------------------------------------------------------------- @@ -670,14 +588,11 @@ static int acpi_battery_add(struct acpi_device *device) int result = 0; acpi_status status = 0; struct acpi_battery *battery = NULL; - if (!device) return -EINVAL; - battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL); if (!battery) return -ENOMEM; - battery->device = device; strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); @@ -687,7 +602,6 @@ static int acpi_battery_add(struct acpi_device *device) result = acpi_battery_add_fs(device); if (result) goto end; - status = acpi_install_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_battery_notify, battery); @@ -696,18 +610,14 @@ static int acpi_battery_add(struct acpi_device *device) result = -ENODEV; goto end; } - printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n", ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device), device->status.battery_present ? "present" : "absent"); - end: - if (result) { acpi_battery_remove_fs(device); kfree(battery); } - return result; } @@ -718,17 +628,13 @@ static int acpi_battery_remove(struct acpi_device *device, int type) if (!device || !acpi_driver_data(device)) return -EINVAL; - battery = acpi_driver_data(device); - status = acpi_remove_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_battery_notify); - acpi_battery_remove_fs(device); mutex_destroy(&battery->lock); kfree(battery); - return 0; } @@ -743,33 +649,35 @@ static int acpi_battery_resume(struct acpi_device *device) return 0; } +static struct acpi_driver acpi_battery_driver = { + .name = "battery", + .class = ACPI_BATTERY_CLASS, + .ids = battery_device_ids, + .ops = { + .add = acpi_battery_add, + .resume = acpi_battery_resume, + .remove = acpi_battery_remove, + }, +}; + static int __init acpi_battery_init(void) { - int result; - if (acpi_disabled) return -ENODEV; - acpi_battery_dir = acpi_lock_battery_dir(); if (!acpi_battery_dir) return -ENODEV; - - result = acpi_bus_register_driver(&acpi_battery_driver); - if (result < 0) { + if (acpi_bus_register_driver(&acpi_battery_driver) < 0) { acpi_unlock_battery_dir(acpi_battery_dir); return -ENODEV; } - return 0; } static void __exit acpi_battery_exit(void) { acpi_bus_unregister_driver(&acpi_battery_driver); - acpi_unlock_battery_dir(acpi_battery_dir); - - return; } module_init(acpi_battery_init); -- cgit v1.1 From d7380965752505951668e85de59c128d1d6fd21f Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 26 Sep 2007 19:43:04 +0400 Subject: ACPI: Battery: Add sysfs support Refer to Documentation/power_supply_class.txt for interface description. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 2 +- drivers/acpi/battery.c | 186 +++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 165 insertions(+), 23 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 4875f01..8560bc3 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -97,7 +97,7 @@ config ACPI_AC config ACPI_BATTERY tristate "Battery" - depends on X86 + depends on X86 && POWER_SUPPLY default y help This driver adds support for battery information through diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index db725bf..057a5eb 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -30,13 +30,18 @@ #include #include #include + +#ifdef CONFIG_ACPI_PROCFS #include #include #include +#endif #include #include +#include + #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF #define ACPI_BATTERY_COMPONENT 0x00040000 @@ -58,9 +63,19 @@ static unsigned int cache_time = 1000; module_param(cache_time, uint, 0644); MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); +#ifdef CONFIG_ACPI_PROCFS extern struct proc_dir_entry *acpi_lock_battery_dir(void); extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); +enum acpi_battery_files { + info_tag = 0, + state_tag, + alarm_tag, + ACPI_BATTERY_NUMFILES, +}; + +#endif + static const struct acpi_device_id battery_device_ids[] = { {"PNP0C0A", 0}, {"", 0}, @@ -68,22 +83,17 @@ static const struct acpi_device_id battery_device_ids[] = { MODULE_DEVICE_TABLE(acpi, battery_device_ids); -enum acpi_battery_files { - info_tag = 0, - state_tag, - alarm_tag, - ACPI_BATTERY_NUMFILES, -}; struct acpi_battery { struct mutex lock; + struct power_supply bat; struct acpi_device *device; unsigned long update_time; - int present_rate; - int remaining_capacity; - int present_voltage; + int current_now; + int capacity_now; + int voltage_now; int design_capacity; - int last_full_capacity; + int full_charge_capacity; int technology; int design_voltage; int design_capacity_warning; @@ -100,15 +110,117 @@ struct acpi_battery { u8 alarm_present; }; +#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); + inline int acpi_battery_present(struct acpi_battery *battery) { return battery->device->status.battery_present; } +static int acpi_battery_technology(struct acpi_battery *battery) +{ + if (!strcasecmp("NiCd", battery->type)) + return POWER_SUPPLY_TECHNOLOGY_NiCd; + if (!strcasecmp("NiMH", battery->type)) + return POWER_SUPPLY_TECHNOLOGY_NiMH; + if (!strcasecmp("LION", battery->type)) + return POWER_SUPPLY_TECHNOLOGY_LION; + if (!strcasecmp("LiP", battery->type)) + return POWER_SUPPLY_TECHNOLOGY_LIPO; + return POWER_SUPPLY_TECHNOLOGY_UNKNOWN; +} + +static int acpi_battery_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct acpi_battery *battery = to_acpi_battery(psy); + + if ((!acpi_battery_present(battery)) && + psp != POWER_SUPPLY_PROP_PRESENT) + return -ENODEV; + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + if (battery->state & 0x01) + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; + else if (battery->state & 0x02) + val->intval = POWER_SUPPLY_STATUS_CHARGING; + else if (battery->state == 0) + val->intval = POWER_SUPPLY_STATUS_FULL; + break; + case POWER_SUPPLY_PROP_PRESENT: + val->intval = acpi_battery_present(battery); + break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = acpi_battery_technology(battery); + break; + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: + val->intval = battery->design_voltage * 1000; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = battery->voltage_now * 1000; + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + val->intval = battery->current_now * 1000; + break; + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: + case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: + val->intval = battery->design_capacity * 1000; + break; + case POWER_SUPPLY_PROP_CHARGE_FULL: + case POWER_SUPPLY_PROP_ENERGY_FULL: + val->intval = battery->full_charge_capacity * 1000; + break; + case POWER_SUPPLY_PROP_CHARGE_NOW: + case POWER_SUPPLY_PROP_ENERGY_NOW: + val->intval = battery->capacity_now * 1000; + break; + case POWER_SUPPLY_PROP_MODEL_NAME: + val->strval = battery->model_number; + break; + case POWER_SUPPLY_PROP_MANUFACTURER: + val->strval = battery->oem_info; + break; + default: + return -EINVAL; + } + return 0; +} + +static enum power_supply_property charge_battery_props[] = { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, + POWER_SUPPLY_PROP_CHARGE_FULL, + POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_MODEL_NAME, + POWER_SUPPLY_PROP_MANUFACTURER, +}; + +static enum power_supply_property energy_battery_props[] = { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, + POWER_SUPPLY_PROP_ENERGY_FULL, + POWER_SUPPLY_PROP_ENERGY_NOW, + POWER_SUPPLY_PROP_MODEL_NAME, + POWER_SUPPLY_PROP_MANUFACTURER, +}; + +#ifdef CONFIG_ACPI_PROCFS inline char *acpi_battery_units(struct acpi_battery *battery) { return (battery->power_unit)?"mA":"mW"; } +#endif /* -------------------------------------------------------------------------- Battery Management @@ -120,15 +232,15 @@ struct acpi_offsets { static struct acpi_offsets state_offsets[] = { {offsetof(struct acpi_battery, state), 0}, - {offsetof(struct acpi_battery, present_rate), 0}, - {offsetof(struct acpi_battery, remaining_capacity), 0}, - {offsetof(struct acpi_battery, present_voltage), 0}, + {offsetof(struct acpi_battery, current_now), 0}, + {offsetof(struct acpi_battery, capacity_now), 0}, + {offsetof(struct acpi_battery, voltage_now), 0}, }; static struct acpi_offsets info_offsets[] = { {offsetof(struct acpi_battery, power_unit), 0}, {offsetof(struct acpi_battery, design_capacity), 0}, - {offsetof(struct acpi_battery, last_full_capacity), 0}, + {offsetof(struct acpi_battery, full_charge_capacity), 0}, {offsetof(struct acpi_battery, technology), 0}, {offsetof(struct acpi_battery, design_voltage), 0}, {offsetof(struct acpi_battery, design_capacity_warning), 0}, @@ -285,6 +397,15 @@ static int acpi_battery_update(struct acpi_battery *battery) result = acpi_battery_get_info(battery); if (result) return result; + if (battery->power_unit) { + battery->bat.properties = charge_battery_props; + battery->bat.num_properties = + ARRAY_SIZE(charge_battery_props); + } else { + battery->bat.properties = energy_battery_props; + battery->bat.num_properties = + ARRAY_SIZE(energy_battery_props); + } acpi_battery_init_alarm(battery); } return acpi_battery_get_state(battery); @@ -294,6 +415,7 @@ static int acpi_battery_update(struct acpi_battery *battery) FS Interface (/proc) -------------------------------------------------------------------------- */ +#ifdef CONFIG_ACPI_PROCFS static struct proc_dir_entry *acpi_battery_dir; static int acpi_battery_print_info(struct seq_file *seq, int result) @@ -314,11 +436,11 @@ static int acpi_battery_print_info(struct seq_file *seq, int result) battery->design_capacity, acpi_battery_units(battery)); - if (battery->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + if (battery->full_charge_capacity == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "last full capacity: unknown\n"); else seq_printf(seq, "last full capacity: %d %sh\n", - battery->last_full_capacity, + battery->full_charge_capacity, acpi_battery_units(battery)); seq_printf(seq, "battery technology: %srechargeable\n", @@ -375,22 +497,22 @@ static int acpi_battery_print_state(struct seq_file *seq, int result) else seq_printf(seq, "charging state: charged\n"); - if (battery->present_rate == ACPI_BATTERY_VALUE_UNKNOWN) + if (battery->current_now == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "present rate: unknown\n"); else seq_printf(seq, "present rate: %d %s\n", - battery->present_rate, acpi_battery_units(battery)); + battery->current_now, acpi_battery_units(battery)); - if (battery->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN) + if (battery->capacity_now == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "remaining capacity: unknown\n"); else seq_printf(seq, "remaining capacity: %d %sh\n", - battery->remaining_capacity, acpi_battery_units(battery)); - if (battery->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN) + battery->capacity_now, acpi_battery_units(battery)); + if (battery->voltage_now == ACPI_BATTERY_VALUE_UNKNOWN) seq_printf(seq, "present voltage: unknown\n"); else seq_printf(seq, "present voltage: %d mV\n", - battery->present_voltage); + battery->voltage_now); end: if (result) seq_printf(seq, "ERROR: Unable to read battery state\n"); @@ -564,6 +686,7 @@ static void acpi_battery_remove_fs(struct acpi_device *device) acpi_device_dir(device) = NULL; } +#endif /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -581,6 +704,7 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) acpi_bus_generate_netlink_event(device->pnp.device_class, device->dev.bus_id, event, acpi_battery_present(battery)); + kobject_uevent(&battery->bat.dev->kobj, KOBJ_CHANGE); } static int acpi_battery_add(struct acpi_device *device) @@ -599,9 +723,15 @@ static int acpi_battery_add(struct acpi_device *device) acpi_driver_data(device) = battery; mutex_init(&battery->lock); acpi_battery_update(battery); +#ifdef CONFIG_ACPI_PROCFS result = acpi_battery_add_fs(device); if (result) goto end; +#endif + battery->bat.name = acpi_device_bid(device); + battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; + battery->bat.get_property = acpi_battery_get_property; + result = power_supply_register(&battery->device->dev, &battery->bat); status = acpi_install_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_battery_notify, battery); @@ -615,7 +745,9 @@ static int acpi_battery_add(struct acpi_device *device) device->status.battery_present ? "present" : "absent"); end: if (result) { +#ifdef CONFIG_ACPI_PROCFS acpi_battery_remove_fs(device); +#endif kfree(battery); } return result; @@ -632,7 +764,11 @@ static int acpi_battery_remove(struct acpi_device *device, int type) status = acpi_remove_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_battery_notify); +#ifdef CONFIG_ACPI_PROCFS acpi_battery_remove_fs(device); +#endif + if (battery->bat.dev) + power_supply_unregister(&battery->bat); mutex_destroy(&battery->lock); kfree(battery); return 0; @@ -664,11 +800,15 @@ static int __init acpi_battery_init(void) { if (acpi_disabled) return -ENODEV; +#ifdef CONFIG_ACPI_PROCFS acpi_battery_dir = acpi_lock_battery_dir(); if (!acpi_battery_dir) return -ENODEV; +#endif if (acpi_bus_register_driver(&acpi_battery_driver) < 0) { +#ifdef CONFIG_ACPI_PROCFS acpi_unlock_battery_dir(acpi_battery_dir); +#endif return -ENODEV; } return 0; @@ -677,7 +817,9 @@ static int __init acpi_battery_init(void) static void __exit acpi_battery_exit(void) { acpi_bus_unregister_driver(&acpi_battery_driver); +#ifdef CONFIG_ACPI_PROCFS acpi_unlock_battery_dir(acpi_battery_dir); +#endif } module_init(acpi_battery_init); -- cgit v1.1 From 3e58ea0d31659b22ba5753f7abf3d7db346eab81 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 26 Sep 2007 19:43:11 +0400 Subject: ACPI: Battery: add sysfs alarm Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/battery.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 057a5eb..681e26b 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -687,6 +687,34 @@ static void acpi_battery_remove_fs(struct acpi_device *device) } #endif + +static ssize_t acpi_battery_alarm_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); + return sprintf(buf, "%d\n", battery->alarm * 1000); +} + +static ssize_t acpi_battery_alarm_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long x; + struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); + if (sscanf(buf, "%ld\n", &x) == 1) + battery->alarm = x/1000; + if (acpi_battery_present(battery)) + acpi_battery_set_alarm(battery); + return count; +} + +static struct device_attribute alarm_attr = { + .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE}, + .show = acpi_battery_alarm_show, + .store = acpi_battery_alarm_store, +}; + /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -732,6 +760,7 @@ static int acpi_battery_add(struct acpi_device *device) battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; battery->bat.get_property = acpi_battery_get_property; result = power_supply_register(&battery->device->dev, &battery->bat); + result = device_create_file(battery->bat.dev, &alarm_attr); status = acpi_install_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_battery_notify, battery); @@ -767,8 +796,10 @@ static int acpi_battery_remove(struct acpi_device *device, int type) #ifdef CONFIG_ACPI_PROCFS acpi_battery_remove_fs(device); #endif - if (battery->bat.dev) + if (battery->bat.dev) { + device_remove_file(battery->bat.dev, &alarm_attr); power_supply_unregister(&battery->bat); + } mutex_destroy(&battery->lock); kfree(battery); return 0; -- cgit v1.1 From 8db85d4c9a0cc131242c80ef8456362d66561dc2 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 26 Sep 2007 19:43:16 +0400 Subject: ACPI: Add acpi_bus_generate_event4() function acpi_bus_generate_event() takes two strings out of passed device object. SBS needs to supply these strings directly. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/bus.c | 23 +++++++++++++++-------- drivers/acpi/sbs.c | 46 ++++++++++++++-------------------------------- 2 files changed, 29 insertions(+), 40 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 9ba778a..a54234d 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -284,15 +284,11 @@ DECLARE_WAIT_QUEUE_HEAD(acpi_bus_event_queue); extern int event_is_open; -int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) +int acpi_bus_generate_proc_event4(const char *device_class, const char *bus_id, u8 type, int data) { - struct acpi_bus_event *event = NULL; + struct acpi_bus_event *event; unsigned long flags = 0; - - if (!device) - return -EINVAL; - /* drop event on the floor if no one's listening */ if (!event_is_open) return 0; @@ -301,8 +297,8 @@ int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) if (!event) return -ENOMEM; - strcpy(event->device_class, device->pnp.device_class); - strcpy(event->bus_id, device->pnp.bus_id); + strcpy(event->device_class, device_class); + strcpy(event->bus_id, bus_id); event->type = type; event->data = data; @@ -313,6 +309,17 @@ int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) wake_up_interruptible(&acpi_bus_event_queue); return 0; + +} + +EXPORT_SYMBOL_GPL(acpi_bus_generate_proc_event4); + +int acpi_bus_generate_proc_event(struct acpi_device *device, u8 type, int data) +{ + if (!device) + return -EINVAL; + return acpi_bus_generate_proc_event4(device->pnp.device_class, + device->pnp.bus_id, type, data); } EXPORT_SYMBOL(acpi_bus_generate_proc_event); diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index a578986..33ba4bf 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -427,28 +427,6 @@ static int acpi_check_update_proc(struct acpi_sbs *sbs) return 0; } -static int acpi_sbs_generate_event(struct acpi_device *device, - int event, int state, char *bid, char *class) -{ - char bid_saved[5]; - char class_saved[20]; - int result = 0; - - strcpy(bid_saved, acpi_device_bid(device)); - strcpy(class_saved, acpi_device_class(device)); - - strcpy(acpi_device_bid(device), bid); - strcpy(acpi_device_class(device), class); - - result = acpi_bus_generate_proc_event(device, event, state); - - strcpy(acpi_device_bid(device), bid_saved); - strcpy(acpi_device_class(device), class_saved); - - acpi_bus_generate_netlink_event(class, bid, event, state); - return result; -} - static int acpi_battery_get_present(struct acpi_battery *battery) { s16 state; @@ -1452,15 +1430,17 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type) } if (do_ac_init) { - result = acpi_sbs_generate_event(sbs->device, - ACPI_SBS_AC_NOTIFY_STATUS, - new_ac_present, + result = acpi_bus_generate_proc_event4(ACPI_AC_CLASS, ACPI_AC_DIR_NAME, - ACPI_AC_CLASS); + ACPI_SBS_AC_NOTIFY_STATUS, + new_ac_present); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_generate_event() failed")); + "acpi_bus_generate_event4() failed")); } + acpi_bus_generate_netlink_event(ACPI_AC_CLASS, ACPI_AC_DIR_NAME, + ACPI_SBS_AC_NOTIFY_STATUS, + new_ac_present); } if (data_type == DATA_TYPE_COMMON) { @@ -1568,14 +1548,16 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type) old_remaining_capacity != battery->state.remaining_capacity) { sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); - result = acpi_sbs_generate_event(sbs->device, - ACPI_SBS_BATTERY_NOTIFY_STATUS, - new_battery_present, + result = acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS, dir_name, - ACPI_BATTERY_CLASS); + ACPI_SBS_BATTERY_NOTIFY_STATUS, + new_battery_present); + acpi_bus_generate_netlink_event(ACPI_BATTERY_CLASS, dir_name, + ACPI_SBS_BATTERY_NOTIFY_STATUS, + new_battery_present); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_generate_event() " + "acpi_bus_generate_proc_event4() " "failed")); } } -- cgit v1.1 From 30c08574da0ead1a47797ce028218ce5b2de61c7 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 26 Sep 2007 19:43:22 +0400 Subject: ACPI: EC: Add new query handler to list head. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/ec.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 3f7935a..e9a0405 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -425,7 +425,7 @@ int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, handler->func = func; handler->data = data; mutex_lock(&ec->lock); - list_add_tail(&handler->node, &ec->list); + list_add(&handler->node, &ec->list); mutex_unlock(&ec->lock); return 0; } @@ -440,7 +440,6 @@ void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit) if (query_bit == handler->query_bit) { list_del(&handler->node); kfree(handler); - break; } } mutex_unlock(&ec->lock); -- cgit v1.1 From 91087dfa51a29b3c190e99339c4c32eb13646c51 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 26 Sep 2007 19:43:28 +0400 Subject: ACPI: SBS: Split host controller (ACPI0001) from SBS driver (ACPI0002) Replace poll-based host controller driver with the notify-based one. Split it out of sbs.c. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/Makefile | 1 + drivers/acpi/sbs.c | 374 ++++++++++---------------------------------------- drivers/acpi/sbshc.c | 309 +++++++++++++++++++++++++++++++++++++++++ drivers/acpi/sbshc.h | 27 ++++ 4 files changed, 412 insertions(+), 299 deletions(-) create mode 100644 drivers/acpi/sbshc.c create mode 100644 drivers/acpi/sbshc.h (limited to 'drivers/acpi') diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index d4336f1..54e3ab0 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -60,3 +60,4 @@ obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o obj-y += cm_sbs.o obj-$(CONFIG_ACPI_SBS) += sbs.o +obj-$(CONFIG_ACPI_SBS) += sbshc.o diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 33ba4bf..7bb8c62 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -34,6 +34,8 @@ #include #include +#include "sbshc.h" + #define ACPI_SBS_COMPONENT 0x00080000 #define ACPI_SBS_CLASS "sbs" #define ACPI_AC_CLASS "ac_adapter" @@ -59,28 +61,6 @@ MODULE_AUTHOR("Rich Townsend"); MODULE_DESCRIPTION("Smart Battery System ACPI interface driver"); MODULE_LICENSE("GPL"); -#define xmsleep(t) msleep(t) - -#define ACPI_EC_SMB_PRTCL 0x00 /* protocol, PEC */ - -#define ACPI_EC_SMB_STS 0x01 /* status */ -#define ACPI_EC_SMB_ADDR 0x02 /* address */ -#define ACPI_EC_SMB_CMD 0x03 /* command */ -#define ACPI_EC_SMB_DATA 0x04 /* 32 data registers */ -#define ACPI_EC_SMB_BCNT 0x24 /* number of data bytes */ - -#define ACPI_EC_SMB_STS_DONE 0x80 -#define ACPI_EC_SMB_STS_STATUS 0x1f - -#define ACPI_EC_SMB_PRTCL_WRITE 0x00 -#define ACPI_EC_SMB_PRTCL_READ 0x01 -#define ACPI_EC_SMB_PRTCL_WORD_DATA 0x08 -#define ACPI_EC_SMB_PRTCL_BLOCK_DATA 0x0a - -#define ACPI_EC_SMB_TRANSACTION_SLEEP 1 -#define ACPI_EC_SMB_ACCESS_SLEEP1 1 -#define ACPI_EC_SMB_ACCESS_SLEEP2 10 - #define DEF_CAPACITY_UNIT 3 #define MAH_CAPACITY_UNIT 1 #define MWH_CAPACITY_UNIT 2 @@ -103,12 +83,6 @@ extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); #define MAX_SBS_BAT 4 #define ACPI_SBS_BLOCK_MAX 32 -#define ACPI_SBS_SMBUS_READ 1 -#define ACPI_SBS_SMBUS_WRITE 2 - -#define ACPI_SBS_WORD_DATA 1 -#define ACPI_SBS_BLOCK_DATA 2 - #define UPDATE_DELAY 10 /* 0 - every time, > 0 - by update_time */ @@ -124,8 +98,7 @@ static int acpi_sbs_remove(struct acpi_device *device, int type); static int acpi_sbs_resume(struct acpi_device *device); static const struct acpi_device_id sbs_device_ids[] = { - {"ACPI0001", 0}, - {"ACPI0005", 0}, + {"ACPI0002", 0}, {"", 0}, }; MODULE_DEVICE_TABLE(acpi, sbs_device_ids); @@ -182,8 +155,8 @@ struct acpi_battery { }; struct acpi_sbs { - int base; struct acpi_device *device; + struct acpi_smb_hc *hc; struct mutex mutex; int sbsm_present; int sbsm_batteries_supported; @@ -199,190 +172,6 @@ struct acpi_sbs { static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type); static void acpi_sbs_update_time(void *data); -union sbs_rw_data { - u16 word; - u8 block[ACPI_SBS_BLOCK_MAX + 2]; -}; - -static int acpi_ec_sbs_access(struct acpi_sbs *sbs, u16 addr, - char read_write, u8 command, int size, - union sbs_rw_data *data); - -/* -------------------------------------------------------------------------- - SMBus Communication - -------------------------------------------------------------------------- */ - -static int acpi_ec_sbs_read(struct acpi_sbs *sbs, u8 address, u8 * data) -{ - u8 val; - int err; - - err = ec_read(sbs->base + address, &val); - if (!err) { - *data = val; - } - xmsleep(ACPI_EC_SMB_TRANSACTION_SLEEP); - return (err); -} - -static int acpi_ec_sbs_write(struct acpi_sbs *sbs, u8 address, u8 data) -{ - int err; - - err = ec_write(sbs->base + address, data); - return (err); -} - -static int -acpi_ec_sbs_access(struct acpi_sbs *sbs, u16 addr, - char read_write, u8 command, int size, - union sbs_rw_data *data) -{ - unsigned char protocol, len = 0, temp[2] = { 0, 0 }; - int i; - - if (read_write == ACPI_SBS_SMBUS_READ) { - protocol = ACPI_EC_SMB_PRTCL_READ; - } else { - protocol = ACPI_EC_SMB_PRTCL_WRITE; - } - - switch (size) { - - case ACPI_SBS_WORD_DATA: - acpi_ec_sbs_write(sbs, ACPI_EC_SMB_CMD, command); - if (read_write == ACPI_SBS_SMBUS_WRITE) { - acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA, data->word); - acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA + 1, - data->word >> 8); - } - protocol |= ACPI_EC_SMB_PRTCL_WORD_DATA; - break; - case ACPI_SBS_BLOCK_DATA: - acpi_ec_sbs_write(sbs, ACPI_EC_SMB_CMD, command); - if (read_write == ACPI_SBS_SMBUS_WRITE) { - len = min_t(u8, data->block[0], 32); - acpi_ec_sbs_write(sbs, ACPI_EC_SMB_BCNT, len); - for (i = 0; i < len; i++) - acpi_ec_sbs_write(sbs, ACPI_EC_SMB_DATA + i, - data->block[i + 1]); - } - protocol |= ACPI_EC_SMB_PRTCL_BLOCK_DATA; - break; - default: - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "unsupported transaction %d", size)); - return (-1); - } - - acpi_ec_sbs_write(sbs, ACPI_EC_SMB_ADDR, addr << 1); - acpi_ec_sbs_write(sbs, ACPI_EC_SMB_PRTCL, protocol); - - acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp); - - if (~temp[0] & ACPI_EC_SMB_STS_DONE) { - xmsleep(ACPI_EC_SMB_ACCESS_SLEEP1); - acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp); - } - if (~temp[0] & ACPI_EC_SMB_STS_DONE) { - xmsleep(ACPI_EC_SMB_ACCESS_SLEEP2); - acpi_ec_sbs_read(sbs, ACPI_EC_SMB_STS, temp); - } - if ((~temp[0] & ACPI_EC_SMB_STS_DONE) - || (temp[0] & ACPI_EC_SMB_STS_STATUS)) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "transaction %d error", size)); - return (-1); - } - - if (read_write == ACPI_SBS_SMBUS_WRITE) { - return (0); - } - - switch (size) { - - case ACPI_SBS_WORD_DATA: - acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA, temp); - acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA + 1, temp + 1); - data->word = (temp[1] << 8) | temp[0]; - break; - - case ACPI_SBS_BLOCK_DATA: - len = 0; - acpi_ec_sbs_read(sbs, ACPI_EC_SMB_BCNT, &len); - len = min_t(u8, len, 32); - for (i = 0; i < len; i++) - acpi_ec_sbs_read(sbs, ACPI_EC_SMB_DATA + i, - data->block + i + 1); - data->block[0] = len; - break; - default: - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "unsupported transaction %d", size)); - return (-1); - } - - return (0); -} - -static int -acpi_sbs_read_word(struct acpi_sbs *sbs, int addr, int func, u16 * word) -{ - union sbs_rw_data data; - int result = 0; - - result = acpi_ec_sbs_access(sbs, addr, - ACPI_SBS_SMBUS_READ, func, - ACPI_SBS_WORD_DATA, &data); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_ec_sbs_access() failed")); - } else { - *word = data.word; - } - - return result; -} - -static int -acpi_sbs_read_str(struct acpi_sbs *sbs, int addr, int func, char *str) -{ - union sbs_rw_data data; - int result = 0; - - result = acpi_ec_sbs_access(sbs, addr, - ACPI_SBS_SMBUS_READ, func, - ACPI_SBS_BLOCK_DATA, &data); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_ec_sbs_access() failed")); - } else { - strncpy(str, (const char *)data.block + 1, data.block[0]); - str[data.block[0]] = 0; - } - - return result; -} - -static int -acpi_sbs_write_word(struct acpi_sbs *sbs, int addr, int func, int word) -{ - union sbs_rw_data data; - int result = 0; - - data.word = word; - - result = acpi_ec_sbs_access(sbs, addr, - ACPI_SBS_SMBUS_WRITE, func, - ACPI_SBS_WORD_DATA, &data); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_ec_sbs_access() failed")); - } - - return result; -} - static int sbs_zombie(struct acpi_sbs *sbs) { return (sbs->zombie); @@ -433,11 +222,11 @@ static int acpi_battery_get_present(struct acpi_battery *battery) int result = 0; int is_present = 0; - result = acpi_sbs_read_word(battery->sbs, - ACPI_SBSM_SMBUS_ADDR, 0x01, &state); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, + ACPI_SBSM_SMBUS_ADDR, 0x01, (u8 *)&state); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); } if (!result) { is_present = (state & 0x000f) & (1 << battery->id); @@ -461,19 +250,19 @@ static int acpi_battery_select(struct acpi_battery *battery) * it causes charging to halt on SBSELs */ result = - acpi_sbs_read_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x01, &state); + acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SBSM_SMBUS_ADDR, 0x01, (u8 *)&state); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); goto end; } foo = (state & 0x0fff) | (1 << (battery->id + 12)); result = - acpi_sbs_write_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x01, foo); + acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBSM_SMBUS_ADDR, 0x01, (u8 *)&foo, 2); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_write_word() failed")); + "acpi_smbus_write() failed")); goto end; } } @@ -487,11 +276,11 @@ static int acpi_sbsm_get_info(struct acpi_sbs *sbs) int result = 0; s16 battery_system_info; - result = acpi_sbs_read_word(sbs, ACPI_SBSM_SMBUS_ADDR, 0x04, - &battery_system_info); + result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBSM_SMBUS_ADDR, 0x04, + (u8 *)&battery_system_info); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); goto end; } sbs->sbsm_present = 1; @@ -504,50 +293,49 @@ static int acpi_sbsm_get_info(struct acpi_sbs *sbs) static int acpi_battery_get_info(struct acpi_battery *battery) { - struct acpi_sbs *sbs = battery->sbs; int result = 0; s16 battery_mode; s16 specification_info; - result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x03, - &battery_mode); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x03, + (u8 *)&battery_mode); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); goto end; } battery->info.capacity_mode = (battery_mode & 0x8000) >> 15; - result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x10, - &battery->info.full_charge_capacity); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x10, + (u8 *)&battery->info.full_charge_capacity); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); goto end; } - result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x18, - &battery->info.design_capacity); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x18, + (u8 *)&battery->info.design_capacity); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); goto end; } - result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x19, - &battery->info.design_voltage); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x19, + (u8 *)&battery->info.design_voltage); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); goto end; } - result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x1a, - &specification_info); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x1a, + (u8 *)&specification_info); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); goto end; } @@ -579,32 +367,32 @@ static int acpi_battery_get_info(struct acpi_battery *battery) battery->info.ipscale = 1; } - result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x1c, - &battery->info.serial_number); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x1c, + (u8 *)&battery->info.serial_number); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); goto end; } - result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x20, - battery->info.manufacturer_name); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_BLOCK, ACPI_SB_SMBUS_ADDR, 0x20, + (u8 *)battery->info.manufacturer_name); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_sbs_read_str() failed")); goto end; } - result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x21, - battery->info.device_name); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_BLOCK, ACPI_SB_SMBUS_ADDR, 0x21, + (u8 *)battery->info.device_name); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_sbs_read_str() failed")); goto end; } - result = acpi_sbs_read_str(sbs, ACPI_SB_SMBUS_ADDR, 0x22, - battery->info.device_chemistry); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_BLOCK, ACPI_SB_SMBUS_ADDR, 0x22, + (u8 *)battery->info.device_chemistry); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_sbs_read_str() failed")); @@ -617,38 +405,37 @@ static int acpi_battery_get_info(struct acpi_battery *battery) static int acpi_battery_get_state(struct acpi_battery *battery) { - struct acpi_sbs *sbs = battery->sbs; int result = 0; - result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x09, - &battery->state.voltage); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x09, + (u8 *)&battery->state.voltage); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); goto end; } - result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0a, - &battery->state.amperage); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x0a, + (u8 *)&battery->state.amperage); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); goto end; } - result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0f, - &battery->state.remaining_capacity); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x0f, + (u8 *)&battery->state.remaining_capacity); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); goto end; } - result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x16, - &battery->state.battery_state); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x16, + (u8 *)&battery->state.battery_state); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); goto end; } @@ -658,14 +445,13 @@ static int acpi_battery_get_state(struct acpi_battery *battery) static int acpi_battery_get_alarm(struct acpi_battery *battery) { - struct acpi_sbs *sbs = battery->sbs; int result = 0; - result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01, - &battery->alarm.remaining_capacity); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x01, + (u8 *)&battery->alarm.remaining_capacity); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); goto end; } @@ -677,7 +463,6 @@ static int acpi_battery_get_alarm(struct acpi_battery *battery) static int acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm) { - struct acpi_sbs *sbs = battery->sbs; int result = 0; s16 battery_mode; int foo; @@ -693,29 +478,30 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery, if (alarm > 0) { result = - acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x03, - &battery_mode); + acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x03, + (u8 *)&battery_mode); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); goto end; } + battery_mode &= 0xbfff; result = - acpi_sbs_write_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01, - battery_mode & 0xbfff); + acpi_smbus_write(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x01, + (u8 *)&battery_mode, 2); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_write_word() failed")); + "acpi_smbus_write() failed")); goto end; } } foo = alarm / (battery->info.capacity_mode ? 10 : 1); - result = acpi_sbs_write_word(sbs, ACPI_SB_SMBUS_ADDR, 0x01, foo); + result = acpi_smbus_write(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x01, (u8 *)&foo, 2); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_write_word() failed")); + "acpi_smbus_write() failed")); goto end; } @@ -726,7 +512,6 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery, static int acpi_battery_set_mode(struct acpi_battery *battery) { - struct acpi_sbs *sbs = battery->sbs; int result = 0; s16 battery_mode; @@ -734,11 +519,11 @@ static int acpi_battery_set_mode(struct acpi_battery *battery) goto end; } - result = acpi_sbs_read_word(sbs, - ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, + ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); goto end; } @@ -747,19 +532,19 @@ static int acpi_battery_set_mode(struct acpi_battery *battery) } else { battery_mode |= 0x8000; } - result = acpi_sbs_write_word(sbs, - ACPI_SB_SMBUS_ADDR, 0x03, battery_mode); + result = acpi_smbus_write(battery->sbs->hc, SMBUS_READ_WORD, + ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode, 2); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_write_word() failed")); + "acpi_smbus_write() failed")); goto end; } - result = acpi_sbs_read_word(sbs, - ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, + ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); goto end; } @@ -815,12 +600,12 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs) int result = 0; s16 charger_status; - result = acpi_sbs_read_word(sbs, ACPI_SBC_SMBUS_ADDR, 0x13, - &charger_status); + result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBC_SMBUS_ADDR, 0x13, + (u8 *)&charger_status); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_word() failed")); + "acpi_smbus_read() failed")); goto end; } @@ -1614,15 +1399,6 @@ static int acpi_sbs_add(struct acpi_device *device) struct acpi_sbs *sbs = NULL; int result = 0, remove_result = 0; int id; - acpi_status status = AE_OK; - unsigned long val; - - status = - acpi_evaluate_integer(device->handle, "_EC", NULL, &val); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Error obtaining _EC")); - return -EIO; - } sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); if (!sbs) { @@ -1635,8 +1411,8 @@ static int acpi_sbs_add(struct acpi_device *device) sbs_mutex_lock(sbs); - sbs->base = 0xff & (val >> 8); sbs->device = device; + sbs->hc = acpi_driver_data(device->parent); strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_SBS_CLASS); diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c new file mode 100644 index 0000000..046d7c3 --- /dev/null +++ b/drivers/acpi/sbshc.c @@ -0,0 +1,309 @@ +/* + * SMBus driver for ACPI Embedded Controller (v0.1) + * + * Copyright (c) 2007 Alexey Starikovskiy + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 2. + */ + +#include +#include +#include +#include +#include +#include +#include "sbshc.h" + +#define ACPI_SMB_HC_CLASS "smbus_host_controller" +#define ACPI_SMB_HC_DEVICE_NAME "ACPI SMBus HC" + +struct acpi_smb_hc { + struct acpi_ec *ec; + struct mutex lock; + wait_queue_head_t wait; + u8 offset; + u8 query_bit; + smbus_alarm_callback callback; + void *context; +}; + +static int acpi_smbus_hc_add(struct acpi_device *device); +static int acpi_smbus_hc_remove(struct acpi_device *device, int type); + +static const struct acpi_device_id sbs_device_ids[] = { + {"ACPI0001", 0}, + {"ACPI0005", 0}, + {"", 0}, +}; + +MODULE_DEVICE_TABLE(acpi, sbs_device_ids); + +static struct acpi_driver acpi_smb_hc_driver = { + .name = "smbus_hc", + .class = ACPI_SMB_HC_CLASS, + .ids = sbs_device_ids, + .ops = { + .add = acpi_smbus_hc_add, + .remove = acpi_smbus_hc_remove, + }, +}; + +union acpi_smb_status { + u8 raw; + struct { + u8 status:5; + u8 reserved:1; + u8 alarm:1; + u8 done:1; + } fields; +}; + +enum acpi_smb_status_codes { + SMBUS_OK = 0, + SMBUS_UNKNOWN_FAILURE = 0x07, + SMBUS_DEVICE_ADDRESS_NACK = 0x10, + SMBUS_DEVICE_ERROR = 0x11, + SMBUS_DEVICE_COMMAND_ACCESS_DENIED = 0x12, + SMBUS_UNKNOWN_ERROR = 0x13, + SMBUS_DEVICE_ACCESS_DENIED = 0x17, + SMBUS_TIMEOUT = 0x18, + SMBUS_HOST_UNSUPPORTED_PROTOCOL = 0x19, + SMBUS_BUSY = 0x1a, + SMBUS_PEC_ERROR = 0x1f, +}; + +enum acpi_smb_offset { + ACPI_SMB_PROTOCOL = 0, /* protocol, PEC */ + ACPI_SMB_STATUS = 1, /* status */ + ACPI_SMB_ADDRESS = 2, /* address */ + ACPI_SMB_COMMAND = 3, /* command */ + ACPI_SMB_DATA = 4, /* 32 data registers */ + ACPI_SMB_BLOCK_COUNT = 0x24, /* number of data bytes */ + ACPI_SMB_ALARM_ADDRESS = 0x25, /* alarm address */ + ACPI_SMB_ALARM_DATA = 0x26, /* 2 bytes alarm data */ +}; + +static inline int smb_hc_read(struct acpi_smb_hc *hc, u8 address, u8 *data) +{ + return ec_read(hc->offset + address, data); +} + +static inline int smb_hc_write(struct acpi_smb_hc *hc, u8 address, u8 data) +{ + return ec_write(hc->offset + address, data); +} + +static inline int smb_check_done(struct acpi_smb_hc *hc) +{ + union acpi_smb_status status = {.raw = 0}; + smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw); + return status.fields.done && (status.fields.status == SMBUS_OK); +} + +static int wait_transaction_complete(struct acpi_smb_hc *hc, int timeout) +{ + if (wait_event_timeout(hc->wait, smb_check_done(hc), + msecs_to_jiffies(timeout))) + return 0; + else + return -ETIME; +} + +int acpi_smbus_transaction(struct acpi_smb_hc *hc, u8 protocol, u8 address, + u8 command, u8 *data, u8 length) +{ + int ret = -EFAULT, i; + u8 temp, sz = 0; + + mutex_lock(&hc->lock); + if (smb_hc_read(hc, ACPI_SMB_PROTOCOL, &temp)) + goto end; + if (temp) { + ret = -EBUSY; + goto end; + } + smb_hc_write(hc, ACPI_SMB_COMMAND, command); + smb_hc_write(hc, ACPI_SMB_COMMAND, command); + if (!(protocol & 0x01)) { + smb_hc_write(hc, ACPI_SMB_BLOCK_COUNT, length); + for (i = 0; i < length; ++i) + smb_hc_write(hc, ACPI_SMB_DATA + i, data[i]); + } + smb_hc_write(hc, ACPI_SMB_ADDRESS, address << 1); + smb_hc_write(hc, ACPI_SMB_PROTOCOL, protocol); + /* + * Wait for completion. Save the status code, data size, + * and data into the return package (if required by the protocol). + */ + ret = wait_transaction_complete(hc, 1000); + if (ret || !(protocol & 0x01)) + goto end; + switch (protocol) { + case SMBUS_RECEIVE_BYTE: + case SMBUS_READ_BYTE: + sz = 1; + break; + case SMBUS_READ_WORD: + sz = 2; + break; + case SMBUS_READ_BLOCK: + if (smb_hc_read(hc, ACPI_SMB_BLOCK_COUNT, &sz)) { + ret = -EFAULT; + goto end; + } + sz &= 0x1f; + break; + } + for (i = 0; i < sz; ++i) + smb_hc_read(hc, ACPI_SMB_DATA + i, &data[i]); + end: + mutex_unlock(&hc->lock); + return ret; +} + +int acpi_smbus_read(struct acpi_smb_hc *hc, u8 protocol, u8 address, + u8 command, u8 *data) +{ + return acpi_smbus_transaction(hc, protocol, address, command, data, 0); +} + +EXPORT_SYMBOL_GPL(acpi_smbus_read); + +int acpi_smbus_write(struct acpi_smb_hc *hc, u8 protocol, u8 address, + u8 command, u8 *data, u8 length) +{ + return acpi_smbus_transaction(hc, protocol, address, command, data, length); +} + +EXPORT_SYMBOL_GPL(acpi_smbus_write); + +int acpi_smbus_register_callback(struct acpi_smb_hc *hc, + smbus_alarm_callback callback, void *context) +{ + mutex_lock(&hc->lock); + hc->callback = callback; + hc->context = context; + mutex_unlock(&hc->lock); + return 0; +} + +EXPORT_SYMBOL_GPL(acpi_smbus_register_callback); + +int acpi_smbus_unregister_callback(struct acpi_smb_hc *hc) +{ + mutex_lock(&hc->lock); + hc->callback = NULL; + hc->context = NULL; + mutex_unlock(&hc->lock); + return 0; +} + +EXPORT_SYMBOL_GPL(acpi_smbus_unregister_callback); + +static void acpi_smbus_callback(void *context) +{ + struct acpi_smb_hc *hc = context; + + if (hc->callback) + hc->callback(hc->context); +} + +static int smbus_alarm(void *context) +{ + struct acpi_smb_hc *hc = context; + union acpi_smb_status status; + if (smb_hc_read(hc, ACPI_SMB_STATUS, &status.raw)) + return 0; + /* Check if it is only a completion notify */ + if (status.fields.done) + wake_up(&hc->wait); + if (!status.fields.alarm) + return 0; + mutex_lock(&hc->lock); + smb_hc_write(hc, ACPI_SMB_STATUS, status.raw); + if (hc->callback) + acpi_os_execute(OSL_GPE_HANDLER, acpi_smbus_callback, hc); + mutex_unlock(&hc->lock); + return 0; +} + +typedef int (*acpi_ec_query_func) (void *data); + +extern int acpi_ec_add_query_handler(struct acpi_ec *ec, u8 query_bit, + acpi_handle handle, acpi_ec_query_func func, + void *data); + +static int acpi_smbus_hc_add(struct acpi_device *device) +{ + int status; + unsigned long val; + struct acpi_smb_hc *hc; + + if (!device) + return -EINVAL; + + status = acpi_evaluate_integer(device->handle, "_EC", NULL, &val); + if (ACPI_FAILURE(status)) { + printk(KERN_ERR PREFIX "error obtaining _EC.\n"); + return -EIO; + } + + strcpy(acpi_device_name(device), ACPI_SMB_HC_DEVICE_NAME); + strcpy(acpi_device_class(device), ACPI_SMB_HC_CLASS); + + hc = kzalloc(sizeof(struct acpi_smb_hc), GFP_KERNEL); + if (!hc) + return -ENOMEM; + mutex_init(&hc->lock); + init_waitqueue_head(&hc->wait); + + hc->ec = acpi_driver_data(device->parent); + hc->offset = (val >> 8) & 0xff; + hc->query_bit = val & 0xff; + acpi_driver_data(device) = hc; + + acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc); + printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n", + hc->ec, hc->offset, hc->query_bit); + + return 0; +} + +extern void acpi_ec_remove_query_handler(struct acpi_ec *ec, u8 query_bit); + +static int acpi_smbus_hc_remove(struct acpi_device *device, int type) +{ + struct acpi_smb_hc *hc; + + if (!device) + return -EINVAL; + + hc = acpi_driver_data(device); + acpi_ec_remove_query_handler(hc->ec, hc->query_bit); + kfree(hc); + return 0; +} + +static int __init acpi_smb_hc_init(void) +{ + int result; + + result = acpi_bus_register_driver(&acpi_smb_hc_driver); + if (result < 0) + return -ENODEV; + return 0; +} + +static void __exit acpi_smb_hc_exit(void) +{ + acpi_bus_unregister_driver(&acpi_smb_hc_driver); +} + +module_init(acpi_smb_hc_init); +module_exit(acpi_smb_hc_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Alexey Starikovskiy"); +MODULE_DESCRIPTION("ACPI SMBus HC driver"); diff --git a/drivers/acpi/sbshc.h b/drivers/acpi/sbshc.h new file mode 100644 index 0000000..3bda349 --- /dev/null +++ b/drivers/acpi/sbshc.h @@ -0,0 +1,27 @@ +struct acpi_smb_hc; +enum acpi_smb_protocol { + SMBUS_WRITE_QUICK = 2, + SMBUS_READ_QUICK = 3, + SMBUS_SEND_BYTE = 4, + SMBUS_RECEIVE_BYTE = 5, + SMBUS_WRITE_BYTE = 6, + SMBUS_READ_BYTE = 7, + SMBUS_WRITE_WORD = 8, + SMBUS_READ_WORD = 9, + SMBUS_WRITE_BLOCK = 0xa, + SMBUS_READ_BLOCK = 0xb, + SMBUS_PROCESS_CALL = 0xc, + SMBUS_BLOCK_PROCESS_CALL = 0xd, +}; + +static const u8 SMBUS_PEC = 0x80; + +typedef void (*smbus_alarm_callback)(void *context); + +extern int acpi_smbus_read(struct acpi_smb_hc *hc, u8 protocol, u8 address, + u8 command, u8 * data); +extern int acpi_smbus_write(struct acpi_smb_hc *hc, u8 protocol, u8 slave_address, + u8 command, u8 * data, u8 length); +extern int acpi_smbus_register_callback(struct acpi_smb_hc *hc, + smbus_alarm_callback callback, void *context); +extern int acpi_smbus_unregister_callback(struct acpi_smb_hc *hc); -- cgit v1.1 From 89862e3be1ba387c738fc2c3a5875cfd7e51c5a8 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 26 Sep 2007 19:43:35 +0400 Subject: ACPI: SBS: Simplify data structures in SBS Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/sbs.c | 282 +++++++++++++++++++++++++---------------------------- 1 file changed, 135 insertions(+), 147 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 7bb8c62..f35fe63 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -88,10 +88,10 @@ extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); /* 0 - every time, > 0 - by update_time */ static unsigned int update_time = 120; -static unsigned int capacity_mode = CAPACITY_UNIT; +static unsigned int mode = CAPACITY_UNIT; module_param(update_time, uint, 0644); -module_param(capacity_mode, uint, 0444); +module_param(mode, uint, 0444); static int acpi_sbs_add(struct acpi_device *device); static int acpi_sbs_remove(struct acpi_device *device, int type); @@ -114,59 +114,43 @@ static struct acpi_driver acpi_sbs_driver = { }, }; -struct acpi_ac { - int ac_present; -}; - -struct acpi_battery_info { - int capacity_mode; - s16 full_charge_capacity; - s16 design_capacity; - s16 design_voltage; - int vscale; - int ipscale; - s16 serial_number; - char manufacturer_name[ACPI_SBS_BLOCK_MAX + 3]; - char device_name[ACPI_SBS_BLOCK_MAX + 3]; - char device_chemistry[ACPI_SBS_BLOCK_MAX + 3]; -}; - -struct acpi_battery_state { - s16 voltage; - s16 amperage; - s16 remaining_capacity; - s16 battery_state; -}; - -struct acpi_battery_alarm { - s16 remaining_capacity; -}; - struct acpi_battery { - int alive; - int id; - int init_state; - int battery_present; struct acpi_sbs *sbs; - struct acpi_battery_info info; - struct acpi_battery_state state; - struct acpi_battery_alarm alarm; - struct proc_dir_entry *battery_entry; + struct proc_dir_entry *proc_entry; + int vscale; + int ipscale; + char manufacturer_name[ACPI_SBS_BLOCK_MAX]; + char device_name[ACPI_SBS_BLOCK_MAX]; + char device_chemistry[ACPI_SBS_BLOCK_MAX]; + u16 full_charge_capacity; + u16 design_capacity; + u16 design_voltage; + u16 serial_number; + u16 voltage_now; + s16 current_now; + u16 capacity_now; + u16 state; + u16 alarm_capacity; + u16 mode; + u8 id; + u8 alive:1; + u8 init_state:1; + u8 present:1; }; struct acpi_sbs { struct acpi_device *device; struct acpi_smb_hc *hc; struct mutex mutex; - int sbsm_present; - int sbsm_batteries_supported; struct proc_dir_entry *ac_entry; - struct acpi_ac ac; struct acpi_battery battery[MAX_SBS_BAT]; int zombie; struct timer_list update_timer; int run_cnt; int update_proc_flg; + u8 batteries_supported; + u8 manager_present:1; + u8 charger_present:1; }; static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type); @@ -231,7 +215,7 @@ static int acpi_battery_get_present(struct acpi_battery *battery) if (!result) { is_present = (state & 0x000f) & (1 << battery->id); } - battery->battery_present = is_present; + battery->present = is_present; return result; } @@ -243,14 +227,14 @@ static int acpi_battery_select(struct acpi_battery *battery) s16 state; int foo; - if (sbs->sbsm_present) { + if (sbs->manager_present) { /* Take special care not to knobble other nibbles of * state (aka selector_state), since * it causes charging to halt on SBSELs */ - result = - acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SBSM_SMBUS_ADDR, 0x01, (u8 *)&state); + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, + ACPI_SBSM_SMBUS_ADDR, 0x01, (u8 *)&state); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_smbus_read() failed")); @@ -258,8 +242,8 @@ static int acpi_battery_select(struct acpi_battery *battery) } foo = (state & 0x0fff) | (1 << (battery->id + 12)); - result = - acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, ACPI_SBSM_SMBUS_ADDR, 0x01, (u8 *)&foo, 2); + result = acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, + ACPI_SBSM_SMBUS_ADDR, 0x01, (u8 *)&foo, 2); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_smbus_write() failed")); @@ -283,8 +267,7 @@ static int acpi_sbsm_get_info(struct acpi_sbs *sbs) "acpi_smbus_read() failed")); goto end; } - sbs->sbsm_present = 1; - sbs->sbsm_batteries_supported = battery_system_info & 0x000f; + sbs->manager_present = 1; end: @@ -304,10 +287,10 @@ static int acpi_battery_get_info(struct acpi_battery *battery) "acpi_smbus_read() failed")); goto end; } - battery->info.capacity_mode = (battery_mode & 0x8000) >> 15; + battery->mode = (battery_mode & 0x8000) >> 15; result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x10, - (u8 *)&battery->info.full_charge_capacity); + (u8 *)&battery->full_charge_capacity); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_smbus_read() failed")); @@ -315,7 +298,7 @@ static int acpi_battery_get_info(struct acpi_battery *battery) } result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x18, - (u8 *)&battery->info.design_capacity); + (u8 *)&battery->design_capacity); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, @@ -324,7 +307,7 @@ static int acpi_battery_get_info(struct acpi_battery *battery) } result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x19, - (u8 *)&battery->info.design_voltage); + (u8 *)&battery->design_voltage); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_smbus_read() failed")); @@ -341,34 +324,34 @@ static int acpi_battery_get_info(struct acpi_battery *battery) switch ((specification_info & 0x0f00) >> 8) { case 1: - battery->info.vscale = 10; + battery->vscale = 10; break; case 2: - battery->info.vscale = 100; + battery->vscale = 100; break; case 3: - battery->info.vscale = 1000; + battery->vscale = 1000; break; default: - battery->info.vscale = 1; + battery->vscale = 1; } switch ((specification_info & 0xf000) >> 12) { case 1: - battery->info.ipscale = 10; + battery->ipscale = 10; break; case 2: - battery->info.ipscale = 100; + battery->ipscale = 100; break; case 3: - battery->info.ipscale = 1000; + battery->ipscale = 1000; break; default: - battery->info.ipscale = 1; + battery->ipscale = 1; } result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x1c, - (u8 *)&battery->info.serial_number); + (u8 *)&battery->serial_number); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_smbus_read() failed")); @@ -376,7 +359,7 @@ static int acpi_battery_get_info(struct acpi_battery *battery) } result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_BLOCK, ACPI_SB_SMBUS_ADDR, 0x20, - (u8 *)battery->info.manufacturer_name); + (u8 *)battery->manufacturer_name); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_sbs_read_str() failed")); @@ -384,7 +367,7 @@ static int acpi_battery_get_info(struct acpi_battery *battery) } result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_BLOCK, ACPI_SB_SMBUS_ADDR, 0x21, - (u8 *)battery->info.device_name); + (u8 *)battery->device_name); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_sbs_read_str() failed")); @@ -392,7 +375,7 @@ static int acpi_battery_get_info(struct acpi_battery *battery) } result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_BLOCK, ACPI_SB_SMBUS_ADDR, 0x22, - (u8 *)battery->info.device_chemistry); + (u8 *)battery->device_chemistry); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_sbs_read_str() failed")); @@ -408,7 +391,7 @@ static int acpi_battery_get_state(struct acpi_battery *battery) int result = 0; result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x09, - (u8 *)&battery->state.voltage); + (u8 *)&battery->voltage_now); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_smbus_read() failed")); @@ -416,7 +399,7 @@ static int acpi_battery_get_state(struct acpi_battery *battery) } result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x0a, - (u8 *)&battery->state.amperage); + (u8 *)&battery->current_now); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_smbus_read() failed")); @@ -424,7 +407,7 @@ static int acpi_battery_get_state(struct acpi_battery *battery) } result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x0f, - (u8 *)&battery->state.remaining_capacity); + (u8 *)&battery->capacity_now); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_smbus_read() failed")); @@ -432,7 +415,7 @@ static int acpi_battery_get_state(struct acpi_battery *battery) } result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x16, - (u8 *)&battery->state.battery_state); + (u8 *)&battery->state); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_smbus_read() failed")); @@ -448,7 +431,7 @@ static int acpi_battery_get_alarm(struct acpi_battery *battery) int result = 0; result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x01, - (u8 *)&battery->alarm.remaining_capacity); + (u8 *)&battery->alarm_capacity); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_smbus_read() failed")); @@ -497,8 +480,9 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery, } } - foo = alarm / (battery->info.capacity_mode ? 10 : 1); - result = acpi_smbus_write(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x01, (u8 *)&foo, 2); + foo = alarm / (battery->mode ? 10 : 1); + result = acpi_smbus_write(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x01, + (u8 *)&foo, 2); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_smbus_write() failed")); @@ -515,25 +499,25 @@ static int acpi_battery_set_mode(struct acpi_battery *battery) int result = 0; s16 battery_mode; - if (capacity_mode == DEF_CAPACITY_UNIT) { + if (mode == DEF_CAPACITY_UNIT) { goto end; } result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, - ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode); + ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_smbus_read() failed")); goto end; } - if (capacity_mode == MAH_CAPACITY_UNIT) { + if (mode == MAH_CAPACITY_UNIT) { battery_mode &= 0x7fff; } else { battery_mode |= 0x8000; } result = acpi_smbus_write(battery->sbs->hc, SMBUS_READ_WORD, - ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode, 2); + ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode, 2); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_smbus_write() failed")); @@ -541,7 +525,7 @@ static int acpi_battery_set_mode(struct acpi_battery *battery) } result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, - ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode); + ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_smbus_read() failed")); @@ -601,7 +585,7 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs) s16 charger_status; result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBC_SMBUS_ADDR, 0x13, - (u8 *)&charger_status); + (u8 *)&charger_status); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, @@ -609,7 +593,7 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs) goto end; } - sbs->ac.ac_present = (charger_status & 0x8000) >> 15; + sbs->charger_present = (charger_status & 0x8000) >> 15; end: @@ -726,30 +710,30 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset) } } - if (battery->battery_present) { + if (battery->present) { seq_printf(seq, "present: yes\n"); } else { seq_printf(seq, "present: no\n"); goto end; } - if (battery->info.capacity_mode) { - cscale = battery->info.vscale * battery->info.ipscale; + if (battery->mode) { + cscale = battery->vscale * battery->ipscale; } else { - cscale = battery->info.ipscale; + cscale = battery->ipscale; } seq_printf(seq, "design capacity: %i%s\n", - battery->info.design_capacity * cscale, - battery->info.capacity_mode ? "0 mWh" : " mAh"); + battery->design_capacity * cscale, + battery->mode ? "0 mWh" : " mAh"); seq_printf(seq, "last full capacity: %i%s\n", - battery->info.full_charge_capacity * cscale, - battery->info.capacity_mode ? "0 mWh" : " mAh"); + battery->full_charge_capacity * cscale, + battery->mode ? "0 mWh" : " mAh"); seq_printf(seq, "battery technology: rechargeable\n"); seq_printf(seq, "design voltage: %i mV\n", - battery->info.design_voltage * battery->info.vscale); + battery->design_voltage * battery->vscale); seq_printf(seq, "design capacity warning: unknown\n"); seq_printf(seq, "design capacity low: unknown\n"); @@ -757,16 +741,16 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset) seq_printf(seq, "capacity granularity 2: unknown\n"); seq_printf(seq, "model number: %s\n", - battery->info.device_name); + battery->device_name); seq_printf(seq, "serial number: %i\n", - battery->info.serial_number); + battery->serial_number); seq_printf(seq, "battery type: %s\n", - battery->info.device_chemistry); + battery->device_chemistry); seq_printf(seq, "OEM info: %s\n", - battery->info.manufacturer_name); + battery->manufacturer_name); end: @@ -804,49 +788,49 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) } } - if (battery->battery_present) { + if (battery->present) { seq_printf(seq, "present: yes\n"); } else { seq_printf(seq, "present: no\n"); goto end; } - if (battery->info.capacity_mode) { - cscale = battery->info.vscale * battery->info.ipscale; + if (battery->mode) { + cscale = battery->vscale * battery->ipscale; } else { - cscale = battery->info.ipscale; + cscale = battery->ipscale; } - if (battery->state.battery_state & 0x0010) { + if (battery->state & 0x0010) { seq_printf(seq, "capacity state: critical\n"); } else { seq_printf(seq, "capacity state: ok\n"); } - foo = (s16) battery->state.amperage * battery->info.ipscale; - if (battery->info.capacity_mode) { - foo = foo * battery->info.design_voltage / 1000; + foo = (s16) battery->current_now * battery->ipscale; + if (battery->mode) { + foo = foo * battery->design_voltage / 1000; } - if (battery->state.amperage < 0) { + if (battery->current_now < 0) { seq_printf(seq, "charging state: discharging\n"); seq_printf(seq, "present rate: %d %s\n", - -foo, battery->info.capacity_mode ? "mW" : "mA"); - } else if (battery->state.amperage > 0) { + -foo, battery->mode ? "mW" : "mA"); + } else if (battery->current_now > 0) { seq_printf(seq, "charging state: charging\n"); seq_printf(seq, "present rate: %d %s\n", - foo, battery->info.capacity_mode ? "mW" : "mA"); + foo, battery->mode ? "mW" : "mA"); } else { seq_printf(seq, "charging state: charged\n"); seq_printf(seq, "present rate: 0 %s\n", - battery->info.capacity_mode ? "mW" : "mA"); + battery->mode ? "mW" : "mA"); } seq_printf(seq, "remaining capacity: %i%s\n", - battery->state.remaining_capacity * cscale, - battery->info.capacity_mode ? "0 mWh" : " mAh"); + battery->capacity_now * cscale, + battery->mode ? "0 mWh" : " mAh"); seq_printf(seq, "present voltage: %i mV\n", - battery->state.voltage * battery->info.vscale); + battery->voltage_now * battery->vscale); end: @@ -883,22 +867,22 @@ static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) } } - if (!battery->battery_present) { + if (!battery->present) { seq_printf(seq, "present: no\n"); goto end; } - if (battery->info.capacity_mode) { - cscale = battery->info.vscale * battery->info.ipscale; + if (battery->mode) { + cscale = battery->vscale * battery->ipscale; } else { - cscale = battery->info.ipscale; + cscale = battery->ipscale; } seq_printf(seq, "alarm: "); - if (battery->alarm.remaining_capacity) { + if (battery->alarm_capacity) { seq_printf(seq, "%i%s\n", - battery->alarm.remaining_capacity * cscale, - battery->info.capacity_mode ? "0 mWh" : " mAh"); + battery->alarm_capacity * cscale, + battery->mode ? "0 mWh" : " mAh"); } else { seq_printf(seq, "disabled\n"); } @@ -928,7 +912,7 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer, if (result) goto end; - if (!battery->battery_present) { + if (!battery->present) { result = -ENODEV; goto end; } @@ -945,7 +929,7 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer, alarm_string[count] = 0; - old_alarm = battery->alarm.remaining_capacity; + old_alarm = battery->alarm_capacity; new_alarm = simple_strtoul(alarm_string, NULL, 0); result = acpi_battery_set_alarm(battery, new_alarm); @@ -1025,7 +1009,7 @@ static int acpi_ac_read_state(struct seq_file *seq, void *offset) } seq_printf(seq, "state: %s\n", - sbs->ac.ac_present ? "on-line" : "off-line"); + sbs->charger_present ? "on-line" : "off-line"); sbs_mutex_unlock(sbs); @@ -1080,7 +1064,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) goto end; } - is_present = battery->battery_present; + is_present = battery->present; if (is_present) { result = acpi_battery_init(battery); @@ -1094,7 +1078,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); - result = acpi_sbs_generic_add_fs(&battery->battery_entry, + result = acpi_sbs_generic_add_fs(&battery->proc_entry, acpi_battery_dir, dir_name, &acpi_battery_info_fops, @@ -1109,7 +1093,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), dir_name, - sbs->battery->battery_present ? "present" : "absent"); + sbs->battery->present ? "present" : "absent"); end: return result; @@ -1118,8 +1102,8 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) static void acpi_battery_remove(struct acpi_sbs *sbs, int id) { - if (sbs->battery[id].battery_entry) { - acpi_sbs_generic_remove_fs(&(sbs->battery[id].battery_entry), + if (sbs->battery[id].proc_entry) { + acpi_sbs_generic_remove_fs(&(sbs->battery[id].proc_entry), acpi_battery_dir); } } @@ -1147,7 +1131,7 @@ static int acpi_ac_add(struct acpi_sbs *sbs) printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), - ACPI_AC_DIR_NAME, sbs->ac.ac_present ? "on-line" : "off-line"); + ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line"); end: @@ -1172,9 +1156,9 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type) struct acpi_battery *battery; int result = 0, cnt; int old_ac_present = -1; - int old_battery_present = -1; + int old_present = -1; int new_ac_present = -1; - int new_battery_present = -1; + int new_present = -1; int id_min = 0, id_max = MAX_SBS_BAT - 1; char dir_name[32]; int do_battery_init = 0, do_ac_init = 0; @@ -1199,7 +1183,11 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type) sbs->run_cnt++; - old_ac_present = sbs->ac.ac_present; + if (!update_battery) { + goto end; + } + + old_ac_present = sbs->charger_present; result = acpi_ac_get_present(sbs); if (result) { @@ -1207,7 +1195,7 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type) "acpi_ac_get_present() failed")); } - new_ac_present = sbs->ac.ac_present; + new_ac_present = sbs->charger_present; do_ac_init = (old_ac_present != new_ac_present); if (sbs->run_cnt == 1 && data_type == DATA_TYPE_COMMON) { @@ -1244,9 +1232,9 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type) continue; } - old_remaining_capacity = battery->state.remaining_capacity; + old_remaining_capacity = battery->capacity_now; - old_battery_present = battery->battery_present; + old_present = battery->present; result = acpi_battery_select(battery); if (result) { @@ -1260,11 +1248,11 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type) "acpi_battery_get_present() failed")); } - new_battery_present = battery->battery_present; + new_present = battery->present; - do_battery_init = ((old_battery_present != new_battery_present) - && new_battery_present); - if (!new_battery_present) + do_battery_init = ((old_present != new_present) + && new_present); + if (!new_present) goto event; if (do_ac_init || do_battery_init) { result = acpi_battery_init(battery); @@ -1280,7 +1268,7 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type) if ((data_type == DATA_TYPE_COMMON || data_type == DATA_TYPE_INFO) - && new_battery_present) { + && new_present) { result = acpi_battery_get_info(battery); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, @@ -1296,7 +1284,7 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type) if ((data_type == DATA_TYPE_COMMON || data_type == DATA_TYPE_STATE) - && new_battery_present) { + && new_present) { result = acpi_battery_get_state(battery); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, @@ -1312,7 +1300,7 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type) if ((data_type == DATA_TYPE_COMMON || data_type == DATA_TYPE_ALARM) - && new_battery_present) { + && new_present) { result = acpi_battery_get_alarm(battery); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, @@ -1329,17 +1317,17 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type) event: - if (old_battery_present != new_battery_present || do_ac_init || + if (old_present != new_present || do_ac_init || old_remaining_capacity != - battery->state.remaining_capacity) { + battery->capacity_now) { sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); result = acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS, dir_name, ACPI_SBS_BATTERY_NOTIFY_STATUS, - new_battery_present); + new_present); acpi_bus_generate_netlink_event(ACPI_BATTERY_CLASS, dir_name, ACPI_SBS_BATTERY_NOTIFY_STATUS, - new_battery_present); + new_present); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_bus_generate_proc_event4() " @@ -1426,7 +1414,7 @@ static int acpi_sbs_add(struct acpi_device *device) acpi_sbsm_get_info(sbs); - if (!sbs->sbsm_present) { + if (!sbs->manager_present) { result = acpi_battery_add(sbs, 0); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, @@ -1435,7 +1423,7 @@ static int acpi_sbs_add(struct acpi_device *device) } } else { for (id = 0; id < MAX_SBS_BAT; id++) { - if ((sbs->sbsm_batteries_supported & (1 << id))) { + if ((sbs->batteries_supported & (1 << id))) { result = acpi_battery_add(sbs, id); if (result) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, @@ -1535,11 +1523,11 @@ static int __init acpi_sbs_init(void) if (acpi_disabled) return -ENODEV; - if (capacity_mode != DEF_CAPACITY_UNIT - && capacity_mode != MAH_CAPACITY_UNIT - && capacity_mode != MWH_CAPACITY_UNIT) { + if (mode != DEF_CAPACITY_UNIT + && mode != MAH_CAPACITY_UNIT + && mode != MWH_CAPACITY_UNIT) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "invalid capacity_mode = %d", capacity_mode)); + "invalid mode = %d", mode)); return -EINVAL; } -- cgit v1.1 From db1c291af7ad748777371f25b9ff92e3e5aba38e Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 26 Sep 2007 19:43:41 +0400 Subject: ACPI: SBS: Make SBS reads table-driven. Re-factor SBS functions to use tables and cycles for repeated operations. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/sbs.c | 1292 +++++++++++----------------------------------------- 1 file changed, 275 insertions(+), 1017 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index f35fe63..3351dea 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -1,6 +1,8 @@ /* - * acpi_sbs.c - ACPI Smart Battery System Driver ($Revision: 1.16 $) + * sbs.c - ACPI Smart Battery System Driver ($Revision: 2.0 $) * + * Copyright (c) 2007 Alexey Starikovskiy + * Copyright (c) 2005-2007 Vladimir Lebedev * Copyright (c) 2005 Rich Townsend * * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -46,53 +48,34 @@ #define ACPI_SBS_FILE_ALARM "alarm" #define ACPI_BATTERY_DIR_NAME "BAT%i" #define ACPI_AC_DIR_NAME "AC0" -#define ACPI_SBC_SMBUS_ADDR 0x9 -#define ACPI_SBSM_SMBUS_ADDR 0xa -#define ACPI_SB_SMBUS_ADDR 0xb -#define ACPI_SBS_AC_NOTIFY_STATUS 0x80 -#define ACPI_SBS_BATTERY_NOTIFY_STATUS 0x80 -#define ACPI_SBS_BATTERY_NOTIFY_INFO 0x81 -#define _COMPONENT ACPI_SBS_COMPONENT +enum acpi_sbs_device_addr { + ACPI_SBS_CHARGER = 0x9, + ACPI_SBS_MANAGER = 0xa, + ACPI_SBS_BATTERY = 0xb, +}; + +#define ACPI_SBS_NOTIFY_STATUS 0x80 +#define ACPI_SBS_NOTIFY_INFO 0x81 ACPI_MODULE_NAME("sbs"); -MODULE_AUTHOR("Rich Townsend"); +MODULE_AUTHOR("Alexey Starikovskiy "); MODULE_DESCRIPTION("Smart Battery System ACPI interface driver"); MODULE_LICENSE("GPL"); -#define DEF_CAPACITY_UNIT 3 -#define MAH_CAPACITY_UNIT 1 -#define MWH_CAPACITY_UNIT 2 -#define CAPACITY_UNIT DEF_CAPACITY_UNIT - -#define REQUEST_UPDATE_MODE 1 -#define QUEUE_UPDATE_MODE 2 - -#define DATA_TYPE_COMMON 0 -#define DATA_TYPE_INFO 1 -#define DATA_TYPE_STATE 2 -#define DATA_TYPE_ALARM 3 -#define DATA_TYPE_AC_STATE 4 +static unsigned int cache_time = 1000; +module_param(cache_time, uint, 0644); +MODULE_PARM_DESC(cache_time, "cache time in milliseconds"); extern struct proc_dir_entry *acpi_lock_ac_dir(void); extern struct proc_dir_entry *acpi_lock_battery_dir(void); extern void acpi_unlock_ac_dir(struct proc_dir_entry *acpi_ac_dir); extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); -#define MAX_SBS_BAT 4 +#define MAX_SBS_BAT 4 #define ACPI_SBS_BLOCK_MAX 32 -#define UPDATE_DELAY 10 - -/* 0 - every time, > 0 - by update_time */ -static unsigned int update_time = 120; - -static unsigned int mode = CAPACITY_UNIT; - -module_param(update_time, uint, 0644); -module_param(mode, uint, 0444); - static int acpi_sbs_add(struct acpi_device *device); static int acpi_sbs_remove(struct acpi_device *device, int type); static int acpi_sbs_resume(struct acpi_device *device); @@ -117,486 +100,187 @@ static struct acpi_driver acpi_sbs_driver = { struct acpi_battery { struct acpi_sbs *sbs; struct proc_dir_entry *proc_entry; - int vscale; - int ipscale; + unsigned long update_time; + char name[8]; char manufacturer_name[ACPI_SBS_BLOCK_MAX]; char device_name[ACPI_SBS_BLOCK_MAX]; char device_chemistry[ACPI_SBS_BLOCK_MAX]; + u32 alarm_capacity; u16 full_charge_capacity; u16 design_capacity; u16 design_voltage; u16 serial_number; + u16 cycle_count; + u16 temp_now; u16 voltage_now; s16 current_now; + s16 current_avg; u16 capacity_now; + u16 state_of_charge; u16 state; - u16 alarm_capacity; u16 mode; + u16 spec; u8 id; - u8 alive:1; - u8 init_state:1; u8 present:1; }; struct acpi_sbs { struct acpi_device *device; struct acpi_smb_hc *hc; - struct mutex mutex; - struct proc_dir_entry *ac_entry; + struct mutex lock; + struct proc_dir_entry *charger_entry; struct acpi_battery battery[MAX_SBS_BAT]; - int zombie; - struct timer_list update_timer; - int run_cnt; - int update_proc_flg; - u8 batteries_supported; + u8 batteries_supported:4; u8 manager_present:1; u8 charger_present:1; }; -static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type); -static void acpi_sbs_update_time(void *data); - -static int sbs_zombie(struct acpi_sbs *sbs) +static inline int battery_scale(int log) { - return (sbs->zombie); + int scale = 1; + while (log--) + scale *= 10; + return scale; } -static int sbs_mutex_lock(struct acpi_sbs *sbs) +static inline int acpi_battery_vscale(struct acpi_battery *battery) { - if (sbs_zombie(sbs)) { - return -ENODEV; - } - mutex_lock(&sbs->mutex); - return 0; + return battery_scale((battery->spec & 0x0f00) >> 8); } -static void sbs_mutex_unlock(struct acpi_sbs *sbs) +static inline int acpi_battery_ipscale(struct acpi_battery *battery) { - mutex_unlock(&sbs->mutex); + return battery_scale((battery->spec & 0xf000) >> 12); } -/* -------------------------------------------------------------------------- - Smart Battery System Management - -------------------------------------------------------------------------- */ - -static int acpi_check_update_proc(struct acpi_sbs *sbs) +static inline int acpi_battery_mode(struct acpi_battery *battery) { - acpi_status status = AE_OK; - - if (update_time == 0) { - sbs->update_proc_flg = 0; - return 0; - } - if (sbs->update_proc_flg == 0) { - status = acpi_os_execute(OSL_GPE_HANDLER, - acpi_sbs_update_time, sbs); - if (status != AE_OK) { - ACPI_EXCEPTION((AE_INFO, status, - "acpi_os_execute() failed")); - return 1; - } - sbs->update_proc_flg = 1; - } - return 0; + return (battery->mode & 0x8000); } -static int acpi_battery_get_present(struct acpi_battery *battery) +static inline int acpi_battery_scale(struct acpi_battery *battery) { - s16 state; - int result = 0; - int is_present = 0; - - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, - ACPI_SBSM_SMBUS_ADDR, 0x01, (u8 *)&state); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - } - if (!result) { - is_present = (state & 0x000f) & (1 << battery->id); - } - battery->present = is_present; - - return result; + return (acpi_battery_mode(battery) ? 10 : 1) * + acpi_battery_ipscale(battery); } -static int acpi_battery_select(struct acpi_battery *battery) -{ - struct acpi_sbs *sbs = battery->sbs; - int result = 0; - s16 state; - int foo; - - if (sbs->manager_present) { - - /* Take special care not to knobble other nibbles of - * state (aka selector_state), since - * it causes charging to halt on SBSELs */ +/* -------------------------------------------------------------------------- + Smart Battery System Management + -------------------------------------------------------------------------- */ - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, - ACPI_SBSM_SMBUS_ADDR, 0x01, (u8 *)&state); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - goto end; - } +struct acpi_battery_reader { + u8 command; /* command for battery */ + u8 mode; /* word or block? */ + size_t offset; /* offset inside struct acpi_sbs_battery */ +}; - foo = (state & 0x0fff) | (1 << (battery->id + 12)); - result = acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, - ACPI_SBSM_SMBUS_ADDR, 0x01, (u8 *)&foo, 2); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_write() failed")); - goto end; - } - } +static struct acpi_battery_reader info_readers[] = { + {0x01, SMBUS_READ_WORD, offsetof(struct acpi_battery, alarm_capacity)}, + {0x03, SMBUS_READ_WORD, offsetof(struct acpi_battery, mode)}, + {0x10, SMBUS_READ_WORD, offsetof(struct acpi_battery, full_charge_capacity)}, + {0x17, SMBUS_READ_WORD, offsetof(struct acpi_battery, cycle_count)}, + {0x18, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_capacity)}, + {0x19, SMBUS_READ_WORD, offsetof(struct acpi_battery, design_voltage)}, + {0x1a, SMBUS_READ_WORD, offsetof(struct acpi_battery, spec)}, + {0x1c, SMBUS_READ_WORD, offsetof(struct acpi_battery, serial_number)}, + {0x20, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, manufacturer_name)}, + {0x21, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_name)}, + {0x22, SMBUS_READ_BLOCK, offsetof(struct acpi_battery, device_chemistry)}, +}; - end: - return result; -} +static struct acpi_battery_reader state_readers[] = { + {0x08, SMBUS_READ_WORD, offsetof(struct acpi_battery, temp_now)}, + {0x09, SMBUS_READ_WORD, offsetof(struct acpi_battery, voltage_now)}, + {0x0a, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_now)}, + {0x0b, SMBUS_READ_WORD, offsetof(struct acpi_battery, current_avg)}, + {0x0f, SMBUS_READ_WORD, offsetof(struct acpi_battery, capacity_now)}, + {0x0e, SMBUS_READ_WORD, offsetof(struct acpi_battery, state_of_charge)}, + {0x16, SMBUS_READ_WORD, offsetof(struct acpi_battery, state)}, +}; -static int acpi_sbsm_get_info(struct acpi_sbs *sbs) +static int acpi_manager_get_info(struct acpi_sbs *sbs) { int result = 0; - s16 battery_system_info; - - result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBSM_SMBUS_ADDR, 0x04, - (u8 *)&battery_system_info); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - goto end; - } - sbs->manager_present = 1; - - end: + u16 battery_system_info; + result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER, + 0x04, (u8 *) & battery_system_info); + if (!result) + sbs->batteries_supported = battery_system_info & 0x000f; return result; } static int acpi_battery_get_info(struct acpi_battery *battery) { - int result = 0; - s16 battery_mode; - s16 specification_info; - - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x03, - (u8 *)&battery_mode); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - goto end; - } - battery->mode = (battery_mode & 0x8000) >> 15; - - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x10, - (u8 *)&battery->full_charge_capacity); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - goto end; - } - - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x18, - (u8 *)&battery->design_capacity); + int i, result = 0; - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - goto end; - } - - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x19, - (u8 *)&battery->design_voltage); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - goto end; + for (i = 0; i < ARRAY_SIZE(info_readers); ++i) { + result = acpi_smbus_read(battery->sbs->hc, info_readers[i].mode, + ACPI_SBS_BATTERY, info_readers[i].command, + (u8 *) battery + info_readers[i].offset); + if (result) + break; } - - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x1a, - (u8 *)&specification_info); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - goto end; - } - - switch ((specification_info & 0x0f00) >> 8) { - case 1: - battery->vscale = 10; - break; - case 2: - battery->vscale = 100; - break; - case 3: - battery->vscale = 1000; - break; - default: - battery->vscale = 1; - } - - switch ((specification_info & 0xf000) >> 12) { - case 1: - battery->ipscale = 10; - break; - case 2: - battery->ipscale = 100; - break; - case 3: - battery->ipscale = 1000; - break; - default: - battery->ipscale = 1; - } - - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x1c, - (u8 *)&battery->serial_number); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - goto end; - } - - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_BLOCK, ACPI_SB_SMBUS_ADDR, 0x20, - (u8 *)battery->manufacturer_name); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_str() failed")); - goto end; - } - - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_BLOCK, ACPI_SB_SMBUS_ADDR, 0x21, - (u8 *)battery->device_name); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_str() failed")); - goto end; - } - - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_BLOCK, ACPI_SB_SMBUS_ADDR, 0x22, - (u8 *)battery->device_chemistry); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_read_str() failed")); - goto end; - } - - end: return result; } static int acpi_battery_get_state(struct acpi_battery *battery) { - int result = 0; - - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x09, - (u8 *)&battery->voltage_now); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - goto end; - } - - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x0a, - (u8 *)&battery->current_now); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - goto end; - } - - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x0f, - (u8 *)&battery->capacity_now); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - goto end; - } - - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x16, - (u8 *)&battery->state); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - goto end; - } - - end: - return result; -} - -static int acpi_battery_get_alarm(struct acpi_battery *battery) -{ - int result = 0; - - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x01, - (u8 *)&battery->alarm_capacity); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - goto end; - } - - end: - - return result; -} - -static int acpi_battery_set_alarm(struct acpi_battery *battery, - unsigned long alarm) -{ - int result = 0; - s16 battery_mode; - int foo; + int i, result = 0; - result = acpi_battery_select(battery); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_select() failed")); - goto end; - } - - /* If necessary, enable the alarm */ - - if (alarm > 0) { - result = - acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x03, - (u8 *)&battery_mode); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - goto end; - } - - battery_mode &= 0xbfff; - result = - acpi_smbus_write(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x01, - (u8 *)&battery_mode, 2); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_write() failed")); + if (time_before(jiffies, battery->update_time + + msecs_to_jiffies(cache_time))) + return 0; + for (i = 0; i < ARRAY_SIZE(state_readers); ++i) { + result = acpi_smbus_read(battery->sbs->hc, + state_readers[i].mode, + ACPI_SBS_BATTERY, + state_readers[i].command, + (u8 *)battery + + state_readers[i].offset); + if (result) goto end; - } } - - foo = alarm / (battery->mode ? 10 : 1); - result = acpi_smbus_write(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SB_SMBUS_ADDR, 0x01, - (u8 *)&foo, 2); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_write() failed")); - goto end; - } - end: - + battery->update_time = jiffies; return result; } -static int acpi_battery_set_mode(struct acpi_battery *battery) +static int acpi_battery_get_alarm(struct acpi_battery *battery) { - int result = 0; - s16 battery_mode; - - if (mode == DEF_CAPACITY_UNIT) { - goto end; - } - - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, - ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - goto end; - } - - if (mode == MAH_CAPACITY_UNIT) { - battery_mode &= 0x7fff; - } else { - battery_mode |= 0x8000; - } - result = acpi_smbus_write(battery->sbs->hc, SMBUS_READ_WORD, - ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode, 2); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_write() failed")); - goto end; - } - - result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, - ACPI_SB_SMBUS_ADDR, 0x03, (u8 *)&battery_mode); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - goto end; - } - - end: - return result; + return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, + ACPI_SBS_BATTERY, 0x01, + (u8 *) & battery->alarm_capacity); } -static int acpi_battery_init(struct acpi_battery *battery) +static int acpi_battery_set_alarm(struct acpi_battery *battery) { - int result = 0; - - result = acpi_battery_select(battery); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_select() failed")); - goto end; - } - - result = acpi_battery_set_mode(battery); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_set_mode() failed")); - goto end; - } - - result = acpi_battery_get_info(battery); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_get_info() failed")); - goto end; - } - - result = acpi_battery_get_state(battery); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_get_state() failed")); - goto end; - } + struct acpi_sbs *sbs = battery->sbs; + u16 value; + return 0; - result = acpi_battery_get_alarm(battery); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_get_alarm() failed")); - goto end; + if (sbs->manager_present) { + acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER, + 0x01, (u8 *)&value); + value &= 0x0fff; + value |= 1 << (battery->id + 12); + acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_MANAGER, + 0x01, (u8 *)&value, 2); } - - end: - return result; + value = battery->alarm_capacity / (acpi_battery_mode(battery) ? 10 : 1); + return acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, + 0x01, (u8 *)&value, 2); } static int acpi_ac_get_present(struct acpi_sbs *sbs) { - int result = 0; - s16 charger_status; - - result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBC_SMBUS_ADDR, 0x13, - (u8 *)&charger_status); - - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_smbus_read() failed")); - goto end; - } - - sbs->charger_present = (charger_status & 0x8000) >> 15; - - end: + int result; + u16 status; + result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_CHARGER, + 0x13, (u8 *) & status); + if (!result) + sbs->charger_present = (status >> 15) & 0x1; return result; } @@ -607,7 +291,7 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs) /* Generic Routines */ static int -acpi_sbs_generic_add_fs(struct proc_dir_entry **dir, +acpi_sbs_add_fs(struct proc_dir_entry **dir, struct proc_dir_entry *parent_dir, char *dir_name, struct file_operations *info_fops, @@ -669,7 +353,7 @@ acpi_sbs_generic_add_fs(struct proc_dir_entry **dir, } static void -acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir, +acpi_sbs_remove_fs(struct proc_dir_entry **dir, struct proc_dir_entry *parent_dir) { @@ -687,75 +371,47 @@ acpi_sbs_generic_remove_fs(struct proc_dir_entry **dir, static struct proc_dir_entry *acpi_battery_dir = NULL; +static inline char *acpi_battery_units(struct acpi_battery *battery) +{ + return acpi_battery_mode(battery) ? " mWh" : " mAh"; +} + + static int acpi_battery_read_info(struct seq_file *seq, void *offset) { struct acpi_battery *battery = seq->private; struct acpi_sbs *sbs = battery->sbs; - int cscale; int result = 0; - if (sbs_mutex_lock(sbs)) { - return -ENODEV; - } + mutex_lock(&sbs->lock); - result = acpi_check_update_proc(sbs); - if (result) + seq_printf(seq, "present: %s\n", + (battery->present) ? "yes" : "no"); + if (!battery->present) goto end; - if (update_time == 0) { - result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_INFO); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_update_run() failed")); - } - } - - if (battery->present) { - seq_printf(seq, "present: yes\n"); - } else { - seq_printf(seq, "present: no\n"); - goto end; - } - - if (battery->mode) { - cscale = battery->vscale * battery->ipscale; - } else { - cscale = battery->ipscale; - } seq_printf(seq, "design capacity: %i%s\n", - battery->design_capacity * cscale, - battery->mode ? "0 mWh" : " mAh"); - + battery->design_capacity * acpi_battery_scale(battery), + acpi_battery_units(battery)); seq_printf(seq, "last full capacity: %i%s\n", - battery->full_charge_capacity * cscale, - battery->mode ? "0 mWh" : " mAh"); - + battery->full_charge_capacity * acpi_battery_scale(battery), + acpi_battery_units(battery)); seq_printf(seq, "battery technology: rechargeable\n"); - seq_printf(seq, "design voltage: %i mV\n", - battery->design_voltage * battery->vscale); - + battery->design_voltage * acpi_battery_vscale(battery)); seq_printf(seq, "design capacity warning: unknown\n"); seq_printf(seq, "design capacity low: unknown\n"); seq_printf(seq, "capacity granularity 1: unknown\n"); seq_printf(seq, "capacity granularity 2: unknown\n"); - - seq_printf(seq, "model number: %s\n", - battery->device_name); - + seq_printf(seq, "model number: %s\n", battery->device_name); seq_printf(seq, "serial number: %i\n", battery->serial_number); - seq_printf(seq, "battery type: %s\n", battery->device_chemistry); - seq_printf(seq, "OEM info: %s\n", battery->manufacturer_name); - end: - - sbs_mutex_unlock(sbs); - + mutex_unlock(&sbs->lock); return result; } @@ -769,73 +425,29 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) struct acpi_battery *battery = seq->private; struct acpi_sbs *sbs = battery->sbs; int result = 0; - int cscale; - int foo; - - if (sbs_mutex_lock(sbs)) { - return -ENODEV; - } - - result = acpi_check_update_proc(sbs); - if (result) - goto end; - - if (update_time == 0) { - result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_STATE); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_update_run() failed")); - } - } - if (battery->present) { - seq_printf(seq, "present: yes\n"); - } else { - seq_printf(seq, "present: no\n"); + mutex_lock(&sbs->lock); + seq_printf(seq, "present: %s\n", + (battery->present) ? "yes" : "no"); + if (!battery->present) goto end; - } - - if (battery->mode) { - cscale = battery->vscale * battery->ipscale; - } else { - cscale = battery->ipscale; - } - - if (battery->state & 0x0010) { - seq_printf(seq, "capacity state: critical\n"); - } else { - seq_printf(seq, "capacity state: ok\n"); - } - - foo = (s16) battery->current_now * battery->ipscale; - if (battery->mode) { - foo = foo * battery->design_voltage / 1000; - } - if (battery->current_now < 0) { - seq_printf(seq, "charging state: discharging\n"); - seq_printf(seq, "present rate: %d %s\n", - -foo, battery->mode ? "mW" : "mA"); - } else if (battery->current_now > 0) { - seq_printf(seq, "charging state: charging\n"); - seq_printf(seq, "present rate: %d %s\n", - foo, battery->mode ? "mW" : "mA"); - } else { - seq_printf(seq, "charging state: charged\n"); - seq_printf(seq, "present rate: 0 %s\n", - battery->mode ? "mW" : "mA"); - } + acpi_battery_get_state(battery); + seq_printf(seq, "capacity state: %s\n", + (battery->state & 0x0010) ? "critical" : "ok"); + seq_printf(seq, "charging state: %s\n", + (battery->current_now < 0) ? "discharging" : + ((battery->current_now > 0) ? "charging" : "charged")); + seq_printf(seq, "present rate: %d mA\n", + abs(battery->current_now) * acpi_battery_ipscale(battery)); seq_printf(seq, "remaining capacity: %i%s\n", - battery->capacity_now * cscale, - battery->mode ? "0 mWh" : " mAh"); - + battery->capacity_now * acpi_battery_scale(battery), + acpi_battery_units(battery)); seq_printf(seq, "present voltage: %i mV\n", - battery->voltage_now * battery->vscale); + battery->voltage_now * acpi_battery_vscale(battery)); end: - - sbs_mutex_unlock(sbs); - + mutex_unlock(&sbs->lock); return result; } @@ -849,48 +461,25 @@ static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) struct acpi_battery *battery = seq->private; struct acpi_sbs *sbs = battery->sbs; int result = 0; - int cscale; - - if (sbs_mutex_lock(sbs)) { - return -ENODEV; - } - result = acpi_check_update_proc(sbs); - if (result) - goto end; - - if (update_time == 0) { - result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_ALARM); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_update_run() failed")); - } - } + mutex_lock(&sbs->lock); if (!battery->present) { seq_printf(seq, "present: no\n"); goto end; } - if (battery->mode) { - cscale = battery->vscale * battery->ipscale; - } else { - cscale = battery->ipscale; - } - + acpi_battery_get_alarm(battery); seq_printf(seq, "alarm: "); - if (battery->alarm_capacity) { + if (battery->alarm_capacity) seq_printf(seq, "%i%s\n", - battery->alarm_capacity * cscale, - battery->mode ? "0 mWh" : " mAh"); - } else { + battery->alarm_capacity * + acpi_battery_scale(battery), + acpi_battery_units(battery)); + else seq_printf(seq, "disabled\n"); - } - end: - - sbs_mutex_unlock(sbs); - + mutex_unlock(&sbs->lock); return result; } @@ -902,59 +491,28 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer, struct acpi_battery *battery = seq->private; struct acpi_sbs *sbs = battery->sbs; char alarm_string[12] = { '\0' }; - int result, old_alarm, new_alarm; - - if (sbs_mutex_lock(sbs)) { - return -ENODEV; - } - - result = acpi_check_update_proc(sbs); - if (result) - goto end; - + int result = 0; + mutex_lock(&sbs->lock); if (!battery->present) { result = -ENODEV; goto end; } - if (count > sizeof(alarm_string) - 1) { result = -EINVAL; goto end; } - if (copy_from_user(alarm_string, buffer, count)) { result = -EFAULT; goto end; } - alarm_string[count] = 0; - - old_alarm = battery->alarm_capacity; - new_alarm = simple_strtoul(alarm_string, NULL, 0); - - result = acpi_battery_set_alarm(battery, new_alarm); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_set_alarm() failed")); - acpi_battery_set_alarm(battery, old_alarm); - goto end; - } - result = acpi_battery_get_alarm(battery); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_get_alarm() failed")); - acpi_battery_set_alarm(battery, old_alarm); - goto end; - } - + battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0); + acpi_battery_set_alarm(battery); end: - sbs_mutex_unlock(sbs); - - if (result) { + mutex_unlock(&sbs->lock); + if (result) return result; - } else { - return count; - } + return count; } static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) @@ -993,26 +551,15 @@ static struct proc_dir_entry *acpi_ac_dir = NULL; static int acpi_ac_read_state(struct seq_file *seq, void *offset) { - struct acpi_sbs *sbs = seq->private; - int result; - if (sbs_mutex_lock(sbs)) { - return -ENODEV; - } + struct acpi_sbs *sbs = seq->private; - if (update_time == 0) { - result = acpi_sbs_update_run(sbs, -1, DATA_TYPE_AC_STATE); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_update_run() failed")); - } - } + mutex_lock(&sbs->lock); seq_printf(seq, "state: %s\n", sbs->charger_present ? "on-line" : "off-line"); - sbs_mutex_unlock(sbs); - + mutex_unlock(&sbs->lock); return 0; } @@ -1035,67 +582,54 @@ static struct file_operations acpi_ac_state_fops = { /* Smart Battery */ -static int acpi_battery_add(struct acpi_sbs *sbs, int id) +static int acpi_battery_read(struct acpi_battery *battery) { - int is_present; - int result; - char dir_name[32]; - struct acpi_battery *battery; + int result = 0, saved_present = battery->present; + u16 state; - battery = &sbs->battery[id]; + if (battery->sbs->manager_present) { + result = acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, + ACPI_SBS_MANAGER, 0x01, (u8 *)&state); + if (!result) + battery->present = state & (1 << battery->id); + state &= 0x0fff; + state |= 1 << (battery->id + 12); + acpi_smbus_write(battery->sbs->hc, SMBUS_WRITE_WORD, + ACPI_SBS_MANAGER, 0x01, (u8 *)&state, 2); + } else if (battery->id == 0) + battery->present = 1; + if (result || !battery->present) + return result; - battery->alive = 0; + if (saved_present != battery->present) { + battery->update_time = 0; + result = acpi_battery_get_info(battery); + if (result) + return result; + } + result = acpi_battery_get_state(battery); + return result; +} - battery->init_state = 0; +static int acpi_battery_add(struct acpi_sbs *sbs, int id) +{ + int result; + struct acpi_battery *battery = &sbs->battery[id]; battery->id = id; battery->sbs = sbs; + battery->update_time = 0; + result = acpi_battery_read(battery); + if (result) + return result; - result = acpi_battery_select(battery); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_select() failed")); - goto end; - } - - result = acpi_battery_get_present(battery); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_get_present() failed")); - goto end; - } - - is_present = battery->present; - - if (is_present) { - result = acpi_battery_init(battery); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_init() failed")); - goto end; - } - battery->init_state = 1; - } - - sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); - - result = acpi_sbs_generic_add_fs(&battery->proc_entry, - acpi_battery_dir, - dir_name, - &acpi_battery_info_fops, - &acpi_battery_state_fops, - &acpi_battery_alarm_fops, battery); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_generic_add_fs() failed")); - goto end; - } - battery->alive = 1; - + sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id); + acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir, + battery->name, &acpi_battery_info_fops, + &acpi_battery_state_fops, &acpi_battery_alarm_fops, + battery); printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", - ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), dir_name, - sbs->battery->present ? "present" : "absent"); - - end: + ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), + battery->name, sbs->battery->present ? "present" : "absent"); return result; } @@ -1103,354 +637,105 @@ static void acpi_battery_remove(struct acpi_sbs *sbs, int id) { if (sbs->battery[id].proc_entry) { - acpi_sbs_generic_remove_fs(&(sbs->battery[id].proc_entry), - acpi_battery_dir); + acpi_sbs_remove_fs(&(sbs->battery[id].proc_entry), + acpi_battery_dir); } } -static int acpi_ac_add(struct acpi_sbs *sbs) +static int acpi_charger_add(struct acpi_sbs *sbs) { int result; result = acpi_ac_get_present(sbs); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_ac_get_present() failed")); + if (result) goto end; - } - - result = acpi_sbs_generic_add_fs(&sbs->ac_entry, - acpi_ac_dir, - ACPI_AC_DIR_NAME, - NULL, &acpi_ac_state_fops, NULL, sbs); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_generic_add_fs() failed")); + result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir, + ACPI_AC_DIR_NAME, NULL, + &acpi_ac_state_fops, NULL, sbs); + if (result) goto end; - } - printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line"); - end: - return result; } -static void acpi_ac_remove(struct acpi_sbs *sbs) +static void acpi_charger_remove(struct acpi_sbs *sbs) { - if (sbs->ac_entry) { - acpi_sbs_generic_remove_fs(&sbs->ac_entry, acpi_ac_dir); - } -} - -static void acpi_sbs_update_time_run(unsigned long data) -{ - acpi_os_execute(OSL_GPE_HANDLER, acpi_sbs_update_time, (void *)data); + if (sbs->charger_entry) + acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir); } -static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type) +void acpi_sbs_callback(void *context) { - struct acpi_battery *battery; - int result = 0, cnt; - int old_ac_present = -1; - int old_present = -1; - int new_ac_present = -1; - int new_present = -1; - int id_min = 0, id_max = MAX_SBS_BAT - 1; - char dir_name[32]; - int do_battery_init = 0, do_ac_init = 0; - int old_remaining_capacity = 0; - int update_battery = 1; - int up_tm = update_time; - - if (sbs_zombie(sbs)) { - goto end; - } - - if (id >= 0) { - id_min = id_max = id; - } - - if (data_type == DATA_TYPE_COMMON && up_tm > 0) { - cnt = up_tm / (up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm); - if (sbs->run_cnt % cnt != 0) { - update_battery = 0; - } - } - - sbs->run_cnt++; - - if (!update_battery) { - goto end; - } - - old_ac_present = sbs->charger_present; - - result = acpi_ac_get_present(sbs); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_ac_get_present() failed")); - } - - new_ac_present = sbs->charger_present; - - do_ac_init = (old_ac_present != new_ac_present); - if (sbs->run_cnt == 1 && data_type == DATA_TYPE_COMMON) { - do_ac_init = 1; - } - - if (do_ac_init) { - result = acpi_bus_generate_proc_event4(ACPI_AC_CLASS, - ACPI_AC_DIR_NAME, - ACPI_SBS_AC_NOTIFY_STATUS, - new_ac_present); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_bus_generate_event4() failed")); - } - acpi_bus_generate_netlink_event(ACPI_AC_CLASS, ACPI_AC_DIR_NAME, - ACPI_SBS_AC_NOTIFY_STATUS, - new_ac_present); - } - - if (data_type == DATA_TYPE_COMMON) { - if (!do_ac_init && !update_battery) { - goto end; - } - } - - if (data_type == DATA_TYPE_AC_STATE && !do_ac_init) { - goto end; + int id; + struct acpi_sbs *sbs = context; + struct acpi_battery *bat; + u8 saved_charger_state = sbs->charger_present; + u8 saved_battery_state; + acpi_ac_get_present(sbs); + if (sbs->charger_present != saved_charger_state) { + acpi_bus_generate_proc_event4(ACPI_AC_CLASS, ACPI_AC_DIR_NAME, + ACPI_SBS_NOTIFY_STATUS, + sbs->charger_present); } - - for (id = id_min; id <= id_max; id++) { - battery = &sbs->battery[id]; - if (battery->alive == 0) { - continue; - } - - old_remaining_capacity = battery->capacity_now; - - old_present = battery->present; - - result = acpi_battery_select(battery); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_select() failed")); - } - - result = acpi_battery_get_present(battery); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_get_present() failed")); - } - - new_present = battery->present; - - do_battery_init = ((old_present != new_present) - && new_present); - if (!new_present) - goto event; - if (do_ac_init || do_battery_init) { - result = acpi_battery_init(battery); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_init() " - "failed")); - } - } - if (sbs_zombie(sbs)) { - goto end; - } - - if ((data_type == DATA_TYPE_COMMON - || data_type == DATA_TYPE_INFO) - && new_present) { - result = acpi_battery_get_info(battery); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_get_info() failed")); - } - } - if (data_type == DATA_TYPE_INFO) { - continue; - } - if (sbs_zombie(sbs)) { - goto end; - } - - if ((data_type == DATA_TYPE_COMMON - || data_type == DATA_TYPE_STATE) - && new_present) { - result = acpi_battery_get_state(battery); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_get_state() failed")); - } - } - if (data_type == DATA_TYPE_STATE) { - goto event; - } - if (sbs_zombie(sbs)) { - goto end; - } - - if ((data_type == DATA_TYPE_COMMON - || data_type == DATA_TYPE_ALARM) - && new_present) { - result = acpi_battery_get_alarm(battery); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_get_alarm() " - "failed")); - } - } - if (data_type == DATA_TYPE_ALARM) { - continue; - } - if (sbs_zombie(sbs)) { - goto end; - } - - event: - - if (old_present != new_present || do_ac_init || - old_remaining_capacity != - battery->capacity_now) { - sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); - result = acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS, - dir_name, - ACPI_SBS_BATTERY_NOTIFY_STATUS, - new_present); - acpi_bus_generate_netlink_event(ACPI_BATTERY_CLASS, dir_name, - ACPI_SBS_BATTERY_NOTIFY_STATUS, - new_present); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_bus_generate_proc_event4() " - "failed")); - } + if (sbs->manager_present) { + for (id = 0; id < MAX_SBS_BAT; ++id) { + if (!(sbs->batteries_supported & (1 << id))) + continue; + bat = &sbs->battery[id]; + saved_battery_state = bat->present; + acpi_battery_read(bat); + if (saved_battery_state == bat->present) + continue; + acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS, + bat->name, + ACPI_SBS_NOTIFY_STATUS, + bat->present); } } - - end: - - return result; } -static void acpi_sbs_update_time(void *data) -{ - struct acpi_sbs *sbs = data; - unsigned long delay = -1; - int result; - unsigned int up_tm = update_time; - - if (sbs_mutex_lock(sbs)) - return; - - result = acpi_sbs_update_run(sbs, -1, DATA_TYPE_COMMON); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_update_run() failed")); - } - - if (sbs_zombie(sbs)) { - goto end; - } - - if (!up_tm) { - if (timer_pending(&sbs->update_timer)) - del_timer(&sbs->update_timer); - } else { - delay = (up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm); - delay = jiffies + HZ * delay; - if (timer_pending(&sbs->update_timer)) { - mod_timer(&sbs->update_timer, delay); - } else { - sbs->update_timer.data = (unsigned long)data; - sbs->update_timer.function = acpi_sbs_update_time_run; - sbs->update_timer.expires = delay; - add_timer(&sbs->update_timer); - } - } - - end: - - sbs_mutex_unlock(sbs); -} +static int acpi_sbs_remove(struct acpi_device *device, int type); static int acpi_sbs_add(struct acpi_device *device) { - struct acpi_sbs *sbs = NULL; - int result = 0, remove_result = 0; + struct acpi_sbs *sbs; + int result = 0; int id; sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); if (!sbs) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, "kzalloc() failed")); result = -ENOMEM; goto end; } - mutex_init(&sbs->mutex); - - sbs_mutex_lock(sbs); + mutex_init(&sbs->lock); - sbs->device = device; sbs->hc = acpi_driver_data(device->parent); - + sbs->device = device; strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_SBS_CLASS); acpi_driver_data(device) = sbs; - result = acpi_ac_add(sbs); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_ac_add() failed")); - goto end; - } - - acpi_sbsm_get_info(sbs); - - if (!sbs->manager_present) { - result = acpi_battery_add(sbs, 0); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_add() failed")); - goto end; - } - } else { - for (id = 0; id < MAX_SBS_BAT; id++) { - if ((sbs->batteries_supported & (1 << id))) { - result = acpi_battery_add(sbs, id); - if (result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_battery_add() failed")); - goto end; - } - } - } - } - - init_timer(&sbs->update_timer); - result = acpi_check_update_proc(sbs); + result = acpi_charger_add(sbs); if (result) goto end; + result = acpi_manager_get_info(sbs); + if (!result) { + sbs->manager_present = 1; + for (id = 0; id < MAX_SBS_BAT; ++id) + if ((sbs->batteries_supported & (1 << id))) + acpi_battery_add(sbs, id); + } else + acpi_battery_add(sbs, 0); + acpi_smbus_register_callback(sbs->hc, acpi_sbs_callback, sbs); end: - - sbs_mutex_unlock(sbs); - - if (result) { - remove_result = acpi_sbs_remove(device, 0); - if (remove_result) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_sbs_remove() failed")); - } - } - + if (result) + acpi_sbs_remove(device, 0); return result; } @@ -1459,34 +744,19 @@ static int acpi_sbs_remove(struct acpi_device *device, int type) struct acpi_sbs *sbs; int id; - if (!device) { + if (!device) return -EINVAL; - } - sbs = acpi_driver_data(device); - if (!sbs) { + if (!sbs) return -EINVAL; - } - - sbs_mutex_lock(sbs); - - sbs->zombie = 1; - del_timer_sync(&sbs->update_timer); - acpi_os_wait_events_complete(NULL); - del_timer_sync(&sbs->update_timer); - - for (id = 0; id < MAX_SBS_BAT; id++) { + mutex_lock(&sbs->lock); + acpi_smbus_unregister_callback(sbs->hc); + for (id = 0; id < MAX_SBS_BAT; ++id) acpi_battery_remove(sbs, id); - } - - acpi_ac_remove(sbs); - - sbs_mutex_unlock(sbs); - - mutex_destroy(&sbs->mutex); - + acpi_charger_remove(sbs); + mutex_unlock(&sbs->lock); + mutex_destroy(&sbs->lock); kfree(sbs); - return 0; } @@ -1505,14 +775,10 @@ static void acpi_sbs_rmdirs(void) static int acpi_sbs_resume(struct acpi_device *device) { struct acpi_sbs *sbs; - if (!device) return -EINVAL; - sbs = device->driver_data; - - sbs->run_cnt = 0; - + acpi_sbs_callback(sbs); return 0; } @@ -1523,14 +789,6 @@ static int __init acpi_sbs_init(void) if (acpi_disabled) return -ENODEV; - if (mode != DEF_CAPACITY_UNIT - && mode != MAH_CAPACITY_UNIT - && mode != MWH_CAPACITY_UNIT) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "invalid mode = %d", mode)); - return -EINVAL; - } - acpi_ac_dir = acpi_lock_ac_dir(); if (!acpi_ac_dir) { ACPI_EXCEPTION((AE_INFO, AE_ERROR, -- cgit v1.1 From 94f6c0860139da9219255b8ff45ad42117dda859 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 26 Sep 2007 19:43:48 +0400 Subject: ACPI: SBS: Add support for power_supply class (and sysfs) Add support for power_supply class and sysfs interface of it. Refer to Documentation/power_supply_class.txt for interface description. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 9 +- drivers/acpi/sbs.c | 314 ++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 237 insertions(+), 86 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 8560bc3..ba6a61f 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -349,12 +349,11 @@ config ACPI_HOTPLUG_MEMORY $>modprobe acpi_memhotplug config ACPI_SBS - tristate "Smart Battery System (EXPERIMENTAL)" + tristate "Smart Battery System" depends on X86 - depends on EXPERIMENTAL + depends on POWER_SUPPLY help - This driver adds support for the Smart Battery System. - A "Smart Battery" is quite old and quite rare compared - to today's ACPI "Control Method" battery. + This driver adds support for the Smart Battery System, another + type of access to battery information, found on some laptops. endif # ACPI diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 3351dea..c4f9641 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -28,17 +28,20 @@ #include #include #include + #include #include #include + #include #include #include #include +#include + #include "sbshc.h" -#define ACPI_SBS_COMPONENT 0x00080000 #define ACPI_SBS_CLASS "sbs" #define ACPI_AC_CLASS "ac_adapter" #define ACPI_BATTERY_CLASS "battery" @@ -58,8 +61,6 @@ enum acpi_sbs_device_addr { #define ACPI_SBS_NOTIFY_STATUS 0x80 #define ACPI_SBS_NOTIFY_INFO 0x81 -ACPI_MODULE_NAME("sbs"); - MODULE_AUTHOR("Alexey Starikovskiy "); MODULE_DESCRIPTION("Smart Battery System ACPI interface driver"); MODULE_LICENSE("GPL"); @@ -76,28 +77,14 @@ extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); #define MAX_SBS_BAT 4 #define ACPI_SBS_BLOCK_MAX 32 -static int acpi_sbs_add(struct acpi_device *device); -static int acpi_sbs_remove(struct acpi_device *device, int type); -static int acpi_sbs_resume(struct acpi_device *device); - static const struct acpi_device_id sbs_device_ids[] = { {"ACPI0002", 0}, {"", 0}, }; MODULE_DEVICE_TABLE(acpi, sbs_device_ids); -static struct acpi_driver acpi_sbs_driver = { - .name = "sbs", - .class = ACPI_SBS_CLASS, - .ids = sbs_device_ids, - .ops = { - .add = acpi_sbs_add, - .remove = acpi_sbs_remove, - .resume = acpi_sbs_resume, - }, -}; - struct acpi_battery { + struct power_supply bat; struct acpi_sbs *sbs; struct proc_dir_entry *proc_entry; unsigned long update_time; @@ -105,7 +92,7 @@ struct acpi_battery { char manufacturer_name[ACPI_SBS_BLOCK_MAX]; char device_name[ACPI_SBS_BLOCK_MAX]; char device_chemistry[ACPI_SBS_BLOCK_MAX]; - u32 alarm_capacity; + u16 alarm_capacity; u16 full_charge_capacity; u16 design_capacity; u16 design_voltage; @@ -124,7 +111,10 @@ struct acpi_battery { u8 present:1; }; +#define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); + struct acpi_sbs { + struct power_supply charger; struct acpi_device *device; struct acpi_smb_hc *hc; struct mutex lock; @@ -135,6 +125,8 @@ struct acpi_sbs { u8 charger_present:1; }; +#define to_acpi_sbs(x) container_of(x, struct acpi_sbs, charger) + static inline int battery_scale(int log) { int scale = 1; @@ -164,6 +156,144 @@ static inline int acpi_battery_scale(struct acpi_battery *battery) acpi_battery_ipscale(battery); } +static int sbs_get_ac_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct acpi_sbs *sbs = to_acpi_sbs(psy); + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + val->intval = sbs->charger_present; + break; + default: + return -EINVAL; + } + return 0; +} + +static int acpi_battery_technology(struct acpi_battery *battery) +{ + if (!strcasecmp("NiCd", battery->device_chemistry)) + return POWER_SUPPLY_TECHNOLOGY_NiCd; + if (!strcasecmp("NiMH", battery->device_chemistry)) + return POWER_SUPPLY_TECHNOLOGY_NiMH; + if (!strcasecmp("LION", battery->device_chemistry)) + return POWER_SUPPLY_TECHNOLOGY_LION; + if (!strcasecmp("LiP", battery->device_chemistry)) + return POWER_SUPPLY_TECHNOLOGY_LIPO; + return POWER_SUPPLY_TECHNOLOGY_UNKNOWN; +} + +static int acpi_sbs_battery_get_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct acpi_battery *battery = to_acpi_battery(psy); + + if ((!battery->present) && psp != POWER_SUPPLY_PROP_PRESENT) + return -ENODEV; + switch (psp) { + case POWER_SUPPLY_PROP_STATUS: + if (battery->current_now < 0) + val->intval = POWER_SUPPLY_STATUS_DISCHARGING; + else if (battery->current_now > 0) + val->intval = POWER_SUPPLY_STATUS_CHARGING; + else + val->intval = POWER_SUPPLY_STATUS_FULL; + break; + case POWER_SUPPLY_PROP_PRESENT: + val->intval = battery->present; + break; + case POWER_SUPPLY_PROP_TECHNOLOGY: + val->intval = acpi_battery_technology(battery); + break; + case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN: + val->intval = battery->design_voltage * + acpi_battery_vscale(battery) * 1000; + break; + case POWER_SUPPLY_PROP_VOLTAGE_NOW: + val->intval = battery->voltage_now * + acpi_battery_vscale(battery) * 1000; + break; + case POWER_SUPPLY_PROP_CURRENT_NOW: + val->intval = abs(battery->current_now) * + acpi_battery_ipscale(battery) * 1000; + break; + case POWER_SUPPLY_PROP_CURRENT_AVG: + val->intval = abs(battery->current_avg) * + acpi_battery_ipscale(battery) * 1000; + break; + case POWER_SUPPLY_PROP_CAPACITY: + val->intval = battery->state_of_charge; + break; + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: + case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: + val->intval = battery->design_capacity * + acpi_battery_scale(battery) * 1000; + break; + case POWER_SUPPLY_PROP_CHARGE_FULL: + case POWER_SUPPLY_PROP_ENERGY_FULL: + val->intval = battery->full_charge_capacity * + acpi_battery_scale(battery) * 1000; + break; + case POWER_SUPPLY_PROP_CHARGE_NOW: + case POWER_SUPPLY_PROP_ENERGY_NOW: + val->intval = battery->capacity_now * + acpi_battery_scale(battery) * 1000; + break; + case POWER_SUPPLY_PROP_TEMP: + val->intval = battery->temp_now - 2730; // dK -> dC + break; + case POWER_SUPPLY_PROP_MODEL_NAME: + val->strval = battery->device_name; + break; + case POWER_SUPPLY_PROP_MANUFACTURER: + val->strval = battery->manufacturer_name; + break; + default: + return -EINVAL; + } + return 0; +} + +static enum power_supply_property sbs_ac_props[] = { + POWER_SUPPLY_PROP_ONLINE, +}; + +static enum power_supply_property sbs_charge_battery_props[] = { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CURRENT_AVG, + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, + POWER_SUPPLY_PROP_CHARGE_FULL, + POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_MODEL_NAME, + POWER_SUPPLY_PROP_MANUFACTURER, +}; + +static enum power_supply_property sbs_energy_battery_props[] = { + POWER_SUPPLY_PROP_STATUS, + POWER_SUPPLY_PROP_PRESENT, + POWER_SUPPLY_PROP_TECHNOLOGY, + POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN, + POWER_SUPPLY_PROP_VOLTAGE_NOW, + POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CURRENT_AVG, + POWER_SUPPLY_PROP_CAPACITY, + POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, + POWER_SUPPLY_PROP_ENERGY_FULL, + POWER_SUPPLY_PROP_ENERGY_NOW, + POWER_SUPPLY_PROP_TEMP, + POWER_SUPPLY_PROP_MODEL_NAME, + POWER_SUPPLY_PROP_MANUFACTURER, +}; + /* -------------------------------------------------------------------------- Smart Battery System Management -------------------------------------------------------------------------- */ @@ -204,7 +334,7 @@ static int acpi_manager_get_info(struct acpi_sbs *sbs) u16 battery_system_info; result = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER, - 0x04, (u8 *) & battery_system_info); + 0x04, (u8 *)&battery_system_info); if (!result) sbs->batteries_supported = battery_system_info & 0x000f; return result; @@ -215,9 +345,12 @@ static int acpi_battery_get_info(struct acpi_battery *battery) int i, result = 0; for (i = 0; i < ARRAY_SIZE(info_readers); ++i) { - result = acpi_smbus_read(battery->sbs->hc, info_readers[i].mode, - ACPI_SBS_BATTERY, info_readers[i].command, - (u8 *) battery + info_readers[i].offset); + result = acpi_smbus_read(battery->sbs->hc, + info_readers[i].mode, + ACPI_SBS_BATTERY, + info_readers[i].command, + (u8 *) battery + + info_readers[i].offset); if (result) break; } @@ -228,7 +361,8 @@ static int acpi_battery_get_state(struct acpi_battery *battery) { int i, result = 0; - if (time_before(jiffies, battery->update_time + + if (battery->update_time && + time_before(jiffies, battery->update_time + msecs_to_jiffies(cache_time))) return 0; for (i = 0; i < ARRAY_SIZE(state_readers); ++i) { @@ -250,26 +384,36 @@ static int acpi_battery_get_alarm(struct acpi_battery *battery) { return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, ACPI_SBS_BATTERY, 0x01, - (u8 *) & battery->alarm_capacity); + (u8 *)&battery->alarm_capacity); } static int acpi_battery_set_alarm(struct acpi_battery *battery) { struct acpi_sbs *sbs = battery->sbs; - u16 value; - return 0; + u16 value, sel = 1 << (battery->id + 12); + + int ret; + if (sbs->manager_present) { - acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER, + ret = acpi_smbus_read(sbs->hc, SMBUS_READ_WORD, ACPI_SBS_MANAGER, 0x01, (u8 *)&value); - value &= 0x0fff; - value |= 1 << (battery->id + 12); - acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_MANAGER, - 0x01, (u8 *)&value, 2); + if (ret) + goto end; + if ((value & 0xf000) != sel) { + value &= 0x0fff; + value |= sel; + ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, + ACPI_SBS_MANAGER, + 0x01, (u8 *)&value, 2); + if (ret) + goto end; + } } - value = battery->alarm_capacity / (acpi_battery_mode(battery) ? 10 : 1); - return acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, - 0x01, (u8 *)&value, 2); + ret = acpi_smbus_write(sbs->hc, SMBUS_WRITE_WORD, ACPI_SBS_BATTERY, + 0x01, (u8 *)&battery->alarm_capacity, 2); + end: + return ret; } static int acpi_ac_get_present(struct acpi_sbs *sbs) @@ -289,22 +433,19 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs) -------------------------------------------------------------------------- */ /* Generic Routines */ - static int acpi_sbs_add_fs(struct proc_dir_entry **dir, - struct proc_dir_entry *parent_dir, - char *dir_name, - struct file_operations *info_fops, - struct file_operations *state_fops, - struct file_operations *alarm_fops, void *data) + struct proc_dir_entry *parent_dir, + char *dir_name, + struct file_operations *info_fops, + struct file_operations *state_fops, + struct file_operations *alarm_fops, void *data) { struct proc_dir_entry *entry = NULL; if (!*dir) { *dir = proc_mkdir(dir_name, parent_dir); if (!*dir) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "proc_mkdir() failed")); return -ENODEV; } (*dir)->owner = THIS_MODULE; @@ -313,10 +454,7 @@ acpi_sbs_add_fs(struct proc_dir_entry **dir, /* 'info' [R] */ if (info_fops) { entry = create_proc_entry(ACPI_SBS_FILE_INFO, S_IRUGO, *dir); - if (!entry) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "create_proc_entry() failed")); - } else { + if (entry) { entry->proc_fops = info_fops; entry->data = data; entry->owner = THIS_MODULE; @@ -326,10 +464,7 @@ acpi_sbs_add_fs(struct proc_dir_entry **dir, /* 'state' [R] */ if (state_fops) { entry = create_proc_entry(ACPI_SBS_FILE_STATE, S_IRUGO, *dir); - if (!entry) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "create_proc_entry() failed")); - } else { + if (entry) { entry->proc_fops = state_fops; entry->data = data; entry->owner = THIS_MODULE; @@ -339,16 +474,12 @@ acpi_sbs_add_fs(struct proc_dir_entry **dir, /* 'alarm' [R/W] */ if (alarm_fops) { entry = create_proc_entry(ACPI_SBS_FILE_ALARM, S_IRUGO, *dir); - if (!entry) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "create_proc_entry() failed")); - } else { + if (entry) { entry->proc_fops = alarm_fops; entry->data = data; entry->owner = THIS_MODULE; } } - return 0; } @@ -356,7 +487,6 @@ static void acpi_sbs_remove_fs(struct proc_dir_entry **dir, struct proc_dir_entry *parent_dir) { - if (*dir) { remove_proc_entry(ACPI_SBS_FILE_INFO, *dir); remove_proc_entry(ACPI_SBS_FILE_STATE, *dir); @@ -364,11 +494,9 @@ acpi_sbs_remove_fs(struct proc_dir_entry **dir, remove_proc_entry((*dir)->name, parent_dir); *dir = NULL; } - } /* Smart Battery Interface */ - static struct proc_dir_entry *acpi_battery_dir = NULL; static inline char *acpi_battery_units(struct acpi_battery *battery) @@ -506,7 +634,8 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer, goto end; } alarm_string[count] = 0; - battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0); + battery->alarm_capacity = simple_strtoul(alarm_string, NULL, 0) / + acpi_battery_scale(battery); acpi_battery_set_alarm(battery); end: mutex_unlock(&sbs->lock); @@ -579,9 +708,6 @@ static struct file_operations acpi_ac_state_fops = { /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ - -/* Smart Battery */ - static int acpi_battery_read(struct acpi_battery *battery) { int result = 0, saved_present = battery->present; @@ -611,13 +737,14 @@ static int acpi_battery_read(struct acpi_battery *battery) return result; } +/* Smart Battery */ static int acpi_battery_add(struct acpi_sbs *sbs, int id) { - int result; struct acpi_battery *battery = &sbs->battery[id]; + int result; + battery->id = id; battery->sbs = sbs; - battery->update_time = 0; result = acpi_battery_read(battery); if (result) return result; @@ -627,6 +754,19 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) battery->name, &acpi_battery_info_fops, &acpi_battery_state_fops, &acpi_battery_alarm_fops, battery); + battery->bat.name = battery->name; + battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; + if (!acpi_battery_mode(battery)) { + battery->bat.properties = sbs_charge_battery_props; + battery->bat.num_properties = + ARRAY_SIZE(sbs_charge_battery_props); + } else { + battery->bat.properties = sbs_energy_battery_props; + battery->bat.num_properties = + ARRAY_SIZE(sbs_energy_battery_props); + } + battery->bat.get_property = acpi_sbs_battery_get_property; + result = power_supply_register(&sbs->device->dev, &battery->bat); printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), battery->name, sbs->battery->present ? "present" : "absent"); @@ -635,7 +775,8 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) static void acpi_battery_remove(struct acpi_sbs *sbs, int id) { - + if (sbs->battery[id].bat.dev) + power_supply_unregister(&sbs->battery[id].bat); if (sbs->battery[id].proc_entry) { acpi_sbs_remove_fs(&(sbs->battery[id].proc_entry), acpi_battery_dir); @@ -654,6 +795,12 @@ static int acpi_charger_add(struct acpi_sbs *sbs) &acpi_ac_state_fops, NULL, sbs); if (result) goto end; + sbs->charger.name = "sbs-charger"; + sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; + sbs->charger.properties = sbs_ac_props; + sbs->charger.num_properties = ARRAY_SIZE(sbs_ac_props); + sbs->charger.get_property = sbs_get_ac_property; + power_supply_register(&sbs->device->dev, &sbs->charger); printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), ACPI_AC_DIR_NAME, sbs->charger_present ? "on-line" : "off-line"); @@ -663,7 +810,8 @@ static int acpi_charger_add(struct acpi_sbs *sbs) static void acpi_charger_remove(struct acpi_sbs *sbs) { - + if (sbs->charger.dev) + power_supply_unregister(&sbs->charger); if (sbs->charger_entry) acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir); } @@ -677,9 +825,12 @@ void acpi_sbs_callback(void *context) u8 saved_battery_state; acpi_ac_get_present(sbs); if (sbs->charger_present != saved_charger_state) { +#ifdef CONFIG_ACPI_PROC_EVENT acpi_bus_generate_proc_event4(ACPI_AC_CLASS, ACPI_AC_DIR_NAME, ACPI_SBS_NOTIFY_STATUS, sbs->charger_present); +#endif + kobject_uevent(&sbs->charger.dev->kobj, KOBJ_CHANGE); } if (sbs->manager_present) { for (id = 0; id < MAX_SBS_BAT; ++id) { @@ -690,10 +841,13 @@ void acpi_sbs_callback(void *context) acpi_battery_read(bat); if (saved_battery_state == bat->present) continue; +#ifdef CONFIG_ACPI_PROC_EVENT acpi_bus_generate_proc_event4(ACPI_BATTERY_CLASS, bat->name, ACPI_SBS_NOTIFY_STATUS, bat->present); +#endif + kobject_uevent(&bat->bat.dev->kobj, KOBJ_CHANGE); } } } @@ -782,45 +936,43 @@ static int acpi_sbs_resume(struct acpi_device *device) return 0; } +static struct acpi_driver acpi_sbs_driver = { + .name = "sbs", + .class = ACPI_SBS_CLASS, + .ids = sbs_device_ids, + .ops = { + .add = acpi_sbs_add, + .remove = acpi_sbs_remove, + .resume = acpi_sbs_resume, + }, +}; + static int __init acpi_sbs_init(void) { int result = 0; if (acpi_disabled) return -ENODEV; - acpi_ac_dir = acpi_lock_ac_dir(); - if (!acpi_ac_dir) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_lock_ac_dir() failed")); + if (!acpi_ac_dir) return -ENODEV; - } - acpi_battery_dir = acpi_lock_battery_dir(); if (!acpi_battery_dir) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_lock_battery_dir() failed")); acpi_sbs_rmdirs(); return -ENODEV; } - result = acpi_bus_register_driver(&acpi_sbs_driver); if (result < 0) { - ACPI_EXCEPTION((AE_INFO, AE_ERROR, - "acpi_bus_register_driver() failed")); acpi_sbs_rmdirs(); return -ENODEV; } - return 0; } static void __exit acpi_sbs_exit(void) { acpi_bus_unregister_driver(&acpi_sbs_driver); - acpi_sbs_rmdirs(); - return; } -- cgit v1.1 From 66e4b72bfa7347fd1017b9b82dce77a410f2e4a1 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 26 Sep 2007 19:43:54 +0400 Subject: ACPI: SBS: Add ACPI_PROCFS around procfs handling code. Make procfs support optional under ACPI_PROCFS Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/sbs.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index c4f9641..aae65e8 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -29,9 +29,11 @@ #include #include +#ifdef CONFIG_ACPI_PROCFS #include #include #include +#endif #include #include @@ -86,7 +88,9 @@ MODULE_DEVICE_TABLE(acpi, sbs_device_ids); struct acpi_battery { struct power_supply bat; struct acpi_sbs *sbs; +#ifdef CONFIG_ACPI_PROCFS struct proc_dir_entry *proc_entry; +#endif unsigned long update_time; char name[8]; char manufacturer_name[ACPI_SBS_BLOCK_MAX]; @@ -118,7 +122,9 @@ struct acpi_sbs { struct acpi_device *device; struct acpi_smb_hc *hc; struct mutex lock; +#ifdef CONFIG_ACPI_PROCFS struct proc_dir_entry *charger_entry; +#endif struct acpi_battery battery[MAX_SBS_BAT]; u8 batteries_supported:4; u8 manager_present:1; @@ -380,6 +386,8 @@ static int acpi_battery_get_state(struct acpi_battery *battery) return result; } +#ifdef CONFIG_ACPI_PROCFS + static int acpi_battery_get_alarm(struct acpi_battery *battery) { return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, @@ -416,6 +424,8 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery) return ret; } +#endif + static int acpi_ac_get_present(struct acpi_sbs *sbs) { int result; @@ -432,6 +442,7 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs) FS Interface (/proc/acpi) -------------------------------------------------------------------------- */ +#ifdef CONFIG_ACPI_PROCFS /* Generic Routines */ static int acpi_sbs_add_fs(struct proc_dir_entry **dir, @@ -705,6 +716,8 @@ static struct file_operations acpi_ac_state_fops = { .owner = THIS_MODULE, }; +#endif + /* -------------------------------------------------------------------------- Driver Interface -------------------------------------------------------------------------- */ @@ -750,10 +763,12 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) return result; sprintf(battery->name, ACPI_BATTERY_DIR_NAME, id); +#ifdef CONFIG_ACPI_PROCFS acpi_sbs_add_fs(&battery->proc_entry, acpi_battery_dir, battery->name, &acpi_battery_info_fops, &acpi_battery_state_fops, &acpi_battery_alarm_fops, battery); +#endif battery->bat.name = battery->name; battery->bat.type = POWER_SUPPLY_TYPE_BATTERY; if (!acpi_battery_mode(battery)) { @@ -777,10 +792,12 @@ static void acpi_battery_remove(struct acpi_sbs *sbs, int id) { if (sbs->battery[id].bat.dev) power_supply_unregister(&sbs->battery[id].bat); +#ifdef CONFIG_ACPI_PROCFS if (sbs->battery[id].proc_entry) { acpi_sbs_remove_fs(&(sbs->battery[id].proc_entry), acpi_battery_dir); } +#endif } static int acpi_charger_add(struct acpi_sbs *sbs) @@ -790,11 +807,13 @@ static int acpi_charger_add(struct acpi_sbs *sbs) result = acpi_ac_get_present(sbs); if (result) goto end; +#ifdef CONFIG_ACPI_PROCFS result = acpi_sbs_add_fs(&sbs->charger_entry, acpi_ac_dir, ACPI_AC_DIR_NAME, NULL, &acpi_ac_state_fops, NULL, sbs); if (result) goto end; +#endif sbs->charger.name = "sbs-charger"; sbs->charger.type = POWER_SUPPLY_TYPE_MAINS; sbs->charger.properties = sbs_ac_props; @@ -812,8 +831,10 @@ static void acpi_charger_remove(struct acpi_sbs *sbs) { if (sbs->charger.dev) power_supply_unregister(&sbs->charger); +#ifdef CONFIG_ACPI_PROCFS if (sbs->charger_entry) acpi_sbs_remove_fs(&sbs->charger_entry, acpi_ac_dir); +#endif } void acpi_sbs_callback(void *context) @@ -916,6 +937,7 @@ static int acpi_sbs_remove(struct acpi_device *device, int type) static void acpi_sbs_rmdirs(void) { +#ifdef CONFIG_ACPI_PROCFS if (acpi_ac_dir) { acpi_unlock_ac_dir(acpi_ac_dir); acpi_ac_dir = NULL; @@ -924,6 +946,7 @@ static void acpi_sbs_rmdirs(void) acpi_unlock_battery_dir(acpi_battery_dir); acpi_battery_dir = NULL; } +#endif } static int acpi_sbs_resume(struct acpi_device *device) @@ -953,6 +976,7 @@ static int __init acpi_sbs_init(void) if (acpi_disabled) return -ENODEV; +#ifdef CONFIG_ACPI_PROCFS acpi_ac_dir = acpi_lock_ac_dir(); if (!acpi_ac_dir) return -ENODEV; @@ -961,6 +985,7 @@ static int __init acpi_sbs_init(void) acpi_sbs_rmdirs(); return -ENODEV; } +#endif result = acpi_bus_register_driver(&acpi_sbs_driver); if (result < 0) { acpi_sbs_rmdirs(); -- cgit v1.1 From 8bd955320661cfd03ab8d5574d96aa684acd38f6 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 26 Sep 2007 19:44:00 +0400 Subject: ACPI: SBS: Add sysfs alarm Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/sbs.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index aae65e8..90fd09c 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c @@ -386,8 +386,6 @@ static int acpi_battery_get_state(struct acpi_battery *battery) return result; } -#ifdef CONFIG_ACPI_PROCFS - static int acpi_battery_get_alarm(struct acpi_battery *battery) { return acpi_smbus_read(battery->sbs->hc, SMBUS_READ_WORD, @@ -424,8 +422,6 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery) return ret; } -#endif - static int acpi_ac_get_present(struct acpi_sbs *sbs) { int result; @@ -438,6 +434,36 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs) return result; } +static ssize_t acpi_battery_alarm_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); + acpi_battery_get_alarm(battery); + return sprintf(buf, "%d\n", battery->alarm_capacity * + acpi_battery_scale(battery) * 1000); +} + +static ssize_t acpi_battery_alarm_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + unsigned long x; + struct acpi_battery *battery = to_acpi_battery(dev_get_drvdata(dev)); + if (sscanf(buf, "%ld\n", &x) == 1) + battery->alarm_capacity = x / + (1000 * acpi_battery_scale(battery)); + if (battery->present) + acpi_battery_set_alarm(battery); + return count; +} + +static struct device_attribute alarm_attr = { + .attr = {.name = "alarm", .mode = 0644, .owner = THIS_MODULE}, + .show = acpi_battery_alarm_show, + .store = acpi_battery_alarm_store, +}; + /* -------------------------------------------------------------------------- FS Interface (/proc/acpi) -------------------------------------------------------------------------- */ @@ -782,6 +808,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) } battery->bat.get_property = acpi_sbs_battery_get_property; result = power_supply_register(&sbs->device->dev, &battery->bat); + device_create_file(battery->bat.dev, &alarm_attr); printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), battery->name, sbs->battery->present ? "present" : "absent"); @@ -791,6 +818,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) static void acpi_battery_remove(struct acpi_sbs *sbs, int id) { if (sbs->battery[id].bat.dev) + device_remove_file(sbs->battery[id].bat.dev, &alarm_attr); power_supply_unregister(&sbs->battery[id].bat); #ifdef CONFIG_ACPI_PROCFS if (sbs->battery[id].proc_entry) { -- cgit v1.1 From d5b4a3d0efa36de31b86d5677dad6c36cb8735d7 Mon Sep 17 00:00:00 2001 From: Alexey Starikovskiy Date: Wed, 26 Sep 2007 19:44:06 +0400 Subject: ACPI: AC: Add sysfs interface Refer to Documentation/power_supply_class.txt for interface description. Signed-off-by: Alexey Starikovskiy Signed-off-by: Len Brown --- drivers/acpi/Kconfig | 2 +- drivers/acpi/ac.c | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) (limited to 'drivers/acpi') diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index ba6a61f..a858bc5 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -88,7 +88,7 @@ config ACPI_PROC_EVENT config ACPI_AC tristate "AC Adapter" - depends on X86 + depends on X86 && POWER_SUPPLY default y help This driver adds support for the AC Adapter object, which indicates diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 26d7070..e03de37 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -72,16 +73,37 @@ static struct acpi_driver acpi_ac_driver = { }; struct acpi_ac { + struct power_supply charger; struct acpi_device * device; unsigned long state; }; +#define to_acpi_ac(x) container_of(x, struct acpi_ac, charger); + static const struct file_operations acpi_ac_fops = { .open = acpi_ac_open_fs, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; +static int get_ac_property(struct power_supply *psy, + enum power_supply_property psp, + union power_supply_propval *val) +{ + struct acpi_ac *ac = to_acpi_ac(psy); + switch (psp) { + case POWER_SUPPLY_PROP_ONLINE: + val->intval = ac->state; + break; + default: + return -EINVAL; + } + return 0; +} + +static enum power_supply_property ac_props[] = { + POWER_SUPPLY_PROP_ONLINE, +}; /* -------------------------------------------------------------------------- AC Adapter Management @@ -208,6 +230,7 @@ static void acpi_ac_notify(acpi_handle handle, u32 event, void *data) acpi_bus_generate_netlink_event(device->pnp.device_class, device->dev.bus_id, event, (u32) ac->state); + kobject_uevent(&ac->charger.dev->kobj, KOBJ_CHANGE); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -244,7 +267,12 @@ static int acpi_ac_add(struct acpi_device *device) result = acpi_ac_add_fs(device); if (result) goto end; - + ac->charger.name = acpi_device_bid(device); + ac->charger.type = POWER_SUPPLY_TYPE_MAINS; + ac->charger.properties = ac_props; + ac->charger.num_properties = ARRAY_SIZE(ac_props); + ac->charger.get_property = get_ac_property; + power_supply_register(&ac->device->dev, &ac->charger); status = acpi_install_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_ac_notify, ac); @@ -279,7 +307,8 @@ static int acpi_ac_remove(struct acpi_device *device, int type) status = acpi_remove_notify_handler(device->handle, ACPI_ALL_NOTIFY, acpi_ac_notify); - + if (ac->charger.dev) + power_supply_unregister(&ac->charger); acpi_ac_remove_fs(device); kfree(ac); -- cgit v1.1