Pull bugzilla-7200 into release branch
[pandora-kernel.git] / drivers / acpi / battery.c
1 /*
2  *  acpi_battery.c - ACPI Battery Driver ($Revision: 37 $)
3  *
4  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
5  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
6  *
7  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or (at
12  *  your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful, but
15  *  WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *  General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License along
20  *  with this program; if not, write to the Free Software Foundation, Inc.,
21  *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
22  *
23  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24  */
25
26 #include <linux/kernel.h>
27 #include <linux/module.h>
28 #include <linux/init.h>
29 #include <linux/types.h>
30 #include <linux/proc_fs.h>
31 #include <linux/seq_file.h>
32 #include <asm/uaccess.h>
33
34 #include <acpi/acpi_bus.h>
35 #include <acpi/acpi_drivers.h>
36
37 #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
38
39 #define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS"
40 #define ACPI_BATTERY_FORMAT_BST "NNNN"
41
42 #define ACPI_BATTERY_COMPONENT          0x00040000
43 #define ACPI_BATTERY_CLASS              "battery"
44 #define ACPI_BATTERY_HID                "PNP0C0A"
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
50 #define ACPI_BATTERY_NOTIFY_INFO        0x81
51 #define ACPI_BATTERY_UNITS_WATTS        "mW"
52 #define ACPI_BATTERY_UNITS_AMPS         "mA"
53
54 #define _COMPONENT              ACPI_BATTERY_COMPONENT
55 ACPI_MODULE_NAME("battery");
56
57 MODULE_AUTHOR("Paul Diefenbaugh");
58 MODULE_DESCRIPTION("ACPI Battery Driver");
59 MODULE_LICENSE("GPL");
60
61 extern struct proc_dir_entry *acpi_lock_battery_dir(void);
62 extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
63
64 static int acpi_battery_add(struct acpi_device *device);
65 static int acpi_battery_remove(struct acpi_device *device, int type);
66 static int acpi_battery_resume(struct acpi_device *device);
67
68 static struct acpi_driver acpi_battery_driver = {
69         .name = "battery",
70         .class = ACPI_BATTERY_CLASS,
71         .ids = ACPI_BATTERY_HID,
72         .ops = {
73                 .add = acpi_battery_add,
74                 .resume = acpi_battery_resume,
75                 .remove = acpi_battery_remove,
76                 },
77 };
78
79 struct acpi_battery_status {
80         acpi_integer state;
81         acpi_integer present_rate;
82         acpi_integer remaining_capacity;
83         acpi_integer present_voltage;
84 };
85
86 struct acpi_battery_info {
87         acpi_integer power_unit;
88         acpi_integer design_capacity;
89         acpi_integer last_full_capacity;
90         acpi_integer battery_technology;
91         acpi_integer design_voltage;
92         acpi_integer design_capacity_warning;
93         acpi_integer design_capacity_low;
94         acpi_integer battery_capacity_granularity_1;
95         acpi_integer battery_capacity_granularity_2;
96         acpi_string model_number;
97         acpi_string serial_number;
98         acpi_string battery_type;
99         acpi_string oem_info;
100 };
101
102 struct acpi_battery_flags {
103         u8 present:1;           /* Bay occupied? */
104         u8 power_unit:1;        /* 0=watts, 1=apms */
105         u8 alarm:1;             /* _BTP present? */
106         u8 reserved:5;
107 };
108
109 struct acpi_battery_trips {
110         unsigned long warning;
111         unsigned long low;
112 };
113
114 struct acpi_battery {
115         struct acpi_device * device;
116         struct acpi_battery_flags flags;
117         struct acpi_battery_trips trips;
118         unsigned long alarm;
119         struct acpi_battery_info *info;
120 };
121
122 /* --------------------------------------------------------------------------
123                                Battery Management
124    -------------------------------------------------------------------------- */
125
126 static int
127 acpi_battery_get_info(struct acpi_battery *battery,
128                       struct acpi_battery_info **bif)
129 {
130         int result = 0;
131         acpi_status status = 0;
132         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
133         struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF),
134                 ACPI_BATTERY_FORMAT_BIF
135         };
136         struct acpi_buffer data = { 0, NULL };
137         union acpi_object *package = NULL;
138
139
140         if (!battery || !bif)
141                 return -EINVAL;
142
143         /* Evalute _BIF */
144
145         status = acpi_evaluate_object(battery->device->handle, "_BIF", NULL, &buffer);
146         if (ACPI_FAILURE(status)) {
147                 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF"));
148                 return -ENODEV;
149         }
150
151         package = buffer.pointer;
152
153         /* Extract Package 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
162         data.pointer = kzalloc(data.length, GFP_KERNEL);
163         if (!data.pointer) {
164                 result = -ENOMEM;
165                 goto end;
166         }
167
168         status = acpi_extract_package(package, &format, &data);
169         if (ACPI_FAILURE(status)) {
170                 ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF"));
171                 kfree(data.pointer);
172                 result = -ENODEV;
173                 goto end;
174         }
175
176       end:
177         kfree(buffer.pointer);
178
179         if (!result)
180                 (*bif) = data.pointer;
181
182         return result;
183 }
184
185 static int
186 acpi_battery_get_status(struct acpi_battery *battery,
187                         struct acpi_battery_status **bst)
188 {
189         int result = 0;
190         acpi_status status = 0;
191         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
192         struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST),
193                 ACPI_BATTERY_FORMAT_BST
194         };
195         struct acpi_buffer data = { 0, NULL };
196         union acpi_object *package = NULL;
197
198
199         if (!battery || !bst)
200                 return -EINVAL;
201
202         /* Evalute _BST */
203
204         status = acpi_evaluate_object(battery->device->handle, "_BST", NULL, &buffer);
205         if (ACPI_FAILURE(status)) {
206                 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
207                 return -ENODEV;
208         }
209
210         package = buffer.pointer;
211
212         /* Extract Package 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
221         data.pointer = kzalloc(data.length, GFP_KERNEL);
222         if (!data.pointer) {
223                 result = -ENOMEM;
224                 goto end;
225         }
226
227         status = acpi_extract_package(package, &format, &data);
228         if (ACPI_FAILURE(status)) {
229                 ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST"));
230                 kfree(data.pointer);
231                 result = -ENODEV;
232                 goto end;
233         }
234
235       end:
236         kfree(buffer.pointer);
237
238         if (!result)
239                 (*bst) = data.pointer;
240
241         return result;
242 }
243
244 static int
245 acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm)
246 {
247         acpi_status status = 0;
248         union acpi_object arg0 = { ACPI_TYPE_INTEGER };
249         struct acpi_object_list arg_list = { 1, &arg0 };
250
251
252         if (!battery)
253                 return -EINVAL;
254
255         if (!battery->flags.alarm)
256                 return -ENODEV;
257
258         arg0.integer.value = alarm;
259
260         status = acpi_evaluate_object(battery->device->handle, "_BTP", &arg_list, NULL);
261         if (ACPI_FAILURE(status))
262                 return -ENODEV;
263
264         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", (u32) alarm));
265
266         battery->alarm = alarm;
267
268         return 0;
269 }
270
271 static int acpi_battery_check(struct acpi_battery *battery)
272 {
273         int result = 0;
274         acpi_status status = AE_OK;
275         acpi_handle handle = NULL;
276         struct acpi_device *device = NULL;
277         struct acpi_battery_info *bif = NULL;
278
279
280         if (!battery)
281                 return -EINVAL;
282
283         device = battery->device;
284
285         result = acpi_bus_get_status(device);
286         if (result)
287                 return result;
288
289         /* Insertion? */
290
291         if (!battery->flags.present && device->status.battery_present) {
292
293                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n"));
294
295                 /* Evalute _BIF to get certain static information */
296
297                 result = acpi_battery_get_info(battery, &bif);
298                 if (result)
299                         return result;
300
301                 battery->flags.power_unit = bif->power_unit;
302                 battery->trips.warning = bif->design_capacity_warning;
303                 battery->trips.low = bif->design_capacity_low;
304                 kfree(bif);
305
306                 /* See if alarms are supported, and if so, set default */
307
308                 status = acpi_get_handle(battery->device->handle, "_BTP", &handle);
309                 if (ACPI_SUCCESS(status)) {
310                         battery->flags.alarm = 1;
311                         acpi_battery_set_alarm(battery, battery->trips.warning);
312                 }
313         }
314
315         /* Removal? */
316
317         else if (battery->flags.present && !device->status.battery_present) {
318                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n"));
319         }
320
321         battery->flags.present = device->status.battery_present;
322
323         return result;
324 }
325
326 static void acpi_battery_check_present(struct acpi_battery *battery)
327 {
328         if (!battery->flags.present) {
329                 acpi_battery_check(battery);
330         }
331 }
332
333 /* --------------------------------------------------------------------------
334                               FS Interface (/proc)
335    -------------------------------------------------------------------------- */
336
337 static struct proc_dir_entry *acpi_battery_dir;
338 static int acpi_battery_read_info(struct seq_file *seq, void *offset)
339 {
340         int result = 0;
341         struct acpi_battery *battery = seq->private;
342         struct acpi_battery_info *bif = NULL;
343         char *units = "?";
344
345
346         if (!battery)
347                 goto end;
348
349         acpi_battery_check_present(battery);
350
351         if (battery->flags.present)
352                 seq_printf(seq, "present:                 yes\n");
353         else {
354                 seq_printf(seq, "present:                 no\n");
355                 goto end;
356         }
357
358         /* Battery Info (_BIF) */
359
360         result = acpi_battery_get_info(battery, &bif);
361         if (result || !bif) {
362                 seq_printf(seq, "ERROR: Unable to read battery information\n");
363                 goto end;
364         }
365
366         units =
367             bif->
368             power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
369
370         if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
371                 seq_printf(seq, "design capacity:         unknown\n");
372         else
373                 seq_printf(seq, "design capacity:         %d %sh\n",
374                            (u32) bif->design_capacity, units);
375
376         if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
377                 seq_printf(seq, "last full capacity:      unknown\n");
378         else
379                 seq_printf(seq, "last full capacity:      %d %sh\n",
380                            (u32) bif->last_full_capacity, units);
381
382         switch ((u32) bif->battery_technology) {
383         case 0:
384                 seq_printf(seq, "battery technology:      non-rechargeable\n");
385                 break;
386         case 1:
387                 seq_printf(seq, "battery technology:      rechargeable\n");
388                 break;
389         default:
390                 seq_printf(seq, "battery technology:      unknown\n");
391                 break;
392         }
393
394         if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
395                 seq_printf(seq, "design voltage:          unknown\n");
396         else
397                 seq_printf(seq, "design voltage:          %d mV\n",
398                            (u32) bif->design_voltage);
399
400         seq_printf(seq, "design capacity warning: %d %sh\n",
401                    (u32) bif->design_capacity_warning, units);
402         seq_printf(seq, "design capacity low:     %d %sh\n",
403                    (u32) bif->design_capacity_low, units);
404         seq_printf(seq, "capacity granularity 1:  %d %sh\n",
405                    (u32) bif->battery_capacity_granularity_1, units);
406         seq_printf(seq, "capacity granularity 2:  %d %sh\n",
407                    (u32) bif->battery_capacity_granularity_2, units);
408         seq_printf(seq, "model number:            %s\n", bif->model_number);
409         seq_printf(seq, "serial number:           %s\n", bif->serial_number);
410         seq_printf(seq, "battery type:            %s\n", bif->battery_type);
411         seq_printf(seq, "OEM info:                %s\n", bif->oem_info);
412
413       end:
414         kfree(bif);
415
416         return 0;
417 }
418
419 static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
420 {
421         return single_open(file, acpi_battery_read_info, PDE(inode)->data);
422 }
423
424 static int acpi_battery_read_state(struct seq_file *seq, void *offset)
425 {
426         int result = 0;
427         struct acpi_battery *battery = seq->private;
428         struct acpi_battery_status *bst = NULL;
429         char *units = "?";
430
431
432         if (!battery)
433                 goto end;
434
435         acpi_battery_check_present(battery);
436
437         if (battery->flags.present)
438                 seq_printf(seq, "present:                 yes\n");
439         else {
440                 seq_printf(seq, "present:                 no\n");
441                 goto end;
442         }
443
444         /* Battery Units */
445
446         units =
447             battery->flags.
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;
456         }
457
458         if (!(bst->state & 0x04))
459                 seq_printf(seq, "capacity state:          ok\n");
460         else
461                 seq_printf(seq, "capacity state:          critical\n");
462
463         if ((bst->state & 0x01) && (bst->state & 0x02)) {
464                 seq_printf(seq,
465                            "charging state:          charging/discharging\n");
466         } else if (bst->state & 0x01)
467                 seq_printf(seq, "charging state:          discharging\n");
468         else if (bst->state & 0x02)
469                 seq_printf(seq, "charging state:          charging\n");
470         else {
471                 seq_printf(seq, "charging state:          charged\n");
472         }
473
474         if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN)
475                 seq_printf(seq, "present rate:            unknown\n");
476         else
477                 seq_printf(seq, "present rate:            %d %s\n",
478                            (u32) bst->present_rate, units);
479
480         if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
481                 seq_printf(seq, "remaining capacity:      unknown\n");
482         else
483                 seq_printf(seq, "remaining capacity:      %d %sh\n",
484                            (u32) bst->remaining_capacity, units);
485
486         if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
487                 seq_printf(seq, "present voltage:         unknown\n");
488         else
489                 seq_printf(seq, "present voltage:         %d mV\n",
490                            (u32) bst->present_voltage);
491
492       end:
493         kfree(bst);
494
495         return 0;
496 }
497
498 static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
499 {
500         return single_open(file, acpi_battery_read_state, PDE(inode)->data);
501 }
502
503 static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
504 {
505         struct acpi_battery *battery = seq->private;
506         char *units = "?";
507
508
509         if (!battery)
510                 goto end;
511
512         acpi_battery_check_present(battery);
513
514         if (!battery->flags.present) {
515                 seq_printf(seq, "present:                 no\n");
516                 goto end;
517         }
518
519         /* Battery Units */
520
521         units =
522             battery->flags.
523             power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
524
525         /* Battery Alarm */
526
527         seq_printf(seq, "alarm:                   ");
528         if (!battery->alarm)
529                 seq_printf(seq, "unsupported\n");
530         else
531                 seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units);
532
533       end:
534         return 0;
535 }
536
537 static ssize_t
538 acpi_battery_write_alarm(struct file *file,
539                          const char __user * buffer,
540                          size_t count, loff_t * ppos)
541 {
542         int result = 0;
543         char alarm_string[12] = { '\0' };
544         struct seq_file *m = file->private_data;
545         struct acpi_battery *battery = m->private;
546
547
548         if (!battery || (count > sizeof(alarm_string) - 1))
549                 return -EINVAL;
550
551         acpi_battery_check_present(battery);
552
553         if (!battery->flags.present)
554                 return -ENODEV;
555
556         if (copy_from_user(alarm_string, buffer, count))
557                 return -EFAULT;
558
559         alarm_string[count] = '\0';
560
561         result = acpi_battery_set_alarm(battery,
562                                         simple_strtoul(alarm_string, NULL, 0));
563         if (result)
564                 return result;
565
566         return count;
567 }
568
569 static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
570 {
571         return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
572 }
573
574 static const struct file_operations acpi_battery_info_ops = {
575         .open = acpi_battery_info_open_fs,
576         .read = seq_read,
577         .llseek = seq_lseek,
578         .release = single_release,
579         .owner = THIS_MODULE,
580 };
581
582 static const struct file_operations acpi_battery_state_ops = {
583         .open = acpi_battery_state_open_fs,
584         .read = seq_read,
585         .llseek = seq_lseek,
586         .release = single_release,
587         .owner = THIS_MODULE,
588 };
589
590 static const struct file_operations acpi_battery_alarm_ops = {
591         .open = acpi_battery_alarm_open_fs,
592         .read = seq_read,
593         .write = acpi_battery_write_alarm,
594         .llseek = seq_lseek,
595         .release = single_release,
596         .owner = THIS_MODULE,
597 };
598
599 static int acpi_battery_add_fs(struct acpi_device *device)
600 {
601         struct proc_dir_entry *entry = NULL;
602
603
604         if (!acpi_device_dir(device)) {
605                 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
606                                                      acpi_battery_dir);
607                 if (!acpi_device_dir(device))
608                         return -ENODEV;
609                 acpi_device_dir(device)->owner = THIS_MODULE;
610         }
611
612         /* 'info' [R] */
613         entry = create_proc_entry(ACPI_BATTERY_FILE_INFO,
614                                   S_IRUGO, acpi_device_dir(device));
615         if (!entry)
616                 return -ENODEV;
617         else {
618                 entry->proc_fops = &acpi_battery_info_ops;
619                 entry->data = acpi_driver_data(device);
620                 entry->owner = THIS_MODULE;
621         }
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         }
645
646         return 0;
647 }
648
649 static int acpi_battery_remove_fs(struct acpi_device *device)
650 {
651
652         if (acpi_device_dir(device)) {
653                 remove_proc_entry(ACPI_BATTERY_FILE_ALARM,
654                                   acpi_device_dir(device));
655                 remove_proc_entry(ACPI_BATTERY_FILE_STATUS,
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);
661                 acpi_device_dir(device) = NULL;
662         }
663
664         return 0;
665 }
666
667 /* --------------------------------------------------------------------------
668                                  Driver Interface
669    -------------------------------------------------------------------------- */
670
671 static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
672 {
673         struct acpi_battery *battery = data;
674         struct acpi_device *device = NULL;
675
676
677         if (!battery)
678                 return;
679
680         device = battery->device;
681
682         switch (event) {
683         case ACPI_BATTERY_NOTIFY_STATUS:
684         case ACPI_BATTERY_NOTIFY_INFO:
685         case ACPI_NOTIFY_BUS_CHECK:
686         case ACPI_NOTIFY_DEVICE_CHECK:
687                 acpi_battery_check(battery);
688                 acpi_bus_generate_event(device, event, battery->flags.present);
689                 break;
690         default:
691                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
692                                   "Unsupported event [0x%x]\n", event));
693                 break;
694         }
695
696         return;
697 }
698
699 static int acpi_battery_add(struct acpi_device *device)
700 {
701         int result = 0;
702         acpi_status status = 0;
703         struct acpi_battery *battery = NULL;
704
705
706         if (!device)
707                 return -EINVAL;
708
709         battery = kzalloc(sizeof(struct acpi_battery), GFP_KERNEL);
710         if (!battery)
711                 return -ENOMEM;
712
713         battery->device = device;
714         strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
715         strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
716         acpi_driver_data(device) = battery;
717
718         result = acpi_battery_check(battery);
719         if (result)
720                 goto end;
721
722         result = acpi_battery_add_fs(device);
723         if (result)
724                 goto end;
725
726         status = acpi_install_notify_handler(device->handle,
727                                              ACPI_ALL_NOTIFY,
728                                              acpi_battery_notify, battery);
729         if (ACPI_FAILURE(status)) {
730                 result = -ENODEV;
731                 goto end;
732         }
733
734         printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
735                ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
736                device->status.battery_present ? "present" : "absent");
737
738       end:
739         if (result) {
740                 acpi_battery_remove_fs(device);
741                 kfree(battery);
742         }
743
744         return result;
745 }
746
747 static int acpi_battery_remove(struct acpi_device *device, int type)
748 {
749         acpi_status status = 0;
750         struct acpi_battery *battery = NULL;
751
752
753         if (!device || !acpi_driver_data(device))
754                 return -EINVAL;
755
756         battery = acpi_driver_data(device);
757
758         status = acpi_remove_notify_handler(device->handle,
759                                             ACPI_ALL_NOTIFY,
760                                             acpi_battery_notify);
761
762         acpi_battery_remove_fs(device);
763
764         kfree(battery);
765
766         return 0;
767 }
768
769 /* this is needed to learn about changes made in suspended state */
770 static int acpi_battery_resume(struct acpi_device *device)
771 {
772         struct acpi_battery *battery;
773
774         if (!device)
775                 return -EINVAL;
776
777         battery = device->driver_data;
778         return acpi_battery_check(battery);
779 }
780
781 static int __init acpi_battery_init(void)
782 {
783         int result;
784
785         if (acpi_disabled)
786                 return -ENODEV;
787
788         acpi_battery_dir = acpi_lock_battery_dir();
789         if (!acpi_battery_dir)
790                 return -ENODEV;
791
792         result = acpi_bus_register_driver(&acpi_battery_driver);
793         if (result < 0) {
794                 acpi_unlock_battery_dir(acpi_battery_dir);
795                 return -ENODEV;
796         }
797
798         return 0;
799 }
800
801 static void __exit acpi_battery_exit(void)
802 {
803
804         acpi_bus_unregister_driver(&acpi_battery_driver);
805
806         acpi_unlock_battery_dir(acpi_battery_dir);
807
808         return;
809 }
810
811 module_init(acpi_battery_init);
812 module_exit(acpi_battery_exit);