aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2007-07-22 02:24:31 -0400
committerLen Brown <len.brown@intel.com>2007-07-22 02:24:31 -0400
commit8269cc4e2b0ddcdcb9e7f2034c464ef8613737a1 (patch)
tree6e41103c15f6b73187c635159e4f08b727c5598a /drivers/acpi
parent939ab20152390c8ccccfa6fac0830405ca91d903 (diff)
parent78490d82129f7331d1366737c8704c1c053221a3 (diff)
Pull battery into release branch
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/battery.c673
1 files changed, 438 insertions, 235 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index e64c76c8b726..cad932de383d 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -43,21 +43,30 @@
43#define ACPI_BATTERY_CLASS "battery" 43#define ACPI_BATTERY_CLASS "battery"
44#define ACPI_BATTERY_HID "PNP0C0A" 44#define ACPI_BATTERY_HID "PNP0C0A"
45#define ACPI_BATTERY_DEVICE_NAME "Battery" 45#define ACPI_BATTERY_DEVICE_NAME "Battery"
46#define ACPI_BATTERY_FILE_INFO "info"
47#define ACPI_BATTERY_FILE_STATUS "state"
48#define ACPI_BATTERY_FILE_ALARM "alarm"
49#define ACPI_BATTERY_NOTIFY_STATUS 0x80 46#define ACPI_BATTERY_NOTIFY_STATUS 0x80
50#define ACPI_BATTERY_NOTIFY_INFO 0x81 47#define ACPI_BATTERY_NOTIFY_INFO 0x81
51#define ACPI_BATTERY_UNITS_WATTS "mW" 48#define ACPI_BATTERY_UNITS_WATTS "mW"
52#define ACPI_BATTERY_UNITS_AMPS "mA" 49#define ACPI_BATTERY_UNITS_AMPS "mA"
53 50
54#define _COMPONENT ACPI_BATTERY_COMPONENT 51#define _COMPONENT ACPI_BATTERY_COMPONENT
52
53#define ACPI_BATTERY_UPDATE_TIME 0
54
55#define ACPI_BATTERY_NONE_UPDATE 0
56#define ACPI_BATTERY_EASY_UPDATE 1
57#define ACPI_BATTERY_INIT_UPDATE 2
58
55ACPI_MODULE_NAME("battery"); 59ACPI_MODULE_NAME("battery");
56 60
57MODULE_AUTHOR("Paul Diefenbaugh"); 61MODULE_AUTHOR("Paul Diefenbaugh");
58MODULE_DESCRIPTION("ACPI Battery Driver"); 62MODULE_DESCRIPTION("ACPI Battery Driver");
59MODULE_LICENSE("GPL"); 63MODULE_LICENSE("GPL");
60 64
65static unsigned int update_time = ACPI_BATTERY_UPDATE_TIME;
66
67/* 0 - every time, > 0 - by update_time */
68module_param(update_time, uint, 0644);
69
61extern struct proc_dir_entry *acpi_lock_battery_dir(void); 70extern struct proc_dir_entry *acpi_lock_battery_dir(void);
62extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); 71extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
63 72
@@ -76,7 +85,7 @@ static struct acpi_driver acpi_battery_driver = {
76 }, 85 },
77}; 86};
78 87
79struct acpi_battery_status { 88struct acpi_battery_state {
80 acpi_integer state; 89 acpi_integer state;
81 acpi_integer present_rate; 90 acpi_integer present_rate;
82 acpi_integer remaining_capacity; 91 acpi_integer remaining_capacity;
@@ -99,33 +108,111 @@ struct acpi_battery_info {
99 acpi_string oem_info; 108 acpi_string oem_info;
100}; 109};
101 110
102struct acpi_battery_flags { 111enum acpi_battery_files{
103 u8 present:1; /* Bay occupied? */ 112 ACPI_BATTERY_INFO = 0,
104 u8 power_unit:1; /* 0=watts, 1=apms */ 113 ACPI_BATTERY_STATE,
105 u8 alarm:1; /* _BTP present? */ 114 ACPI_BATTERY_ALARM,
106 u8 reserved:5; 115 ACPI_BATTERY_NUMFILES,
107}; 116};
108 117
109struct acpi_battery_trips { 118struct acpi_battery_flags {
110 unsigned long warning; 119 u8 battery_present_prev;
111 unsigned long low; 120 u8 alarm_present;
121 u8 init_update;
122 u8 update[ACPI_BATTERY_NUMFILES];
123 u8 power_unit;
112}; 124};
113 125
114struct acpi_battery { 126struct acpi_battery {
115 struct acpi_device * device; 127 struct mutex mutex;
128 struct acpi_device *device;
116 struct acpi_battery_flags flags; 129 struct acpi_battery_flags flags;
117 struct acpi_battery_trips trips; 130 struct acpi_buffer bif_data;
131 struct acpi_buffer bst_data;
118 unsigned long alarm; 132 unsigned long alarm;
119 struct acpi_battery_info *info; 133 unsigned long update_time[ACPI_BATTERY_NUMFILES];
120}; 134};
121 135
136inline int acpi_battery_present(struct acpi_battery *battery)
137{
138 return battery->device->status.battery_present;
139}
140inline char *acpi_battery_power_units(struct acpi_battery *battery)
141{
142 if (battery->flags.power_unit)
143 return ACPI_BATTERY_UNITS_AMPS;
144 else
145 return ACPI_BATTERY_UNITS_WATTS;
146}
147
148inline acpi_handle acpi_battery_handle(struct acpi_battery *battery)
149{
150 return battery->device->handle;
151}
152
122/* -------------------------------------------------------------------------- 153/* --------------------------------------------------------------------------
123 Battery Management 154 Battery Management
124 -------------------------------------------------------------------------- */ 155 -------------------------------------------------------------------------- */
125 156
126static int 157static void acpi_battery_check_result(struct acpi_battery *battery, int result)
127acpi_battery_get_info(struct acpi_battery *battery, 158{
128 struct acpi_battery_info **bif) 159 if (!battery)
160 return;
161
162 if (result) {
163 battery->flags.init_update = 1;
164 }
165}
166
167static int acpi_battery_extract_package(struct acpi_battery *battery,
168 union acpi_object *package,
169 struct acpi_buffer *format,
170 struct acpi_buffer *data,
171 char *package_name)
172{
173 acpi_status status = AE_OK;
174 struct acpi_buffer data_null = { 0, NULL };
175
176 status = acpi_extract_package(package, format, &data_null);
177 if (status != AE_BUFFER_OVERFLOW) {
178 ACPI_EXCEPTION((AE_INFO, status, "Extracting size %s",
179 package_name));
180 return -ENODEV;
181 }
182
183 if (data_null.length != data->length) {
184 kfree(data->pointer);
185 data->pointer = kzalloc(data_null.length, GFP_KERNEL);
186 if (!data->pointer) {
187 ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "kzalloc()"));
188 return -ENOMEM;
189 }
190 data->length = data_null.length;
191 }
192
193 status = acpi_extract_package(package, format, data);
194 if (ACPI_FAILURE(status)) {
195 ACPI_EXCEPTION((AE_INFO, status, "Extracting %s",
196 package_name));
197 return -ENODEV;
198 }
199
200 return 0;
201}
202
203static int acpi_battery_get_status(struct acpi_battery *battery)
204{
205 int result = 0;
206
207 result = acpi_bus_get_status(battery->device);
208 if (result) {
209 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "Evaluating _STA"));
210 return -ENODEV;
211 }
212 return result;
213}
214
215static int acpi_battery_get_info(struct acpi_battery *battery)
129{ 216{
130 int result = 0; 217 int result = 0;
131 acpi_status status = 0; 218 acpi_status status = 0;
@@ -133,16 +220,20 @@ acpi_battery_get_info(struct acpi_battery *battery,
133 struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF), 220 struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF),
134 ACPI_BATTERY_FORMAT_BIF 221 ACPI_BATTERY_FORMAT_BIF
135 }; 222 };
136 struct acpi_buffer data = { 0, NULL };
137 union acpi_object *package = NULL; 223 union acpi_object *package = NULL;
224 struct acpi_buffer *data = NULL;
225 struct acpi_battery_info *bif = NULL;
138 226
227 battery->update_time[ACPI_BATTERY_INFO] = get_seconds();
139 228
140 if (!battery || !bif) 229 if (!acpi_battery_present(battery))
141 return -EINVAL; 230 return 0;
142 231
143 /* Evalute _BIF */ 232 /* Evaluate _BIF */
144 233
145 status = acpi_evaluate_object(battery->device->handle, "_BIF", NULL, &buffer); 234 status =
235 acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL,
236 &buffer);
146 if (ACPI_FAILURE(status)) { 237 if (ACPI_FAILURE(status)) {
147 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); 238 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF"));
148 return -ENODEV; 239 return -ENODEV;
@@ -150,41 +241,29 @@ acpi_battery_get_info(struct acpi_battery *battery,
150 241
151 package = buffer.pointer; 242 package = buffer.pointer;
152 243
153 /* Extract Package Data */ 244 data = &battery->bif_data;
154
155 status = acpi_extract_package(package, &format, &data);
156 if (status != AE_BUFFER_OVERFLOW) {
157 ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF"));
158 result = -ENODEV;
159 goto end;
160 }
161 245
162 data.pointer = kzalloc(data.length, GFP_KERNEL); 246 /* Extract Package Data */
163 if (!data.pointer) {
164 result = -ENOMEM;
165 goto end;
166 }
167 247
168 status = acpi_extract_package(package, &format, &data); 248 result =
169 if (ACPI_FAILURE(status)) { 249 acpi_battery_extract_package(battery, package, &format, data,
170 ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF")); 250 "_BIF");
171 kfree(data.pointer); 251 if (result)
172 result = -ENODEV;
173 goto end; 252 goto end;
174 }
175 253
176 end: 254 end:
255
177 kfree(buffer.pointer); 256 kfree(buffer.pointer);
178 257
179 if (!result) 258 if (!result) {
180 (*bif) = data.pointer; 259 bif = data->pointer;
260 battery->flags.power_unit = bif->power_unit;
261 }
181 262
182 return result; 263 return result;
183} 264}
184 265
185static int 266static int acpi_battery_get_state(struct acpi_battery *battery)
186acpi_battery_get_status(struct acpi_battery *battery,
187 struct acpi_battery_status **bst)
188{ 267{
189 int result = 0; 268 int result = 0;
190 acpi_status status = 0; 269 acpi_status status = 0;
@@ -192,16 +271,19 @@ acpi_battery_get_status(struct acpi_battery *battery,
192 struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST), 271 struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST),
193 ACPI_BATTERY_FORMAT_BST 272 ACPI_BATTERY_FORMAT_BST
194 }; 273 };
195 struct acpi_buffer data = { 0, NULL };
196 union acpi_object *package = NULL; 274 union acpi_object *package = NULL;
275 struct acpi_buffer *data = NULL;
197 276
277 battery->update_time[ACPI_BATTERY_STATE] = get_seconds();
198 278
199 if (!battery || !bst) 279 if (!acpi_battery_present(battery))
200 return -EINVAL; 280 return 0;
201 281
202 /* Evalute _BST */ 282 /* Evaluate _BST */
203 283
204 status = acpi_evaluate_object(battery->device->handle, "_BST", NULL, &buffer); 284 status =
285 acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL,
286 &buffer);
205 if (ACPI_FAILURE(status)) { 287 if (ACPI_FAILURE(status)) {
206 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST")); 288 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
207 return -ENODEV; 289 return -ENODEV;
@@ -209,55 +291,49 @@ acpi_battery_get_status(struct acpi_battery *battery,
209 291
210 package = buffer.pointer; 292 package = buffer.pointer;
211 293
212 /* Extract Package Data */ 294 data = &battery->bst_data;
213
214 status = acpi_extract_package(package, &format, &data);
215 if (status != AE_BUFFER_OVERFLOW) {
216 ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST"));
217 result = -ENODEV;
218 goto end;
219 }
220 295
221 data.pointer = kzalloc(data.length, GFP_KERNEL); 296 /* Extract Package Data */
222 if (!data.pointer) {
223 result = -ENOMEM;
224 goto end;
225 }
226 297
227 status = acpi_extract_package(package, &format, &data); 298 result =
228 if (ACPI_FAILURE(status)) { 299 acpi_battery_extract_package(battery, package, &format, data,
229 ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST")); 300 "_BST");
230 kfree(data.pointer); 301 if (result)
231 result = -ENODEV;
232 goto end; 302 goto end;
233 }
234 303
235 end: 304 end:
236 kfree(buffer.pointer); 305 kfree(buffer.pointer);
237 306
238 if (!result)
239 (*bst) = data.pointer;
240
241 return result; 307 return result;
242} 308}
243 309
244static int 310static int acpi_battery_get_alarm(struct acpi_battery *battery)
245acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm) 311{
312 battery->update_time[ACPI_BATTERY_ALARM] = get_seconds();
313
314 return 0;
315}
316
317static int acpi_battery_set_alarm(struct acpi_battery *battery,
318 unsigned long alarm)
246{ 319{
247 acpi_status status = 0; 320 acpi_status status = 0;
248 union acpi_object arg0 = { ACPI_TYPE_INTEGER }; 321 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
249 struct acpi_object_list arg_list = { 1, &arg0 }; 322 struct acpi_object_list arg_list = { 1, &arg0 };
250 323
324 battery->update_time[ACPI_BATTERY_ALARM] = get_seconds();
251 325
252 if (!battery) 326 if (!acpi_battery_present(battery))
253 return -EINVAL; 327 return -ENODEV;
254 328
255 if (!battery->flags.alarm) 329 if (!battery->flags.alarm_present)
256 return -ENODEV; 330 return -ENODEV;
257 331
258 arg0.integer.value = alarm; 332 arg0.integer.value = alarm;
259 333
260 status = acpi_evaluate_object(battery->device->handle, "_BTP", &arg_list, NULL); 334 status =
335 acpi_evaluate_object(acpi_battery_handle(battery), "_BTP",
336 &arg_list, NULL);
261 if (ACPI_FAILURE(status)) 337 if (ACPI_FAILURE(status))
262 return -ENODEV; 338 return -ENODEV;
263 339
@@ -268,65 +344,114 @@ acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm)
268 return 0; 344 return 0;
269} 345}
270 346
271static int acpi_battery_check(struct acpi_battery *battery) 347static int acpi_battery_init_alarm(struct acpi_battery *battery)
272{ 348{
273 int result = 0; 349 int result = 0;
274 acpi_status status = AE_OK; 350 acpi_status status = AE_OK;
275 acpi_handle handle = NULL; 351 acpi_handle handle = NULL;
276 struct acpi_device *device = NULL; 352 struct acpi_battery_info *bif = battery->bif_data.pointer;
277 struct acpi_battery_info *bif = NULL; 353 unsigned long alarm = battery->alarm;
278 354
355 /* See if alarms are supported, and if so, set default */
279 356
280 if (!battery) 357 status = acpi_get_handle(acpi_battery_handle(battery), "_BTP", &handle);
281 return -EINVAL; 358 if (ACPI_SUCCESS(status)) {
282 359 battery->flags.alarm_present = 1;
283 device = battery->device; 360 if (!alarm && bif) {
361 alarm = bif->design_capacity_warning;
362 }
363 result = acpi_battery_set_alarm(battery, alarm);
364 if (result)
365 goto end;
366 } else {
367 battery->flags.alarm_present = 0;
368 }
284 369
285 result = acpi_bus_get_status(device); 370 end:
286 if (result)
287 return result;
288 371
289 /* Insertion? */ 372 return result;
373}
290 374
291 if (!battery->flags.present && device->status.battery_present) { 375static int acpi_battery_init_update(struct acpi_battery *battery)
376{
377 int result = 0;
292 378
293 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n")); 379 result = acpi_battery_get_status(battery);
380 if (result)
381 return result;
294 382
295 /* Evalute _BIF to get certain static information */ 383 battery->flags.battery_present_prev = acpi_battery_present(battery);
296 384
297 result = acpi_battery_get_info(battery, &bif); 385 if (acpi_battery_present(battery)) {
386 result = acpi_battery_get_info(battery);
387 if (result)
388 return result;
389 result = acpi_battery_get_state(battery);
298 if (result) 390 if (result)
299 return result; 391 return result;
300 392
301 battery->flags.power_unit = bif->power_unit; 393 acpi_battery_init_alarm(battery);
302 battery->trips.warning = bif->design_capacity_warning; 394 }
303 battery->trips.low = bif->design_capacity_low; 395
304 kfree(bif); 396 return result;
397}
305 398
306 /* See if alarms are supported, and if so, set default */ 399static int acpi_battery_update(struct acpi_battery *battery,
400 int update, int *update_result_ptr)
401{
402 int result = 0;
403 int update_result = ACPI_BATTERY_NONE_UPDATE;
404
405 if (!acpi_battery_present(battery)) {
406 update = 1;
407 }
307 408
308 status = acpi_get_handle(battery->device->handle, "_BTP", &handle); 409 if (battery->flags.init_update) {
309 if (ACPI_SUCCESS(status)) { 410 result = acpi_battery_init_update(battery);
310 battery->flags.alarm = 1; 411 if (result)
311 acpi_battery_set_alarm(battery, battery->trips.warning); 412 goto end;
413 update_result = ACPI_BATTERY_INIT_UPDATE;
414 } else if (update) {
415 result = acpi_battery_get_status(battery);
416 if (result)
417 goto end;
418 if ((!battery->flags.battery_present_prev & acpi_battery_present(battery))
419 || (battery->flags.battery_present_prev & !acpi_battery_present(battery))) {
420 result = acpi_battery_init_update(battery);
421 if (result)
422 goto end;
423 update_result = ACPI_BATTERY_INIT_UPDATE;
424 } else {
425 update_result = ACPI_BATTERY_EASY_UPDATE;
312 } 426 }
313 } 427 }
314 428
315 /* Removal? */ 429 end:
316 430
317 else if (battery->flags.present && !device->status.battery_present) { 431 battery->flags.init_update = (result != 0);
318 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n"));
319 }
320 432
321 battery->flags.present = device->status.battery_present; 433 *update_result_ptr = update_result;
322 434
323 return result; 435 return result;
324} 436}
325 437
326static void acpi_battery_check_present(struct acpi_battery *battery) 438static void acpi_battery_notify_update(struct acpi_battery *battery)
327{ 439{
328 if (!battery->flags.present) { 440 acpi_battery_get_status(battery);
329 acpi_battery_check(battery); 441
442 if (battery->flags.init_update) {
443 return;
444 }
445
446 if ((!battery->flags.battery_present_prev &
447 acpi_battery_present(battery)) ||
448 (battery->flags.battery_present_prev &
449 !acpi_battery_present(battery))) {
450 battery->flags.init_update = 1;
451 } else {
452 battery->flags.update[ACPI_BATTERY_INFO] = 1;
453 battery->flags.update[ACPI_BATTERY_STATE] = 1;
454 battery->flags.update[ACPI_BATTERY_ALARM] = 1;
330 } 455 }
331} 456}
332 457
@@ -335,37 +460,33 @@ static void acpi_battery_check_present(struct acpi_battery *battery)
335 -------------------------------------------------------------------------- */ 460 -------------------------------------------------------------------------- */
336 461
337static struct proc_dir_entry *acpi_battery_dir; 462static struct proc_dir_entry *acpi_battery_dir;
338static int acpi_battery_read_info(struct seq_file *seq, void *offset) 463
464static int acpi_battery_print_info(struct seq_file *seq, int result)
339{ 465{
340 int result = 0;
341 struct acpi_battery *battery = seq->private; 466 struct acpi_battery *battery = seq->private;
342 struct acpi_battery_info *bif = NULL; 467 struct acpi_battery_info *bif = NULL;
343 char *units = "?"; 468 char *units = "?";
344 469
345 470 if (result)
346 if (!battery)
347 goto end; 471 goto end;
348 472
349 acpi_battery_check_present(battery); 473 if (acpi_battery_present(battery))
350
351 if (battery->flags.present)
352 seq_printf(seq, "present: yes\n"); 474 seq_printf(seq, "present: yes\n");
353 else { 475 else {
354 seq_printf(seq, "present: no\n"); 476 seq_printf(seq, "present: no\n");
355 goto end; 477 goto end;
356 } 478 }
357 479
358 /* Battery Info (_BIF) */ 480 bif = battery->bif_data.pointer;
359 481 if (!bif) {
360 result = acpi_battery_get_info(battery, &bif); 482 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BIF buffer is NULL"));
361 if (result || !bif) { 483 result = -ENODEV;
362 seq_printf(seq, "ERROR: Unable to read battery information\n");
363 goto end; 484 goto end;
364 } 485 }
365 486
366 units = 487 /* Battery Units */
367 bif-> 488
368 power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS; 489 units = acpi_battery_power_units(battery);
369 490
370 if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN) 491 if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
371 seq_printf(seq, "design capacity: unknown\n"); 492 seq_printf(seq, "design capacity: unknown\n");
@@ -396,7 +517,6 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
396 else 517 else
397 seq_printf(seq, "design voltage: %d mV\n", 518 seq_printf(seq, "design voltage: %d mV\n",
398 (u32) bif->design_voltage); 519 (u32) bif->design_voltage);
399
400 seq_printf(seq, "design capacity warning: %d %sh\n", 520 seq_printf(seq, "design capacity warning: %d %sh\n",
401 (u32) bif->design_capacity_warning, units); 521 (u32) bif->design_capacity_warning, units);
402 seq_printf(seq, "design capacity low: %d %sh\n", 522 seq_printf(seq, "design capacity low: %d %sh\n",
@@ -411,50 +531,40 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset)
411 seq_printf(seq, "OEM info: %s\n", bif->oem_info); 531 seq_printf(seq, "OEM info: %s\n", bif->oem_info);
412 532
413 end: 533 end:
414 kfree(bif);
415 534
416 return 0; 535 if (result)
417} 536 seq_printf(seq, "ERROR: Unable to read battery info\n");
418 537
419static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) 538 return result;
420{
421 return single_open(file, acpi_battery_read_info, PDE(inode)->data);
422} 539}
423 540
424static int acpi_battery_read_state(struct seq_file *seq, void *offset) 541static int acpi_battery_print_state(struct seq_file *seq, int result)
425{ 542{
426 int result = 0;
427 struct acpi_battery *battery = seq->private; 543 struct acpi_battery *battery = seq->private;
428 struct acpi_battery_status *bst = NULL; 544 struct acpi_battery_state *bst = NULL;
429 char *units = "?"; 545 char *units = "?";
430 546
431 547 if (result)
432 if (!battery)
433 goto end; 548 goto end;
434 549
435 acpi_battery_check_present(battery); 550 if (acpi_battery_present(battery))
436
437 if (battery->flags.present)
438 seq_printf(seq, "present: yes\n"); 551 seq_printf(seq, "present: yes\n");
439 else { 552 else {
440 seq_printf(seq, "present: no\n"); 553 seq_printf(seq, "present: no\n");
441 goto end; 554 goto end;
442 } 555 }
443 556
444 /* Battery Units */ 557 bst = battery->bst_data.pointer;
445 558 if (!bst) {
446 units = 559 ACPI_EXCEPTION((AE_INFO, AE_ERROR, "BST buffer is NULL"));
447 battery->flags. 560 result = -ENODEV;
448 power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
449
450 /* Battery Status (_BST) */
451
452 result = acpi_battery_get_status(battery, &bst);
453 if (result || !bst) {
454 seq_printf(seq, "ERROR: Unable to read battery status\n");
455 goto end; 561 goto end;
456 } 562 }
457 563
564 /* Battery Units */
565
566 units = acpi_battery_power_units(battery);
567
458 if (!(bst->state & 0x04)) 568 if (!(bst->state & 0x04))
459 seq_printf(seq, "capacity state: ok\n"); 569 seq_printf(seq, "capacity state: ok\n");
460 else 570 else
@@ -490,48 +600,43 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset)
490 (u32) bst->present_voltage); 600 (u32) bst->present_voltage);
491 601
492 end: 602 end:
493 kfree(bst);
494 603
495 return 0; 604 if (result) {
496} 605 seq_printf(seq, "ERROR: Unable to read battery state\n");
606 }
497 607
498static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) 608 return result;
499{
500 return single_open(file, acpi_battery_read_state, PDE(inode)->data);
501} 609}
502 610
503static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) 611static int acpi_battery_print_alarm(struct seq_file *seq, int result)
504{ 612{
505 struct acpi_battery *battery = seq->private; 613 struct acpi_battery *battery = seq->private;
506 char *units = "?"; 614 char *units = "?";
507 615
508 616 if (result)
509 if (!battery)
510 goto end; 617 goto end;
511 618
512 acpi_battery_check_present(battery); 619 if (!acpi_battery_present(battery)) {
513
514 if (!battery->flags.present) {
515 seq_printf(seq, "present: no\n"); 620 seq_printf(seq, "present: no\n");
516 goto end; 621 goto end;
517 } 622 }
518 623
519 /* Battery Units */ 624 /* Battery Units */
520 625
521 units = 626 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 627
527 seq_printf(seq, "alarm: "); 628 seq_printf(seq, "alarm: ");
528 if (!battery->alarm) 629 if (!battery->alarm)
529 seq_printf(seq, "unsupported\n"); 630 seq_printf(seq, "unsupported\n");
530 else 631 else
531 seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units); 632 seq_printf(seq, "%lu %sh\n", battery->alarm, units);
532 633
533 end: 634 end:
534 return 0; 635
636 if (result)
637 seq_printf(seq, "ERROR: Unable to read battery alarm\n");
638
639 return result;
535} 640}
536 641
537static ssize_t 642static ssize_t
@@ -543,27 +648,113 @@ acpi_battery_write_alarm(struct file *file,
543 char alarm_string[12] = { '\0' }; 648 char alarm_string[12] = { '\0' };
544 struct seq_file *m = file->private_data; 649 struct seq_file *m = file->private_data;
545 struct acpi_battery *battery = m->private; 650 struct acpi_battery *battery = m->private;
546 651 int update_result = ACPI_BATTERY_NONE_UPDATE;
547 652
548 if (!battery || (count > sizeof(alarm_string) - 1)) 653 if (!battery || (count > sizeof(alarm_string) - 1))
549 return -EINVAL; 654 return -EINVAL;
550 655
551 acpi_battery_check_present(battery); 656 mutex_lock(&battery->mutex);
552 657
553 if (!battery->flags.present) 658 result = acpi_battery_update(battery, 1, &update_result);
554 return -ENODEV; 659 if (result) {
660 result = -ENODEV;
661 goto end;
662 }
663
664 if (!acpi_battery_present(battery)) {
665 result = -ENODEV;
666 goto end;
667 }
555 668
556 if (copy_from_user(alarm_string, buffer, count)) 669 if (copy_from_user(alarm_string, buffer, count)) {
557 return -EFAULT; 670 result = -EFAULT;
671 goto end;
672 }
558 673
559 alarm_string[count] = '\0'; 674 alarm_string[count] = '\0';
560 675
561 result = acpi_battery_set_alarm(battery, 676 result = acpi_battery_set_alarm(battery,
562 simple_strtoul(alarm_string, NULL, 0)); 677 simple_strtoul(alarm_string, NULL, 0));
563 if (result) 678 if (result)
564 return result; 679 goto end;
680
681 end:
565 682
566 return count; 683 acpi_battery_check_result(battery, result);
684
685 if (!result)
686 result = count;
687
688 mutex_unlock(&battery->mutex);
689
690 return result;
691}
692
693typedef int(*print_func)(struct seq_file *seq, int result);
694typedef int(*get_func)(struct acpi_battery *battery);
695
696static struct acpi_read_mux {
697 print_func print;
698 get_func get;
699} acpi_read_funcs[ACPI_BATTERY_NUMFILES] = {
700 {.get = acpi_battery_get_info, .print = acpi_battery_print_info},
701 {.get = acpi_battery_get_state, .print = acpi_battery_print_state},
702 {.get = acpi_battery_get_alarm, .print = acpi_battery_print_alarm},
703};
704
705static int acpi_battery_read(int fid, struct seq_file *seq)
706{
707 struct acpi_battery *battery = seq->private;
708 int result = 0;
709 int update_result = ACPI_BATTERY_NONE_UPDATE;
710 int update = 0;
711
712 mutex_lock(&battery->mutex);
713
714 update = (get_seconds() - battery->update_time[fid] >= update_time);
715 update = (update | battery->flags.update[fid]);
716
717 result = acpi_battery_update(battery, update, &update_result);
718 if (result)
719 goto end;
720
721 if (update_result == ACPI_BATTERY_EASY_UPDATE) {
722 result = acpi_read_funcs[fid].get(battery);
723 if (result)
724 goto end;
725 }
726
727 end:
728 result = acpi_read_funcs[fid].print(seq, result);
729 acpi_battery_check_result(battery, result);
730 battery->flags.update[fid] = result;
731 mutex_unlock(&battery->mutex);
732 return result;
733}
734
735static int acpi_battery_read_info(struct seq_file *seq, void *offset)
736{
737 return acpi_battery_read(ACPI_BATTERY_INFO, seq);
738}
739
740static int acpi_battery_read_state(struct seq_file *seq, void *offset)
741{
742 return acpi_battery_read(ACPI_BATTERY_STATE, seq);
743}
744
745static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
746{
747 return acpi_battery_read(ACPI_BATTERY_ALARM, seq);
748}
749
750static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
751{
752 return single_open(file, acpi_battery_read_info, PDE(inode)->data);
753}
754
755static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
756{
757 return single_open(file, acpi_battery_read_state, PDE(inode)->data);
567} 758}
568 759
569static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file) 760static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
@@ -571,35 +762,51 @@ static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
571 return single_open(file, acpi_battery_read_alarm, PDE(inode)->data); 762 return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
572} 763}
573 764
574static const struct file_operations acpi_battery_info_ops = { 765static struct battery_file {
766 struct file_operations ops;
767 mode_t mode;
768 char *name;
769} acpi_battery_file[] = {
770 {
771 .name = "info",
772 .mode = S_IRUGO,
773 .ops = {
575 .open = acpi_battery_info_open_fs, 774 .open = acpi_battery_info_open_fs,
576 .read = seq_read, 775 .read = seq_read,
577 .llseek = seq_lseek, 776 .llseek = seq_lseek,
578 .release = single_release, 777 .release = single_release,
579 .owner = THIS_MODULE, 778 .owner = THIS_MODULE,
580}; 779 },
581 780 },
582static const struct file_operations acpi_battery_state_ops = { 781 {
782 .name = "state",
783 .mode = S_IRUGO,
784 .ops = {
583 .open = acpi_battery_state_open_fs, 785 .open = acpi_battery_state_open_fs,
584 .read = seq_read, 786 .read = seq_read,
585 .llseek = seq_lseek, 787 .llseek = seq_lseek,
586 .release = single_release, 788 .release = single_release,
587 .owner = THIS_MODULE, 789 .owner = THIS_MODULE,
588}; 790 },
589 791 },
590static const struct file_operations acpi_battery_alarm_ops = { 792 {
793 .name = "alarm",
794 .mode = S_IFREG | S_IRUGO | S_IWUSR,
795 .ops = {
591 .open = acpi_battery_alarm_open_fs, 796 .open = acpi_battery_alarm_open_fs,
592 .read = seq_read, 797 .read = seq_read,
593 .write = acpi_battery_write_alarm, 798 .write = acpi_battery_write_alarm,
594 .llseek = seq_lseek, 799 .llseek = seq_lseek,
595 .release = single_release, 800 .release = single_release,
596 .owner = THIS_MODULE, 801 .owner = THIS_MODULE,
802 },
803 },
597}; 804};
598 805
599static int acpi_battery_add_fs(struct acpi_device *device) 806static int acpi_battery_add_fs(struct acpi_device *device)
600{ 807{
601 struct proc_dir_entry *entry = NULL; 808 struct proc_dir_entry *entry = NULL;
602 809 int i;
603 810
604 if (!acpi_device_dir(device)) { 811 if (!acpi_device_dir(device)) {
605 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), 812 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
@@ -609,38 +816,16 @@ static int acpi_battery_add_fs(struct acpi_device *device)
609 acpi_device_dir(device)->owner = THIS_MODULE; 816 acpi_device_dir(device)->owner = THIS_MODULE;
610 } 817 }
611 818
612 /* 'info' [R] */ 819 for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
613 entry = create_proc_entry(ACPI_BATTERY_FILE_INFO, 820 entry = create_proc_entry(acpi_battery_file[i].name,
614 S_IRUGO, acpi_device_dir(device)); 821 acpi_battery_file[i].mode, acpi_device_dir(device));
615 if (!entry) 822 if (!entry)
616 return -ENODEV; 823 return -ENODEV;
617 else { 824 else {
618 entry->proc_fops = &acpi_battery_info_ops; 825 entry->proc_fops = &acpi_battery_file[i].ops;
619 entry->data = acpi_driver_data(device); 826 entry->data = acpi_driver_data(device);
620 entry->owner = THIS_MODULE; 827 entry->owner = THIS_MODULE;
621 } 828 }
622
623 /* 'status' [R] */
624 entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS,
625 S_IRUGO, acpi_device_dir(device));
626 if (!entry)
627 return -ENODEV;
628 else {
629 entry->proc_fops = &acpi_battery_state_ops;
630 entry->data = acpi_driver_data(device);
631 entry->owner = THIS_MODULE;
632 }
633
634 /* 'alarm' [R/W] */
635 entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM,
636 S_IFREG | S_IRUGO | S_IWUSR,
637 acpi_device_dir(device));
638 if (!entry)
639 return -ENODEV;
640 else {
641 entry->proc_fops = &acpi_battery_alarm_ops;
642 entry->data = acpi_driver_data(device);
643 entry->owner = THIS_MODULE;
644 } 829 }
645 830
646 return 0; 831 return 0;
@@ -648,15 +833,12 @@ static int acpi_battery_add_fs(struct acpi_device *device)
648 833
649static int acpi_battery_remove_fs(struct acpi_device *device) 834static int acpi_battery_remove_fs(struct acpi_device *device)
650{ 835{
651 836 int i;
652 if (acpi_device_dir(device)) { 837 if (acpi_device_dir(device)) {
653 remove_proc_entry(ACPI_BATTERY_FILE_ALARM, 838 for (i = 0; i < ACPI_BATTERY_NUMFILES; ++i) {
839 remove_proc_entry(acpi_battery_file[i].name,
654 acpi_device_dir(device)); 840 acpi_device_dir(device));
655 remove_proc_entry(ACPI_BATTERY_FILE_STATUS, 841 }
656 acpi_device_dir(device));
657 remove_proc_entry(ACPI_BATTERY_FILE_INFO,
658 acpi_device_dir(device));
659
660 remove_proc_entry(acpi_device_bid(device), acpi_battery_dir); 842 remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
661 acpi_device_dir(device) = NULL; 843 acpi_device_dir(device) = NULL;
662 } 844 }
@@ -673,7 +855,6 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
673 struct acpi_battery *battery = data; 855 struct acpi_battery *battery = data;
674 struct acpi_device *device = NULL; 856 struct acpi_device *device = NULL;
675 857
676
677 if (!battery) 858 if (!battery)
678 return; 859 return;
679 860
@@ -684,8 +865,10 @@ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
684 case ACPI_BATTERY_NOTIFY_INFO: 865 case ACPI_BATTERY_NOTIFY_INFO:
685 case ACPI_NOTIFY_BUS_CHECK: 866 case ACPI_NOTIFY_BUS_CHECK:
686 case ACPI_NOTIFY_DEVICE_CHECK: 867 case ACPI_NOTIFY_DEVICE_CHECK:
687 acpi_battery_check(battery); 868 device = battery->device;
688 acpi_bus_generate_event(device, event, battery->flags.present); 869 acpi_battery_notify_update(battery);
870 acpi_bus_generate_event(device, event,
871 acpi_battery_present(battery));
689 break; 872 break;
690 default: 873 default:
691 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 874 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
@@ -702,7 +885,6 @@ static int acpi_battery_add(struct acpi_device *device)
702 acpi_status status = 0; 885 acpi_status status = 0;
703 struct acpi_battery *battery = NULL; 886 struct acpi_battery *battery = NULL;
704 887
705
706 if (!device) 888 if (!device)
707 return -EINVAL; 889 return -EINVAL;
708 890
@@ -710,15 +892,21 @@ static int acpi_battery_add(struct acpi_device *device)
710 if (!battery) 892 if (!battery)
711 return -ENOMEM; 893 return -ENOMEM;
712 894
895 mutex_init(&battery->mutex);
896
897 mutex_lock(&battery->mutex);
898
713 battery->device = device; 899 battery->device = device;
714 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); 900 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
715 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); 901 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
716 acpi_driver_data(device) = battery; 902 acpi_driver_data(device) = battery;
717 903
718 result = acpi_battery_check(battery); 904 result = acpi_battery_get_status(battery);
719 if (result) 905 if (result)
720 goto end; 906 goto end;
721 907
908 battery->flags.init_update = 1;
909
722 result = acpi_battery_add_fs(device); 910 result = acpi_battery_add_fs(device);
723 if (result) 911 if (result)
724 goto end; 912 goto end;
@@ -727,6 +915,7 @@ static int acpi_battery_add(struct acpi_device *device)
727 ACPI_ALL_NOTIFY, 915 ACPI_ALL_NOTIFY,
728 acpi_battery_notify, battery); 916 acpi_battery_notify, battery);
729 if (ACPI_FAILURE(status)) { 917 if (ACPI_FAILURE(status)) {
918 ACPI_EXCEPTION((AE_INFO, status, "Installing notify handler"));
730 result = -ENODEV; 919 result = -ENODEV;
731 goto end; 920 goto end;
732 } 921 }
@@ -736,11 +925,14 @@ static int acpi_battery_add(struct acpi_device *device)
736 device->status.battery_present ? "present" : "absent"); 925 device->status.battery_present ? "present" : "absent");
737 926
738 end: 927 end:
928
739 if (result) { 929 if (result) {
740 acpi_battery_remove_fs(device); 930 acpi_battery_remove_fs(device);
741 kfree(battery); 931 kfree(battery);
742 } 932 }
743 933
934 mutex_unlock(&battery->mutex);
935
744 return result; 936 return result;
745} 937}
746 938
@@ -749,18 +941,27 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
749 acpi_status status = 0; 941 acpi_status status = 0;
750 struct acpi_battery *battery = NULL; 942 struct acpi_battery *battery = NULL;
751 943
752
753 if (!device || !acpi_driver_data(device)) 944 if (!device || !acpi_driver_data(device))
754 return -EINVAL; 945 return -EINVAL;
755 946
756 battery = acpi_driver_data(device); 947 battery = acpi_driver_data(device);
757 948
949 mutex_lock(&battery->mutex);
950
758 status = acpi_remove_notify_handler(device->handle, 951 status = acpi_remove_notify_handler(device->handle,
759 ACPI_ALL_NOTIFY, 952 ACPI_ALL_NOTIFY,
760 acpi_battery_notify); 953 acpi_battery_notify);
761 954
762 acpi_battery_remove_fs(device); 955 acpi_battery_remove_fs(device);
763 956
957 kfree(battery->bif_data.pointer);
958
959 kfree(battery->bst_data.pointer);
960
961 mutex_unlock(&battery->mutex);
962
963 mutex_destroy(&battery->mutex);
964
764 kfree(battery); 965 kfree(battery);
765 966
766 return 0; 967 return 0;
@@ -775,7 +976,10 @@ static int acpi_battery_resume(struct acpi_device *device)
775 return -EINVAL; 976 return -EINVAL;
776 977
777 battery = device->driver_data; 978 battery = device->driver_data;
778 return acpi_battery_check(battery); 979
980 battery->flags.init_update = 1;
981
982 return 0;
779} 983}
780 984
781static int __init acpi_battery_init(void) 985static int __init acpi_battery_init(void)
@@ -800,7 +1004,6 @@ static int __init acpi_battery_init(void)
800 1004
801static void __exit acpi_battery_exit(void) 1005static void __exit acpi_battery_exit(void)
802{ 1006{
803
804 acpi_bus_unregister_driver(&acpi_battery_driver); 1007 acpi_bus_unregister_driver(&acpi_battery_driver);
805 1008
806 acpi_unlock_battery_dir(acpi_battery_dir); 1009 acpi_unlock_battery_dir(acpi_battery_dir);