aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/battery.c
diff options
context:
space:
mode:
authorVladimir Lebedev <vladimir.p.lebedev@intel.com>2007-02-20 07:48:06 -0500
committerLen Brown <len.brown@intel.com>2007-03-07 01:48:07 -0500
commitb6ce4083ed8e2a01a3a59301eabe0fc1e68a8a84 (patch)
treef332faa4712841a76a61c885c304662e3b6e4a59 /drivers/acpi/battery.c
parenta1f0eff21edac1bd87e397f56c4258b9611b5a50 (diff)
ACPI: Cache battery status instead of re-evaluating AML
/proc exports _BST in a single file, and _BST is re-evaulated whenever that file is read. Sometimes user-space reads this file frequently, and on some systems _BST takes a long time to evaluate due to a slow EC. Further, when we move to sysfs, the values returned from _BST will be in multiple files, and evaluating _BST for each file read would make matters worse. Here code is added to support caching the results of _BST. A new module parameter "update_time" tells how many seconds the cached _BST should be used before it is re-evaluated. Currently, update_time defaults to 0, and so the existing behaviour of re-evaluating on each read retained. Signed-off-by: Vladimir Lebedev <vladimir.p.lebedev@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/battery.c')
-rw-r--r--drivers/acpi/battery.c613
1 files changed, 441 insertions, 172 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index df04f87dd491..f3b0024e5760 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -52,12 +52,24 @@
52#define ACPI_BATTERY_UNITS_AMPS "mA" 52#define ACPI_BATTERY_UNITS_AMPS "mA"
53 53
54#define _COMPONENT ACPI_BATTERY_COMPONENT 54#define _COMPONENT ACPI_BATTERY_COMPONENT
55
56#define ACPI_BATTERY_UPDATE_TIME 0
57
58#define ACPI_BATTERY_NONE_UPDATE 0
59#define ACPI_BATTERY_EASY_UPDATE 1
60#define ACPI_BATTERY_INIT_UPDATE 2
61
55ACPI_MODULE_NAME("battery"); 62ACPI_MODULE_NAME("battery");
56 63
57MODULE_AUTHOR("Paul Diefenbaugh"); 64MODULE_AUTHOR("Paul Diefenbaugh");
58MODULE_DESCRIPTION("ACPI Battery Driver"); 65MODULE_DESCRIPTION("ACPI Battery Driver");
59MODULE_LICENSE("GPL"); 66MODULE_LICENSE("GPL");
60 67
68static unsigned int update_time = ACPI_BATTERY_UPDATE_TIME;
69
70/* 0 - every time, > 0 - by update_time */
71module_param(update_time, uint, 0644);
72
61extern struct proc_dir_entry *acpi_lock_battery_dir(void); 73extern struct proc_dir_entry *acpi_lock_battery_dir(void);
62extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); 74extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
63 75
@@ -100,32 +112,117 @@ struct acpi_battery_info {
100}; 112};
101 113
102struct acpi_battery_flags { 114struct acpi_battery_flags {
103 u8 present:1; /* Bay occupied? */ 115 u8 battery_present_prev;
104 u8 power_unit:1; /* 0=watts, 1=apms */ 116 u8 alarm_present;
105 u8 alarm:1; /* _BTP present? */ 117 u8 init_update;
106 u8 reserved:5; 118 u8 info_update;
107}; 119 u8 state_update;
108 120 u8 alarm_update;
109struct acpi_battery_trips { 121 u8 power_unit;
110 unsigned long warning;
111 unsigned long low;
112}; 122};
113 123
114struct acpi_battery { 124struct acpi_battery {
125 struct mutex mutex;
115 struct acpi_device * device; 126 struct acpi_device * device;
116 struct acpi_battery_flags flags; 127 struct acpi_battery_flags flags;
117 struct acpi_battery_trips trips; 128 struct acpi_buffer bif_data;
129 struct acpi_buffer bst_data;
118 unsigned long alarm; 130 unsigned long alarm;
119 struct acpi_battery_info *info; 131 unsigned long info_update_time;
132 unsigned long state_update_time;
133 unsigned long alarm_update_time;
120}; 134};
121 135
136#define acpi_battery_present(battery) battery->device->status.battery_present
137#define acpi_battery_present_prev(battery) battery->flags.battery_present_prev
138#define acpi_battery_alarm_present(battery) battery->flags.alarm_present
139#define acpi_battery_init_update_flag(battery) battery->flags.init_update
140#define acpi_battery_info_update_flag(battery) battery->flags.info_update
141#define acpi_battery_state_update_flag(battery) battery->flags.state_update
142#define acpi_battery_alarm_update_flag(battery) battery->flags.alarm_update
143#define acpi_battery_power_units(battery) battery->flags.power_unit ? \
144 ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS
145#define acpi_battery_handle(battery) battery->device->handle
146#define acpi_battery_inserted(battery) (!acpi_battery_present_prev(battery) & acpi_battery_present(battery))
147#define acpi_battery_removed(battery) (acpi_battery_present_prev(battery) & !acpi_battery_present(battery))
148#define acpi_battery_bid(battery) acpi_device_bid(battery->device)
149#define acpi_battery_status_str(battery) acpi_battery_present(battery) ? "present" : "absent"
150
122/* -------------------------------------------------------------------------- 151/* --------------------------------------------------------------------------
123 Battery Management 152 Battery Management
124 -------------------------------------------------------------------------- */ 153 -------------------------------------------------------------------------- */
125 154
126static int 155static void acpi_battery_mutex_lock(struct acpi_battery *battery)
127acpi_battery_get_info(struct acpi_battery *battery, 156{
128 struct acpi_battery_info **bif) 157 mutex_lock(&battery->mutex);
158}
159
160static void acpi_battery_mutex_unlock(struct acpi_battery *battery)
161{
162 mutex_unlock(&battery->mutex);
163}
164
165static void acpi_battery_check_result(struct acpi_battery *battery, int result)
166{
167 if (!battery)
168 return;
169
170 if (result) {
171 acpi_battery_init_update_flag(battery) = 1;
172 }
173}
174
175static int acpi_battery_extract_package(struct acpi_battery *battery,
176 union acpi_object *package,
177 struct acpi_buffer *format,
178 struct acpi_buffer *data,
179 char *package_name)
180{
181 acpi_status status = AE_OK;
182 struct acpi_buffer data_null = { 0, NULL };
183
184 status = acpi_extract_package(package, format, &data_null);
185 if (status != AE_BUFFER_OVERFLOW) {
186 ACPI_EXCEPTION((AE_INFO, status, "Extracting size %s",
187 package_name));
188 return -ENODEV;
189 }
190
191 if (data_null.length != data->length) {
192 if (data->pointer) {
193 kfree(data->pointer);
194 }
195 data->pointer = kzalloc(data_null.length, GFP_KERNEL);
196 if (!data->pointer) {
197 ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "kzalloc()"));
198 return -ENOMEM;
199 }
200 data->length = data_null.length;
201 }
202
203 status = acpi_extract_package(package, format, data);
204 if (ACPI_FAILURE(status)) {
205 ACPI_EXCEPTION((AE_INFO, status, "Extracting %s",
206 package_name));
207 return -ENODEV;
208 }
209
210 return 0;
211}
212
213static int acpi_battery_get_status(struct acpi_battery *battery)
214{
215 int result = 0;
216
217 result = acpi_bus_get_status(battery->device);
218 if (result) {
219 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
220 return -ENODEV;
221 }
222 return result;
223}
224
225static int acpi_battery_get_info(struct acpi_battery *battery)
129{ 226{
130 int result = 0; 227 int result = 0;
131 acpi_status status = 0; 228 acpi_status status = 0;
@@ -133,16 +230,18 @@ acpi_battery_get_info(struct acpi_battery *battery,
133 struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF), 230 struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF),
134 ACPI_BATTERY_FORMAT_BIF 231 ACPI_BATTERY_FORMAT_BIF
135 }; 232 };
136 struct acpi_buffer data = { 0, NULL };
137 union acpi_object *package = NULL; 233 union acpi_object *package = NULL;
234 struct acpi_buffer *data = NULL;
235 struct acpi_battery_info *bif = NULL;
138 236
237 battery->info_update_time = get_seconds();
139 238
140 if (!battery || !bif) 239 if (!acpi_battery_present(battery))
141 return -EINVAL; 240 return 0;
142 241
143 /* Evalute _BIF */ 242 /* Evalute _BIF */
144 243
145 status = acpi_evaluate_object(battery->device->handle, "_BIF", NULL, &buffer); 244 status = acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL, &buffer);
146 if (ACPI_FAILURE(status)) { 245 if (ACPI_FAILURE(status)) {
147 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); 246 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF"));
148 return -ENODEV; 247 return -ENODEV;
@@ -150,41 +249,29 @@ acpi_battery_get_info(struct acpi_battery *battery,
150 249
151 package = buffer.pointer; 250 package = buffer.pointer;
152 251
252 data = &battery->bif_data;
253
153 /* Extract Package Data */ 254 /* Extract Package Data */
154 255
155 status = acpi_extract_package(package, &format, &data); 256 result = acpi_battery_extract_package(battery, package, &format, data, "_BIF");
156 if (status != AE_BUFFER_OVERFLOW) { 257 if (result)
157 ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF"));
158 result = -ENODEV;
159 goto end; 258 goto end;
160 }
161 259
162 data.pointer = kzalloc(data.length, GFP_KERNEL); 260 end:
163 if (!data.pointer) {
164 result = -ENOMEM;
165 goto end;
166 }
167 261
168 status = acpi_extract_package(package, &format, &data); 262 if (buffer.pointer) {
169 if (ACPI_FAILURE(status)) { 263 kfree(buffer.pointer);
170 ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF"));
171 kfree(data.pointer);
172 result = -ENODEV;
173 goto end;
174 } 264 }
175 265
176 end: 266 if (!result) {
177 kfree(buffer.pointer); 267 bif = data->pointer;
178 268 battery->flags.power_unit = bif->power_unit;
179 if (!result) 269 }
180 (*bif) = data.pointer;
181 270
182 return result; 271 return result;
183} 272}
184 273
185static int 274static int acpi_battery_get_state(struct acpi_battery *battery)
186acpi_battery_get_state(struct acpi_battery *battery,
187 struct acpi_battery_state **bst)
188{ 275{
189 int result = 0; 276 int result = 0;
190 acpi_status status = 0; 277 acpi_status status = 0;
@@ -192,16 +279,17 @@ acpi_battery_get_state(struct acpi_battery *battery,
192 struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST), 279 struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST),
193 ACPI_BATTERY_FORMAT_BST 280 ACPI_BATTERY_FORMAT_BST
194 }; 281 };
195 struct acpi_buffer data = { 0, NULL };
196 union acpi_object *package = NULL; 282 union acpi_object *package = NULL;
283 struct acpi_buffer *data = NULL;
197 284
285 battery->state_update_time = get_seconds();
198 286
199 if (!battery || !bst) 287 if (!acpi_battery_present(battery))
200 return -EINVAL; 288 return 0;
201 289
202 /* Evalute _BST */ 290 /* Evalute _BST */
203 291
204 status = acpi_evaluate_object(battery->device->handle, "_BST", NULL, &buffer); 292 status = acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL, &buffer);
205 if (ACPI_FAILURE(status)) { 293 if (ACPI_FAILURE(status)) {
206 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST")); 294 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
207 return -ENODEV; 295 return -ENODEV;
@@ -209,55 +297,46 @@ acpi_battery_get_state(struct acpi_battery *battery,
209 297
210 package = buffer.pointer; 298 package = buffer.pointer;
211 299
212 /* Extract Package Data */ 300 data = &battery->bst_data;
213 301
214 status = acpi_extract_package(package, &format, &data); 302 /* Extract Package Data */
215 if (status != AE_BUFFER_OVERFLOW) {
216 ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST"));
217 result = -ENODEV;
218 goto end;
219 }
220 303
221 data.pointer = kzalloc(data.length, GFP_KERNEL); 304 result = acpi_battery_extract_package(battery, package, &format, data, "_BST");
222 if (!data.pointer) { 305 if (result)
223 result = -ENOMEM;
224 goto end; 306 goto end;
225 }
226 307
227 status = acpi_extract_package(package, &format, &data); 308 end:
228 if (ACPI_FAILURE(status)) { 309 if (buffer.pointer) {
229 ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST")); 310 kfree(buffer.pointer);
230 kfree(data.pointer);
231 result = -ENODEV;
232 goto end;
233 } 311 }
234 312
235 end: 313 return result;
236 kfree(buffer.pointer); 314}
237 315
238 if (!result) 316static int acpi_battery_get_alarm(struct acpi_battery *battery)
239 (*bst) = data.pointer; 317{
318 battery->alarm_update_time = get_seconds();
240 319
241 return result; 320 return 0;
242} 321}
243 322
244static int 323static int acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm)
245acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm)
246{ 324{
247 acpi_status status = 0; 325 acpi_status status = 0;
248 union acpi_object arg0 = { ACPI_TYPE_INTEGER }; 326 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
249 struct acpi_object_list arg_list = { 1, &arg0 }; 327 struct acpi_object_list arg_list = { 1, &arg0 };
250 328
329 battery->alarm_update_time = get_seconds();
251 330
252 if (!battery) 331 if (!acpi_battery_present(battery))
253 return -EINVAL; 332 return -ENODEV;
254 333
255 if (!battery->flags.alarm) 334 if (!acpi_battery_alarm_present(battery))
256 return -ENODEV; 335 return -ENODEV;
257 336
258 arg0.integer.value = alarm; 337 arg0.integer.value = alarm;
259 338
260 status = acpi_evaluate_object(battery->device->handle, "_BTP", &arg_list, NULL); 339 status = acpi_evaluate_object(acpi_battery_handle(battery), "_BTP", &arg_list, NULL);
261 if (ACPI_FAILURE(status)) 340 if (ACPI_FAILURE(status))
262 return -ENODEV; 341 return -ENODEV;
263 342
@@ -268,65 +347,110 @@ acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm)
268 return 0; 347 return 0;
269} 348}
270 349
271static int acpi_battery_check(struct acpi_battery *battery) 350static int acpi_battery_init_alarm(struct acpi_battery *battery)
272{ 351{
273 int result = 0; 352 int result = 0;
274 acpi_status status = AE_OK; 353 acpi_status status = AE_OK;
275 acpi_handle handle = NULL; 354 acpi_handle handle = NULL;
276 struct acpi_device *device = NULL; 355 struct acpi_battery_info *bif = battery->bif_data.pointer;
277 struct acpi_battery_info *bif = NULL; 356 unsigned long alarm = battery->alarm;
278
279 357
280 if (!battery) 358 /* See if alarms are supported, and if so, set default */
281 return -EINVAL;
282 359
283 device = battery->device; 360 status = acpi_get_handle(acpi_battery_handle(battery), "_BTP", &handle);
361 if (ACPI_SUCCESS(status)) {
362 acpi_battery_alarm_present(battery) = 1;
363 if (!alarm && bif) {
364 alarm = bif->design_capacity_warning;
365 }
366 result = acpi_battery_set_alarm(battery, alarm);
367 if (result)
368 goto end;
369 } else {
370 acpi_battery_alarm_present(battery) = 0;
371 }
284 372
285 result = acpi_bus_get_status(device); 373 end:
286 if (result)
287 return result;
288 374
289 /* Insertion? */ 375 return result;
376}
290 377
291 if (!battery->flags.present && device->status.battery_present) { 378static int acpi_battery_init_update(struct acpi_battery *battery)
379{
380 int result = 0;
292 381
293 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n")); 382 result = acpi_battery_get_status(battery);
383 if (result)
384 return result;
294 385
295 /* Evalute _BIF to get certain static information */ 386 acpi_battery_present_prev(battery) = acpi_battery_present(battery);
296 387
297 result = acpi_battery_get_info(battery, &bif); 388 if (acpi_battery_present(battery)) {
389 result = acpi_battery_get_info(battery);
390 if (result)
391 return result;
392 result = acpi_battery_get_state(battery);
298 if (result) 393 if (result)
299 return result; 394 return result;
300 395
301 battery->flags.power_unit = bif->power_unit; 396 acpi_battery_init_alarm(battery);
302 battery->trips.warning = bif->design_capacity_warning; 397 }
303 battery->trips.low = bif->design_capacity_low; 398
304 kfree(bif); 399 return result;
400}
401
402static int acpi_battery_update(struct acpi_battery *battery,
403 int update, int *update_result_ptr)
404{
405 int result = 0;
406 int update_result = ACPI_BATTERY_NONE_UPDATE;
305 407
306 /* See if alarms are supported, and if so, set default */ 408 if (!acpi_battery_present(battery)) {
409 update = 1;
410 }
307 411
308 status = acpi_get_handle(battery->device->handle, "_BTP", &handle); 412 if (acpi_battery_init_update_flag(battery)) {
309 if (ACPI_SUCCESS(status)) { 413 result = acpi_battery_init_update(battery);
310 battery->flags.alarm = 1; 414 if (result)
311 acpi_battery_set_alarm(battery, battery->trips.warning); 415 goto end;;
416 update_result = ACPI_BATTERY_INIT_UPDATE;
417 } else if (update) {
418 result = acpi_battery_get_status(battery);
419 if (result)
420 goto end;;
421 if (acpi_battery_inserted(battery) || acpi_battery_removed(battery)) {
422 result = acpi_battery_init_update(battery);
423 if (result)
424 goto end;;
425 update_result = ACPI_BATTERY_INIT_UPDATE;
426 } else {
427 update_result = ACPI_BATTERY_EASY_UPDATE;
312 } 428 }
313 } 429 }
314 430
315 /* Removal? */ 431 end:
316 432
317 else if (battery->flags.present && !device->status.battery_present) { 433 acpi_battery_init_update_flag(battery) = (result != 0);
318 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n"));
319 }
320 434
321 battery->flags.present = device->status.battery_present; 435 *update_result_ptr = update_result;
322 436
323 return result; 437 return result;
324} 438}
325 439
326static void acpi_battery_check_present(struct acpi_battery *battery) 440static void acpi_battery_notify_update(struct acpi_battery *battery)
327{ 441{
328 if (!battery->flags.present) { 442 acpi_battery_get_status(battery);
329 acpi_battery_check(battery); 443
444 if (acpi_battery_init_update_flag(battery)) {
445 return;
446 }
447
448 if (acpi_battery_inserted(battery) || acpi_battery_removed(battery)) {
449 acpi_battery_init_update_flag(battery) = 1;
450 } else {
451 acpi_battery_info_update_flag(battery) = 1;
452 acpi_battery_state_update_flag(battery) = 1;
453 acpi_battery_alarm_update_flag(battery) = 1;
330 } 454 }
331} 455}
332 456
@@ -335,37 +459,33 @@ static void acpi_battery_check_present(struct acpi_battery *battery)
335 -------------------------------------------------------------------------- */ 459 -------------------------------------------------------------------------- */
336 460
337static struct proc_dir_entry *acpi_battery_dir; 461static struct proc_dir_entry *acpi_battery_dir;
338static int acpi_battery_read_info(struct seq_file *seq, void *offset) 462
463static int acpi_battery_read_info_print(struct seq_file *seq, int result)
339{ 464{
340 int result = 0;
341 struct acpi_battery *battery = seq->private; 465 struct acpi_battery *battery = seq->private;
342 struct acpi_battery_info *bif = NULL; 466 struct acpi_battery_info *bif = NULL;
343 char *units = "?"; 467 char *units = "?";
344 468
345 469 if (result)
346 if (!battery)
347 goto end; 470 goto end;
348 471
349 acpi_battery_check_present(battery); 472 if (acpi_battery_present(battery))
350
351 if (battery->flags.present)
352 seq_printf(seq, "present: yes\n"); 473 seq_printf(seq, "present: yes\n");
353 else { 474 else {
354 seq_printf(seq, "present: no\n"); 475 seq_printf(seq, "present: no\n");
355 goto end; 476 goto end;
356 } 477 }
357 478
358 /* Battery Info (_BIF) */ 479 bif = battery->bif_data.pointer;
359 480 if (!bif) {
360 result = acpi_battery_get_info(battery, &bif); 481 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BIF buffer is NULL"));
361 if (result || !bif) { 482 result = -ENODEV;
362 seq_printf(seq, "ERROR: Unable to read battery information\n");
363 goto end; 483 goto end;
364 } 484 }
365 485
366 units = 486 /* Battery Units */
367 bif-> 487
368 power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; 488 units = acpi_battery_power_units(battery);
369 489
370 if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) 490 if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
371 seq_printf(seq, "design capacity: unknown\n"); 491 seq_printf(seq, "design capacity: unknown\n");
@@ -396,7 +516,6 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
396 else 516 else
397 seq_printf(seq, "design voltage: %d mV\n", 517 seq_printf(seq, "design voltage: %d mV\n",
398 (u32) bif->design_voltage); 518 (u32) bif->design_voltage);
399
400 seq_printf(seq, "design capacity warning: %d %sh\n", 519 seq_printf(seq, "design capacity warning: %d %sh\n",
401 (u32) bif->design_capacity_warning, units); 520 (u32) bif->design_capacity_warning, units);
402 seq_printf(seq, "design capacity low: %d %sh\n", 521 seq_printf(seq, "design capacity low: %d %sh\n",
@@ -411,9 +530,48 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
411 seq_printf(seq, "OEM info: %s\n", bif->oem_info); 530 seq_printf(seq, "OEM info: %s\n", bif->oem_info);
412 531
413 end: 532 end:
414 kfree(bif);
415 533
416 return 0; 534 if (result)
535 seq_printf(seq, "ERROR: Unable to read battery info\n");
536
537 return result;
538}
539
540static int acpi_battery_read_info(struct seq_file *seq, void *offset)
541{
542 struct acpi_battery *battery = seq->private;
543 int result = 0;
544 int update_result = ACPI_BATTERY_NONE_UPDATE;
545 int update = 0;
546
547 acpi_battery_mutex_lock(battery);
548
549 update = (get_seconds() - battery->info_update_time >= update_time);
550 update = (update | acpi_battery_info_update_flag(battery));
551
552 result = acpi_battery_update(battery, update, &update_result);
553 if (result)
554 goto end;
555
556 /* Battery Info (_BIF) */
557
558 if (update_result == ACPI_BATTERY_EASY_UPDATE) {
559 result = acpi_battery_get_info(battery);
560 if (result)
561 goto end;
562 }
563
564 end:
565
566 result = acpi_battery_read_info_print(seq, result);
567
568 acpi_battery_check_result(battery, result);
569
570 acpi_battery_info_update_flag(battery) = result;
571
572 acpi_battery_mutex_unlock(battery);
573
574 return result;
417} 575}
418 576
419static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) 577static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
@@ -421,40 +579,33 @@ static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
421 return single_open(file, acpi_battery_read_info, PDE(inode)->data); 579 return single_open(file, acpi_battery_read_info, PDE(inode)->data);
422} 580}
423 581
424static int acpi_battery_read_state(struct seq_file *seq, void *offset) 582static int acpi_battery_read_state_print(struct seq_file *seq, int result)
425{ 583{
426 int result = 0;
427 struct acpi_battery *battery = seq->private; 584 struct acpi_battery *battery = seq->private;
428 struct acpi_battery_state *bst = NULL; 585 struct acpi_battery_state *bst = NULL;
429 char *units = "?"; 586 char *units = "?";
430 587
431 588 if (result)
432 if (!battery)
433 goto end; 589 goto end;
434 590
435 acpi_battery_check_present(battery); 591 if (acpi_battery_present(battery))
436
437 if (battery->flags.present)
438 seq_printf(seq, "present: yes\n"); 592 seq_printf(seq, "present: yes\n");
439 else { 593 else {
440 seq_printf(seq, "present: no\n"); 594 seq_printf(seq, "present: no\n");
441 goto end; 595 goto end;
442 } 596 }
443 597
444 /* Battery Units */ 598 bst = battery->bst_data.pointer;
445 599 if (!bst) {
446 units = 600 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BST buffer is NULL"));
447 battery->flags. 601 result = -ENODEV;
448 power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
449
450 /* Battery Status (_BST) */
451
452 result = acpi_battery_get_state(battery, &bst);
453 if (result || !bst) {
454 seq_printf(seq, "ERROR: Unable to read battery state\n");
455 goto end; 602 goto end;
456 } 603 }
457 604
605 /* Battery Units */
606
607 units = acpi_battery_power_units(battery);
608
458 if (!(bst->state & 0x04)) 609 if (!(bst->state & 0x04))
459 seq_printf(seq, "capacity state: ok\n"); 610 seq_printf(seq, "capacity state: ok\n");
460 else 611 else
@@ -490,9 +641,49 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
490 (u32) bst->present_voltage); 641 (u32) bst->present_voltage);
491 642
492 end: 643 end:
493 kfree(bst);
494 644
495 return 0; 645 if (result) {
646 seq_printf(seq, "ERROR: Unable to read battery state\n");
647 }
648
649 return result;
650}
651
652static int acpi_battery_read_state(struct seq_file *seq, void *offset)
653{
654 struct acpi_battery *battery = seq->private;
655 int result = 0;
656 int update_result = ACPI_BATTERY_NONE_UPDATE;
657 int update = 0;
658
659 acpi_battery_mutex_lock(battery);
660
661 update = (get_seconds() - battery->state_update_time >= update_time);
662 update = (update | acpi_battery_state_update_flag(battery));
663
664 result = acpi_battery_update(battery, update, &update_result);
665 if (result)
666 goto end;
667
668 /* Battery State (_BST) */
669
670 if (update_result == ACPI_BATTERY_EASY_UPDATE) {
671 result = acpi_battery_get_state(battery);
672 if (result)
673 goto end;
674 }
675
676 end:
677
678 result = acpi_battery_read_state_print(seq, result);
679
680 acpi_battery_check_result(battery, result);
681
682 acpi_battery_state_update_flag(battery) = result;
683
684 acpi_battery_mutex_unlock(battery);
685
686 return result;
496} 687}
497 688
498static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) 689static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
@@ -500,38 +691,72 @@ static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
500 return single_open(file, acpi_battery_read_state, PDE(inode)->data); 691 return single_open(file, acpi_battery_read_state, PDE(inode)->data);
501} 692}
502 693
503static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) 694static int acpi_battery_read_alarm_print(struct seq_file *seq, int result)
504{ 695{
505 struct acpi_battery *battery = seq->private; 696 struct acpi_battery *battery = seq->private;
506 char *units = "?"; 697 char *units = "?";
507 698
508 699 if (result)
509 if (!battery)
510 goto end; 700 goto end;
511 701
512 acpi_battery_check_present(battery); 702 if (!acpi_battery_present(battery)) {
513
514 if (!battery->flags.present) {
515 seq_printf(seq, "present: no\n"); 703 seq_printf(seq, "present: no\n");
516 goto end; 704 goto end;
517 } 705 }
518 706
519 /* Battery Units */ 707 /* Battery Units */
520 708
521 units = 709 units = acpi_battery_power_units(battery);
522 battery->flags.
523 power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
524
525 /* Battery Alarm */
526 710
527 seq_printf(seq, "alarm: "); 711 seq_printf(seq, "alarm: ");
528 if (!battery->alarm) 712 if (!battery->alarm)
529 seq_printf(seq, "unsupported\n"); 713 seq_printf(seq, "unsupported\n");
530 else 714 else
531 seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units); 715 seq_printf(seq, "%lu %sh\n", battery->alarm, units);
532 716
533 end: 717 end:
534 return 0; 718
719 if (result)
720 seq_printf(seq, "ERROR: Unable to read battery alarm\n");
721
722 return result;
723}
724
725static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
726{
727 struct acpi_battery *battery = seq->private;
728 int result = 0;
729 int update_result = ACPI_BATTERY_NONE_UPDATE;
730 int update = 0;
731
732 acpi_battery_mutex_lock(battery);
733
734 update = (get_seconds() - battery->alarm_update_time >= update_time);
735 update = (update | acpi_battery_alarm_update_flag(battery));
736
737 result = acpi_battery_update(battery, update, &update_result);
738 if (result)
739 goto end;
740
741 /* Battery Alarm */
742
743 if (update_result == ACPI_BATTERY_EASY_UPDATE) {
744 result = acpi_battery_get_alarm(battery);
745 if (result)
746 goto end;
747 }
748
749 end:
750
751 result = acpi_battery_read_alarm_print(seq, result);
752
753 acpi_battery_check_result(battery, result);
754
755 acpi_battery_alarm_update_flag(battery) = result;
756
757 acpi_battery_mutex_unlock(battery);
758
759 return result;
535} 760}
536 761
537static ssize_t 762static ssize_t
@@ -543,27 +768,47 @@ acpi_battery_write_alarm(struct file *file,
543 char alarm_string[12] = { '\0' }; 768 char alarm_string[12] = { '\0' };
544 struct seq_file *m = file->private_data; 769 struct seq_file *m = file->private_data;
545 struct acpi_battery *battery = m->private; 770 struct acpi_battery *battery = m->private;
771 int update_result = ACPI_BATTERY_NONE_UPDATE;
546 772
547 773
548 if (!battery || (count > sizeof(alarm_string) - 1)) 774 if (!battery || (count > sizeof(alarm_string) - 1))
549 return -EINVAL; 775 return -EINVAL;
550 776
551 acpi_battery_check_present(battery); 777 acpi_battery_mutex_lock(battery);
552 778
553 if (!battery->flags.present) 779 result = acpi_battery_update(battery, 1, &update_result);
554 return -ENODEV; 780 if (result) {
781 result = -ENODEV;
782 goto end;
783 }
555 784
556 if (copy_from_user(alarm_string, buffer, count)) 785 if (!acpi_battery_present(battery)) {
557 return -EFAULT; 786 result = -ENODEV;
787 goto end;
788 }
789
790 if (copy_from_user(alarm_string, buffer, count)) {
791 result = -EFAULT;
792 goto end;
793 }
558 794
559 alarm_string[count] = '\0'; 795 alarm_string[count] = '\0';
560 796
561 result = acpi_battery_set_alarm(battery, 797 result = acpi_battery_set_alarm(battery,
562 simple_strtoul(alarm_string, NULL, 0)); 798 simple_strtoul(alarm_string, NULL, 0));
563 if (result) 799 if (result)
564 return result; 800 goto end;
801
802 end:
803
804 acpi_battery_check_result(battery, result);
565 805
566 return count; 806 if (!result)
807 result = count;
808
809 acpi_battery_mutex_unlock(battery);
810
811 return result;
567} 812}
568 813
569static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) 814static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
@@ -648,7 +893,6 @@ static int acpi_battery_add_fs(struct acpi_device *device)
648 893
649static int acpi_battery_remove_fs(struct acpi_device *device) 894static int acpi_battery_remove_fs(struct acpi_device *device)
650{ 895{
651
652 if (acpi_device_dir(device)) { 896 if (acpi_device_dir(device)) {
653 remove_proc_entry(ACPI_BATTERY_FILE_ALARM, 897 remove_proc_entry(ACPI_BATTERY_FILE_ALARM,
654 acpi_device_dir(device)); 898 acpi_device_dir(device));
@@ -684,8 +928,11 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
684 case ACPI_BATTERY_NOTIFY_INFO: 928 case ACPI_BATTERY_NOTIFY_INFO:
685 case ACPI_NOTIFY_BUS_CHECK: 929 case ACPI_NOTIFY_BUS_CHECK:
686 case ACPI_NOTIFY_DEVICE_CHECK: 930 case ACPI_NOTIFY_DEVICE_CHECK:
687 acpi_battery_check(battery); 931 acpi_battery_mutex_lock(battery);
688 acpi_bus_generate_event(device, event, battery->flags.present); 932 device = battery->device;
933 acpi_battery_notify_update(battery);
934 acpi_battery_mutex_unlock(battery);
935 acpi_bus_generate_event(device, event, acpi_battery_present(battery));
689 break; 936 break;
690 default: 937 default:
691 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 938 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -702,7 +949,6 @@ static int acpi_battery_add(struct acpi_device *device)
702 acpi_status status = 0; 949 acpi_status status = 0;
703 struct acpi_battery *battery = NULL; 950 struct acpi_battery *battery = NULL;
704 951
705
706 if (!device) 952 if (!device)
707 return -EINVAL; 953 return -EINVAL;
708 954
@@ -710,15 +956,21 @@ static int acpi_battery_add(struct acpi_device *device)
710 if (!battery) 956 if (!battery)
711 return -ENOMEM; 957 return -ENOMEM;
712 958
959 mutex_init(&battery->mutex);
960
961 acpi_battery_mutex_lock(battery);
962
713 battery->device = device; 963 battery->device = device;
714 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); 964 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
715 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); 965 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
716 acpi_driver_data(device) = battery; 966 acpi_driver_data(device) = battery;
717 967
718 result = acpi_battery_check(battery); 968 result = acpi_battery_get_status(battery);
719 if (result) 969 if (result)
720 goto end; 970 goto end;
721 971
972 acpi_battery_init_update_flag(battery) = 1;
973
722 result = acpi_battery_add_fs(device); 974 result = acpi_battery_add_fs(device);
723 if (result) 975 if (result)
724 goto end; 976 goto end;
@@ -727,6 +979,7 @@ static int acpi_battery_add(struct acpi_device *device)
727 ACPI_ALL_NOTIFY, 979 ACPI_ALL_NOTIFY,
728 acpi_battery_notify, battery); 980 acpi_battery_notify, battery);
729 if (ACPI_FAILURE(status)) { 981 if (ACPI_FAILURE(status)) {
982 ACPI_EXCEPTION((AE_INFO, status, "Installing notify handler"));
730 result = -ENODEV; 983 result = -ENODEV;
731 goto end; 984 goto end;
732 } 985 }
@@ -736,11 +989,14 @@ static int acpi_battery_add(struct acpi_device *device)
736 device->status.battery_present ? "present" : "absent"); 989 device->status.battery_present ? "present" : "absent");
737 990
738 end: 991 end:
992
739 if (result) { 993 if (result) {
740 acpi_battery_remove_fs(device); 994 acpi_battery_remove_fs(device);
741 kfree(battery); 995 kfree(battery);
742 } 996 }
743 997
998 acpi_battery_mutex_unlock(battery);
999
744 return result; 1000 return result;
745} 1001}
746 1002
@@ -749,18 +1005,29 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
749 acpi_status status = 0; 1005 acpi_status status = 0;
750 struct acpi_battery *battery = NULL; 1006 struct acpi_battery *battery = NULL;
751 1007
752
753 if (!device || !acpi_driver_data(device)) 1008 if (!device || !acpi_driver_data(device))
754 return -EINVAL; 1009 return -EINVAL;
755 1010
756 battery = acpi_driver_data(device); 1011 battery = acpi_driver_data(device);
757 1012
1013 acpi_battery_mutex_lock(battery);
1014
758 status = acpi_remove_notify_handler(device->handle, 1015 status = acpi_remove_notify_handler(device->handle,
759 ACPI_ALL_NOTIFY, 1016 ACPI_ALL_NOTIFY,
760 acpi_battery_notify); 1017 acpi_battery_notify);
761 1018
762 acpi_battery_remove_fs(device); 1019 acpi_battery_remove_fs(device);
763 1020
1021 if (battery->bif_data.pointer)
1022 kfree(battery->bif_data.pointer);
1023
1024 if (battery->bst_data.pointer)
1025 kfree(battery->bst_data.pointer);
1026
1027 acpi_battery_mutex_unlock(battery);
1028
1029 mutex_destroy(&battery->mutex);
1030
764 kfree(battery); 1031 kfree(battery);
765 1032
766 return 0; 1033 return 0;
@@ -775,7 +1042,10 @@ static int acpi_battery_resume(struct acpi_device *device)
775 return -EINVAL; 1042 return -EINVAL;
776 1043
777 battery = device->driver_data; 1044 battery = device->driver_data;
778 return acpi_battery_check(battery); 1045
1046 acpi_battery_init_update_flag(battery) = 1;
1047
1048 return 0;
779} 1049}
780 1050
781static int __init acpi_battery_init(void) 1051static int __init acpi_battery_init(void)
@@ -800,7 +1070,6 @@ static int __init acpi_battery_init(void)
800 1070
801static void __exit acpi_battery_exit(void) 1071static void __exit acpi_battery_exit(void)
802{ 1072{
803
804 acpi_bus_unregister_driver(&acpi_battery_driver); 1073 acpi_bus_unregister_driver(&acpi_battery_driver);
805 1074
806 acpi_unlock_battery_dir(acpi_battery_dir); 1075 acpi_unlock_battery_dir(acpi_battery_dir);