ACPI: battery: Use acpi_device's handle instead of driver's
[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_DRIVER_NAME        "ACPI Battery Driver"
46 #define ACPI_BATTERY_DEVICE_NAME        "Battery"
47 #define ACPI_BATTERY_FILE_INFO          "info"
48 #define ACPI_BATTERY_FILE_STATUS        "state"
49 #define ACPI_BATTERY_FILE_ALARM         "alarm"
50 #define ACPI_BATTERY_NOTIFY_STATUS      0x80
51 #define ACPI_BATTERY_NOTIFY_INFO        0x81
52 #define ACPI_BATTERY_UNITS_WATTS        "mW"
53 #define ACPI_BATTERY_UNITS_AMPS         "mA"
54
55 #define _COMPONENT              ACPI_BATTERY_COMPONENT
56 ACPI_MODULE_NAME("acpi_battery")
57
58     MODULE_AUTHOR("Paul Diefenbaugh");
59 MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME);
60 MODULE_LICENSE("GPL");
61
62 static int acpi_battery_add(struct acpi_device *device);
63 static int acpi_battery_remove(struct acpi_device *device, int type);
64
65 static struct acpi_driver acpi_battery_driver = {
66         .name = ACPI_BATTERY_DRIVER_NAME,
67         .class = ACPI_BATTERY_CLASS,
68         .ids = ACPI_BATTERY_HID,
69         .ops = {
70                 .add = acpi_battery_add,
71                 .remove = acpi_battery_remove,
72                 },
73 };
74
75 struct acpi_battery_status {
76         acpi_integer state;
77         acpi_integer present_rate;
78         acpi_integer remaining_capacity;
79         acpi_integer present_voltage;
80 };
81
82 struct acpi_battery_info {
83         acpi_integer power_unit;
84         acpi_integer design_capacity;
85         acpi_integer last_full_capacity;
86         acpi_integer battery_technology;
87         acpi_integer design_voltage;
88         acpi_integer design_capacity_warning;
89         acpi_integer design_capacity_low;
90         acpi_integer battery_capacity_granularity_1;
91         acpi_integer battery_capacity_granularity_2;
92         acpi_string model_number;
93         acpi_string serial_number;
94         acpi_string battery_type;
95         acpi_string oem_info;
96 };
97
98 struct acpi_battery_flags {
99         u8 present:1;           /* Bay occupied? */
100         u8 power_unit:1;        /* 0=watts, 1=apms */
101         u8 alarm:1;             /* _BTP present? */
102         u8 reserved:5;
103 };
104
105 struct acpi_battery_trips {
106         unsigned long warning;
107         unsigned long low;
108 };
109
110 struct acpi_battery {
111         acpi_handle handle;
112         struct acpi_device * device;
113         struct acpi_battery_flags flags;
114         struct acpi_battery_trips trips;
115         unsigned long alarm;
116         struct acpi_battery_info *info;
117 };
118
119 /* --------------------------------------------------------------------------
120                                Battery Management
121    -------------------------------------------------------------------------- */
122
123 static int
124 acpi_battery_get_info(struct acpi_battery *battery,
125                       struct acpi_battery_info **bif)
126 {
127         int result = 0;
128         acpi_status status = 0;
129         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
130         struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF),
131                 ACPI_BATTERY_FORMAT_BIF
132         };
133         struct acpi_buffer data = { 0, NULL };
134         union acpi_object *package = NULL;
135
136
137         if (!battery || !bif)
138                 return -EINVAL;
139
140         /* Evalute _BIF */
141
142         status = acpi_evaluate_object(battery->device->handle, "_BIF", NULL, &buffer);
143         if (ACPI_FAILURE(status)) {
144                 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF"));
145                 return -ENODEV;
146         }
147
148         package = (union acpi_object *)buffer.pointer;
149
150         /* Extract Package Data */
151
152         status = acpi_extract_package(package, &format, &data);
153         if (status != AE_BUFFER_OVERFLOW) {
154                 ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF"));
155                 result = -ENODEV;
156                 goto end;
157         }
158
159         data.pointer = kmalloc(data.length, GFP_KERNEL);
160         if (!data.pointer) {
161                 result = -ENOMEM;
162                 goto end;
163         }
164         memset(data.pointer, 0, data.length);
165
166         status = acpi_extract_package(package, &format, &data);
167         if (ACPI_FAILURE(status)) {
168                 ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF"));
169                 kfree(data.pointer);
170                 result = -ENODEV;
171                 goto end;
172         }
173
174       end:
175         acpi_os_free(buffer.pointer);
176
177         if (!result)
178                 (*bif) = (struct acpi_battery_info *)data.pointer;
179
180         return result;
181 }
182
183 static int
184 acpi_battery_get_status(struct acpi_battery *battery,
185                         struct acpi_battery_status **bst)
186 {
187         int result = 0;
188         acpi_status status = 0;
189         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
190         struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BST),
191                 ACPI_BATTERY_FORMAT_BST
192         };
193         struct acpi_buffer data = { 0, NULL };
194         union acpi_object *package = NULL;
195
196
197         if (!battery || !bst)
198                 return -EINVAL;
199
200         /* Evalute _BST */
201
202         status = acpi_evaluate_object(battery->device->handle, "_BST", NULL, &buffer);
203         if (ACPI_FAILURE(status)) {
204                 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
205                 return -ENODEV;
206         }
207
208         package = (union acpi_object *)buffer.pointer;
209
210         /* Extract Package Data */
211
212         status = acpi_extract_package(package, &format, &data);
213         if (status != AE_BUFFER_OVERFLOW) {
214                 ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST"));
215                 result = -ENODEV;
216                 goto end;
217         }
218
219         data.pointer = kmalloc(data.length, GFP_KERNEL);
220         if (!data.pointer) {
221                 result = -ENOMEM;
222                 goto end;
223         }
224         memset(data.pointer, 0, data.length);
225
226         status = acpi_extract_package(package, &format, &data);
227         if (ACPI_FAILURE(status)) {
228                 ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST"));
229                 kfree(data.pointer);
230                 result = -ENODEV;
231                 goto end;
232         }
233
234       end:
235         acpi_os_free(buffer.pointer);
236
237         if (!result)
238                 (*bst) = (struct acpi_battery_status *)data.pointer;
239
240         return result;
241 }
242
243 static int
244 acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm)
245 {
246         acpi_status status = 0;
247         union acpi_object arg0 = { ACPI_TYPE_INTEGER };
248         struct acpi_object_list arg_list = { 1, &arg0 };
249
250
251         if (!battery)
252                 return -EINVAL;
253
254         if (!battery->flags.alarm)
255                 return -ENODEV;
256
257         arg0.integer.value = alarm;
258
259         status = acpi_evaluate_object(battery->device->handle, "_BTP", &arg_list, NULL);
260         if (ACPI_FAILURE(status))
261                 return -ENODEV;
262
263         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", (u32) alarm));
264
265         battery->alarm = alarm;
266
267         return 0;
268 }
269
270 static int acpi_battery_check(struct acpi_battery *battery)
271 {
272         int result = 0;
273         acpi_status status = AE_OK;
274         acpi_handle handle = NULL;
275         struct acpi_device *device = NULL;
276         struct acpi_battery_info *bif = NULL;
277
278
279         if (!battery)
280                 return -EINVAL;
281
282         device = battery->device;
283
284         result = acpi_bus_get_status(device);
285         if (result)
286                 return result;
287
288         /* Insertion? */
289
290         if (!battery->flags.present && device->status.battery_present) {
291
292                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n"));
293
294                 /* Evalute _BIF to get certain static information */
295
296                 result = acpi_battery_get_info(battery, &bif);
297                 if (result)
298                         return result;
299
300                 battery->flags.power_unit = bif->power_unit;
301                 battery->trips.warning = bif->design_capacity_warning;
302                 battery->trips.low = bif->design_capacity_low;
303                 kfree(bif);
304
305                 /* See if alarms are supported, and if so, set default */
306
307                 status = acpi_get_handle(battery->device->handle, "_BTP", &handle);
308                 if (ACPI_SUCCESS(status)) {
309                         battery->flags.alarm = 1;
310                         acpi_battery_set_alarm(battery, battery->trips.warning);
311                 }
312         }
313
314         /* Removal? */
315
316         else if (battery->flags.present && !device->status.battery_present) {
317                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n"));
318         }
319
320         battery->flags.present = device->status.battery_present;
321
322         return result;
323 }
324
325 /* --------------------------------------------------------------------------
326                               FS Interface (/proc)
327    -------------------------------------------------------------------------- */
328
329 static struct proc_dir_entry *acpi_battery_dir;
330 static int acpi_battery_read_info(struct seq_file *seq, void *offset)
331 {
332         int result = 0;
333         struct acpi_battery *battery = (struct acpi_battery *)seq->private;
334         struct acpi_battery_info *bif = NULL;
335         char *units = "?";
336
337
338         if (!battery)
339                 goto end;
340
341         if (battery->flags.present)
342                 seq_printf(seq, "present:                 yes\n");
343         else {
344                 seq_printf(seq, "present:                 no\n");
345                 goto end;
346         }
347
348         /* Battery Info (_BIF) */
349
350         result = acpi_battery_get_info(battery, &bif);
351         if (result || !bif) {
352                 seq_printf(seq, "ERROR: Unable to read battery information\n");
353                 goto end;
354         }
355
356         units =
357             bif->
358             power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
359
360         if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
361                 seq_printf(seq, "design capacity:         unknown\n");
362         else
363                 seq_printf(seq, "design capacity:         %d %sh\n",
364                            (u32) bif->design_capacity, units);
365
366         if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
367                 seq_printf(seq, "last full capacity:      unknown\n");
368         else
369                 seq_printf(seq, "last full capacity:      %d %sh\n",
370                            (u32) bif->last_full_capacity, units);
371
372         switch ((u32) bif->battery_technology) {
373         case 0:
374                 seq_printf(seq, "battery technology:      non-rechargeable\n");
375                 break;
376         case 1:
377                 seq_printf(seq, "battery technology:      rechargeable\n");
378                 break;
379         default:
380                 seq_printf(seq, "battery technology:      unknown\n");
381                 break;
382         }
383
384         if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
385                 seq_printf(seq, "design voltage:          unknown\n");
386         else
387                 seq_printf(seq, "design voltage:          %d mV\n",
388                            (u32) bif->design_voltage);
389
390         seq_printf(seq, "design capacity warning: %d %sh\n",
391                    (u32) bif->design_capacity_warning, units);
392         seq_printf(seq, "design capacity low:     %d %sh\n",
393                    (u32) bif->design_capacity_low, units);
394         seq_printf(seq, "capacity granularity 1:  %d %sh\n",
395                    (u32) bif->battery_capacity_granularity_1, units);
396         seq_printf(seq, "capacity granularity 2:  %d %sh\n",
397                    (u32) bif->battery_capacity_granularity_2, units);
398         seq_printf(seq, "model number:            %s\n", bif->model_number);
399         seq_printf(seq, "serial number:           %s\n", bif->serial_number);
400         seq_printf(seq, "battery type:            %s\n", bif->battery_type);
401         seq_printf(seq, "OEM info:                %s\n", bif->oem_info);
402
403       end:
404         kfree(bif);
405
406         return 0;
407 }
408
409 static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
410 {
411         return single_open(file, acpi_battery_read_info, PDE(inode)->data);
412 }
413
414 static int acpi_battery_read_state(struct seq_file *seq, void *offset)
415 {
416         int result = 0;
417         struct acpi_battery *battery = (struct acpi_battery *)seq->private;
418         struct acpi_battery_status *bst = NULL;
419         char *units = "?";
420
421
422         if (!battery)
423                 goto end;
424
425         if (battery->flags.present)
426                 seq_printf(seq, "present:                 yes\n");
427         else {
428                 seq_printf(seq, "present:                 no\n");
429                 goto end;
430         }
431
432         /* Battery Units */
433
434         units =
435             battery->flags.
436             power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
437
438         /* Battery Status (_BST) */
439
440         result = acpi_battery_get_status(battery, &bst);
441         if (result || !bst) {
442                 seq_printf(seq, "ERROR: Unable to read battery status\n");
443                 goto end;
444         }
445
446         if (!(bst->state & 0x04))
447                 seq_printf(seq, "capacity state:          ok\n");
448         else
449                 seq_printf(seq, "capacity state:          critical\n");
450
451         if ((bst->state & 0x01) && (bst->state & 0x02)) {
452                 seq_printf(seq,
453                            "charging state:          charging/discharging\n");
454         } else if (bst->state & 0x01)
455                 seq_printf(seq, "charging state:          discharging\n");
456         else if (bst->state & 0x02)
457                 seq_printf(seq, "charging state:          charging\n");
458         else {
459                 seq_printf(seq, "charging state:          charged\n");
460         }
461
462         if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN)
463                 seq_printf(seq, "present rate:            unknown\n");
464         else
465                 seq_printf(seq, "present rate:            %d %s\n",
466                            (u32) bst->present_rate, units);
467
468         if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
469                 seq_printf(seq, "remaining capacity:      unknown\n");
470         else
471                 seq_printf(seq, "remaining capacity:      %d %sh\n",
472                            (u32) bst->remaining_capacity, units);
473
474         if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
475                 seq_printf(seq, "present voltage:         unknown\n");
476         else
477                 seq_printf(seq, "present voltage:         %d mV\n",
478                            (u32) bst->present_voltage);
479
480       end:
481         kfree(bst);
482
483         return 0;
484 }
485
486 static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
487 {
488         return single_open(file, acpi_battery_read_state, PDE(inode)->data);
489 }
490
491 static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
492 {
493         struct acpi_battery *battery = (struct acpi_battery *)seq->private;
494         char *units = "?";
495
496
497         if (!battery)
498                 goto end;
499
500         if (!battery->flags.present) {
501                 seq_printf(seq, "present:                 no\n");
502                 goto end;
503         }
504
505         /* Battery Units */
506
507         units =
508             battery->flags.
509             power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
510
511         /* Battery Alarm */
512
513         seq_printf(seq, "alarm:                   ");
514         if (!battery->alarm)
515                 seq_printf(seq, "unsupported\n");
516         else
517                 seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units);
518
519       end:
520         return 0;
521 }
522
523 static ssize_t
524 acpi_battery_write_alarm(struct file *file,
525                          const char __user * buffer,
526                          size_t count, loff_t * ppos)
527 {
528         int result = 0;
529         char alarm_string[12] = { '\0' };
530         struct seq_file *m = (struct seq_file *)file->private_data;
531         struct acpi_battery *battery = (struct acpi_battery *)m->private;
532
533
534         if (!battery || (count > sizeof(alarm_string) - 1))
535                 return -EINVAL;
536
537         if (!battery->flags.present)
538                 return -ENODEV;
539
540         if (copy_from_user(alarm_string, buffer, count))
541                 return -EFAULT;
542
543         alarm_string[count] = '\0';
544
545         result = acpi_battery_set_alarm(battery,
546                                         simple_strtoul(alarm_string, NULL, 0));
547         if (result)
548                 return result;
549
550         return count;
551 }
552
553 static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
554 {
555         return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
556 }
557
558 static struct file_operations acpi_battery_info_ops = {
559         .open = acpi_battery_info_open_fs,
560         .read = seq_read,
561         .llseek = seq_lseek,
562         .release = single_release,
563         .owner = THIS_MODULE,
564 };
565
566 static struct file_operations acpi_battery_state_ops = {
567         .open = acpi_battery_state_open_fs,
568         .read = seq_read,
569         .llseek = seq_lseek,
570         .release = single_release,
571         .owner = THIS_MODULE,
572 };
573
574 static struct file_operations acpi_battery_alarm_ops = {
575         .open = acpi_battery_alarm_open_fs,
576         .read = seq_read,
577         .write = acpi_battery_write_alarm,
578         .llseek = seq_lseek,
579         .release = single_release,
580         .owner = THIS_MODULE,
581 };
582
583 static int acpi_battery_add_fs(struct acpi_device *device)
584 {
585         struct proc_dir_entry *entry = NULL;
586
587
588         if (!acpi_device_dir(device)) {
589                 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
590                                                      acpi_battery_dir);
591                 if (!acpi_device_dir(device))
592                         return -ENODEV;
593                 acpi_device_dir(device)->owner = THIS_MODULE;
594         }
595
596         /* 'info' [R] */
597         entry = create_proc_entry(ACPI_BATTERY_FILE_INFO,
598                                   S_IRUGO, acpi_device_dir(device));
599         if (!entry)
600                 return -ENODEV;
601         else {
602                 entry->proc_fops = &acpi_battery_info_ops;
603                 entry->data = acpi_driver_data(device);
604                 entry->owner = THIS_MODULE;
605         }
606
607         /* 'status' [R] */
608         entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS,
609                                   S_IRUGO, acpi_device_dir(device));
610         if (!entry)
611                 return -ENODEV;
612         else {
613                 entry->proc_fops = &acpi_battery_state_ops;
614                 entry->data = acpi_driver_data(device);
615                 entry->owner = THIS_MODULE;
616         }
617
618         /* 'alarm' [R/W] */
619         entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM,
620                                   S_IFREG | S_IRUGO | S_IWUSR,
621                                   acpi_device_dir(device));
622         if (!entry)
623                 return -ENODEV;
624         else {
625                 entry->proc_fops = &acpi_battery_alarm_ops;
626                 entry->data = acpi_driver_data(device);
627                 entry->owner = THIS_MODULE;
628         }
629
630         return 0;
631 }
632
633 static int acpi_battery_remove_fs(struct acpi_device *device)
634 {
635
636         if (acpi_device_dir(device)) {
637                 remove_proc_entry(ACPI_BATTERY_FILE_ALARM,
638                                   acpi_device_dir(device));
639                 remove_proc_entry(ACPI_BATTERY_FILE_STATUS,
640                                   acpi_device_dir(device));
641                 remove_proc_entry(ACPI_BATTERY_FILE_INFO,
642                                   acpi_device_dir(device));
643
644                 remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
645                 acpi_device_dir(device) = NULL;
646         }
647
648         return 0;
649 }
650
651 /* --------------------------------------------------------------------------
652                                  Driver Interface
653    -------------------------------------------------------------------------- */
654
655 static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
656 {
657         struct acpi_battery *battery = (struct acpi_battery *)data;
658         struct acpi_device *device = NULL;
659
660
661         if (!battery)
662                 return;
663
664         device = battery->device;
665
666         switch (event) {
667         case ACPI_BATTERY_NOTIFY_STATUS:
668         case ACPI_BATTERY_NOTIFY_INFO:
669                 acpi_battery_check(battery);
670                 acpi_bus_generate_event(device, event, battery->flags.present);
671                 break;
672         default:
673                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
674                                   "Unsupported event [0x%x]\n", event));
675                 break;
676         }
677
678         return;
679 }
680
681 static int acpi_battery_add(struct acpi_device *device)
682 {
683         int result = 0;
684         acpi_status status = 0;
685         struct acpi_battery *battery = NULL;
686
687
688         if (!device)
689                 return -EINVAL;
690
691         battery = kmalloc(sizeof(struct acpi_battery), GFP_KERNEL);
692         if (!battery)
693                 return -ENOMEM;
694         memset(battery, 0, sizeof(struct acpi_battery));
695
696         battery->handle = device->handle;
697         battery->device = device;
698         strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
699         strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
700         acpi_driver_data(device) = battery;
701
702         result = acpi_battery_check(battery);
703         if (result)
704                 goto end;
705
706         result = acpi_battery_add_fs(device);
707         if (result)
708                 goto end;
709
710         status = acpi_install_notify_handler(device->handle,
711                                              ACPI_DEVICE_NOTIFY,
712                                              acpi_battery_notify, battery);
713         if (ACPI_FAILURE(status)) {
714                 result = -ENODEV;
715                 goto end;
716         }
717
718         printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
719                ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
720                device->status.battery_present ? "present" : "absent");
721
722       end:
723         if (result) {
724                 acpi_battery_remove_fs(device);
725                 kfree(battery);
726         }
727
728         return result;
729 }
730
731 static int acpi_battery_remove(struct acpi_device *device, int type)
732 {
733         acpi_status status = 0;
734         struct acpi_battery *battery = NULL;
735
736
737         if (!device || !acpi_driver_data(device))
738                 return -EINVAL;
739
740         battery = (struct acpi_battery *)acpi_driver_data(device);
741
742         status = acpi_remove_notify_handler(device->handle,
743                                             ACPI_DEVICE_NOTIFY,
744                                             acpi_battery_notify);
745
746         acpi_battery_remove_fs(device);
747
748         kfree(battery);
749
750         return 0;
751 }
752
753 static int __init acpi_battery_init(void)
754 {
755         int result = 0;
756
757
758         acpi_battery_dir = proc_mkdir(ACPI_BATTERY_CLASS, acpi_root_dir);
759         if (!acpi_battery_dir)
760                 return -ENODEV;
761         acpi_battery_dir->owner = THIS_MODULE;
762
763         result = acpi_bus_register_driver(&acpi_battery_driver);
764         if (result < 0) {
765                 remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
766                 return -ENODEV;
767         }
768
769         return 0;
770 }
771
772 static void __exit acpi_battery_exit(void)
773 {
774
775         acpi_bus_unregister_driver(&acpi_battery_driver);
776
777         remove_proc_entry(ACPI_BATTERY_CLASS, acpi_root_dir);
778
779         return;
780 }
781
782 module_init(acpi_battery_init);
783 module_exit(acpi_battery_exit);