ia64/linux-2.6.18-xen.hg

view drivers/acpi/battery.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents 831230e53067
children
line source
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 */
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>
34 #include <acpi/acpi_bus.h>
35 #include <acpi/acpi_drivers.h>
37 #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF
39 #define ACPI_BATTERY_FORMAT_BIF "NNNNNNNNNSSSS"
40 #define ACPI_BATTERY_FORMAT_BST "NNNN"
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"
55 #define _COMPONENT ACPI_BATTERY_COMPONENT
56 ACPI_MODULE_NAME("acpi_battery")
58 MODULE_AUTHOR("Paul Diefenbaugh");
59 MODULE_DESCRIPTION(ACPI_BATTERY_DRIVER_NAME);
60 MODULE_LICENSE("GPL");
62 extern struct proc_dir_entry *acpi_lock_battery_dir(void);
63 extern void *acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir);
65 static int acpi_battery_add(struct acpi_device *device);
66 static int acpi_battery_remove(struct acpi_device *device, int type);
68 static struct acpi_driver acpi_battery_driver = {
69 .name = ACPI_BATTERY_DRIVER_NAME,
70 .class = ACPI_BATTERY_CLASS,
71 .ids = ACPI_BATTERY_HID,
72 .ops = {
73 .add = acpi_battery_add,
74 .remove = acpi_battery_remove,
75 },
76 };
78 struct acpi_battery_status {
79 acpi_integer state;
80 acpi_integer present_rate;
81 acpi_integer remaining_capacity;
82 acpi_integer present_voltage;
83 };
85 struct acpi_battery_info {
86 acpi_integer power_unit;
87 acpi_integer design_capacity;
88 acpi_integer last_full_capacity;
89 acpi_integer battery_technology;
90 acpi_integer design_voltage;
91 acpi_integer design_capacity_warning;
92 acpi_integer design_capacity_low;
93 acpi_integer battery_capacity_granularity_1;
94 acpi_integer battery_capacity_granularity_2;
95 acpi_string model_number;
96 acpi_string serial_number;
97 acpi_string battery_type;
98 acpi_string oem_info;
99 };
101 struct acpi_battery_flags {
102 u8 present:1; /* Bay occupied? */
103 u8 power_unit:1; /* 0=watts, 1=apms */
104 u8 alarm:1; /* _BTP present? */
105 u8 reserved:5;
106 };
108 struct acpi_battery_trips {
109 unsigned long warning;
110 unsigned long low;
111 };
113 struct acpi_battery {
114 struct acpi_device * device;
115 struct acpi_battery_flags flags;
116 struct acpi_battery_trips trips;
117 unsigned long alarm;
118 struct acpi_battery_info *info;
119 };
121 /* --------------------------------------------------------------------------
122 Battery Management
123 -------------------------------------------------------------------------- */
125 static int
126 acpi_battery_get_info(struct acpi_battery *battery,
127 struct acpi_battery_info **bif)
128 {
129 int result = 0;
130 acpi_status status = 0;
131 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
132 struct acpi_buffer format = { sizeof(ACPI_BATTERY_FORMAT_BIF),
133 ACPI_BATTERY_FORMAT_BIF
134 };
135 struct acpi_buffer data = { 0, NULL };
136 union acpi_object *package = NULL;
139 if (!battery || !bif)
140 return -EINVAL;
142 /* Evalute _BIF */
144 status = acpi_evaluate_object(battery->device->handle, "_BIF", NULL, &buffer);
145 if (ACPI_FAILURE(status)) {
146 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF"));
147 return -ENODEV;
148 }
150 package = (union acpi_object *)buffer.pointer;
152 /* Extract Package Data */
154 status = acpi_extract_package(package, &format, &data);
155 if (status != AE_BUFFER_OVERFLOW) {
156 ACPI_EXCEPTION((AE_INFO, status, "Extracting _BIF"));
157 result = -ENODEV;
158 goto end;
159 }
161 data.pointer = kmalloc(data.length, GFP_KERNEL);
162 if (!data.pointer) {
163 result = -ENOMEM;
164 goto end;
165 }
166 memset(data.pointer, 0, data.length);
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 }
176 end:
177 kfree(buffer.pointer);
179 if (!result)
180 (*bif) = (struct acpi_battery_info *)data.pointer;
182 return result;
183 }
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;
199 if (!battery || !bst)
200 return -EINVAL;
202 /* Evalute _BST */
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 }
210 package = (union acpi_object *)buffer.pointer;
212 /* Extract Package Data */
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 }
221 data.pointer = kmalloc(data.length, GFP_KERNEL);
222 if (!data.pointer) {
223 result = -ENOMEM;
224 goto end;
225 }
226 memset(data.pointer, 0, data.length);
228 status = acpi_extract_package(package, &format, &data);
229 if (ACPI_FAILURE(status)) {
230 ACPI_EXCEPTION((AE_INFO, status, "Extracting _BST"));
231 kfree(data.pointer);
232 result = -ENODEV;
233 goto end;
234 }
236 end:
237 kfree(buffer.pointer);
239 if (!result)
240 (*bst) = (struct acpi_battery_status *)data.pointer;
242 return result;
243 }
245 static int
246 acpi_battery_set_alarm(struct acpi_battery *battery, unsigned long alarm)
247 {
248 acpi_status status = 0;
249 union acpi_object arg0 = { ACPI_TYPE_INTEGER };
250 struct acpi_object_list arg_list = { 1, &arg0 };
253 if (!battery)
254 return -EINVAL;
256 if (!battery->flags.alarm)
257 return -ENODEV;
259 arg0.integer.value = alarm;
261 status = acpi_evaluate_object(battery->device->handle, "_BTP", &arg_list, NULL);
262 if (ACPI_FAILURE(status))
263 return -ENODEV;
265 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Alarm set to %d\n", (u32) alarm));
267 battery->alarm = alarm;
269 return 0;
270 }
272 static int acpi_battery_check(struct acpi_battery *battery)
273 {
274 int result = 0;
275 acpi_status status = AE_OK;
276 acpi_handle handle = NULL;
277 struct acpi_device *device = NULL;
278 struct acpi_battery_info *bif = NULL;
281 if (!battery)
282 return -EINVAL;
284 device = battery->device;
286 result = acpi_bus_get_status(device);
287 if (result)
288 return result;
290 /* Insertion? */
292 if (!battery->flags.present && device->status.battery_present) {
294 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery inserted\n"));
296 /* Evalute _BIF to get certain static information */
298 result = acpi_battery_get_info(battery, &bif);
299 if (result)
300 return result;
302 battery->flags.power_unit = bif->power_unit;
303 battery->trips.warning = bif->design_capacity_warning;
304 battery->trips.low = bif->design_capacity_low;
305 kfree(bif);
307 /* See if alarms are supported, and if so, set default */
309 status = acpi_get_handle(battery->device->handle, "_BTP", &handle);
310 if (ACPI_SUCCESS(status)) {
311 battery->flags.alarm = 1;
312 acpi_battery_set_alarm(battery, battery->trips.warning);
313 }
314 }
316 /* Removal? */
318 else if (battery->flags.present && !device->status.battery_present) {
319 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Battery removed\n"));
320 }
322 battery->flags.present = device->status.battery_present;
324 return result;
325 }
327 /* --------------------------------------------------------------------------
328 FS Interface (/proc)
329 -------------------------------------------------------------------------- */
331 static struct proc_dir_entry *acpi_battery_dir;
332 static int acpi_battery_read_info(struct seq_file *seq, void *offset)
333 {
334 int result = 0;
335 struct acpi_battery *battery = (struct acpi_battery *)seq->private;
336 struct acpi_battery_info *bif = NULL;
337 char *units = "?";
340 if (!battery)
341 goto end;
343 if (battery->flags.present)
344 seq_printf(seq, "present: yes\n");
345 else {
346 seq_printf(seq, "present: no\n");
347 goto end;
348 }
350 /* Battery Info (_BIF) */
352 result = acpi_battery_get_info(battery, &bif);
353 if (result || !bif) {
354 seq_printf(seq, "ERROR: Unable to read battery information\n");
355 goto end;
356 }
358 units =
359 bif->
360 power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
362 if (bif->design_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
363 seq_printf(seq, "design capacity: unknown\n");
364 else
365 seq_printf(seq, "design capacity: %d %sh\n",
366 (u32) bif->design_capacity, units);
368 if (bif->last_full_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
369 seq_printf(seq, "last full capacity: unknown\n");
370 else
371 seq_printf(seq, "last full capacity: %d %sh\n",
372 (u32) bif->last_full_capacity, units);
374 switch ((u32) bif->battery_technology) {
375 case 0:
376 seq_printf(seq, "battery technology: non-rechargeable\n");
377 break;
378 case 1:
379 seq_printf(seq, "battery technology: rechargeable\n");
380 break;
381 default:
382 seq_printf(seq, "battery technology: unknown\n");
383 break;
384 }
386 if (bif->design_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
387 seq_printf(seq, "design voltage: unknown\n");
388 else
389 seq_printf(seq, "design voltage: %d mV\n",
390 (u32) bif->design_voltage);
392 seq_printf(seq, "design capacity warning: %d %sh\n",
393 (u32) bif->design_capacity_warning, units);
394 seq_printf(seq, "design capacity low: %d %sh\n",
395 (u32) bif->design_capacity_low, units);
396 seq_printf(seq, "capacity granularity 1: %d %sh\n",
397 (u32) bif->battery_capacity_granularity_1, units);
398 seq_printf(seq, "capacity granularity 2: %d %sh\n",
399 (u32) bif->battery_capacity_granularity_2, units);
400 seq_printf(seq, "model number: %s\n", bif->model_number);
401 seq_printf(seq, "serial number: %s\n", bif->serial_number);
402 seq_printf(seq, "battery type: %s\n", bif->battery_type);
403 seq_printf(seq, "OEM info: %s\n", bif->oem_info);
405 end:
406 kfree(bif);
408 return 0;
409 }
411 static int acpi_battery_info_open_fs(struct inode *inode, struct file *file)
412 {
413 return single_open(file, acpi_battery_read_info, PDE(inode)->data);
414 }
416 static int acpi_battery_read_state(struct seq_file *seq, void *offset)
417 {
418 int result = 0;
419 struct acpi_battery *battery = (struct acpi_battery *)seq->private;
420 struct acpi_battery_status *bst = NULL;
421 char *units = "?";
424 if (!battery)
425 goto end;
427 if (battery->flags.present)
428 seq_printf(seq, "present: yes\n");
429 else {
430 seq_printf(seq, "present: no\n");
431 goto end;
432 }
434 /* Battery Units */
436 units =
437 battery->flags.
438 power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
440 /* Battery Status (_BST) */
442 result = acpi_battery_get_status(battery, &bst);
443 if (result || !bst) {
444 seq_printf(seq, "ERROR: Unable to read battery status\n");
445 goto end;
446 }
448 if (!(bst->state & 0x04))
449 seq_printf(seq, "capacity state: ok\n");
450 else
451 seq_printf(seq, "capacity state: critical\n");
453 if ((bst->state & 0x01) && (bst->state & 0x02)) {
454 seq_printf(seq,
455 "charging state: charging/discharging\n");
456 } else if (bst->state & 0x01)
457 seq_printf(seq, "charging state: discharging\n");
458 else if (bst->state & 0x02)
459 seq_printf(seq, "charging state: charging\n");
460 else {
461 seq_printf(seq, "charging state: charged\n");
462 }
464 if (bst->present_rate == ACPI_BATTERY_VALUE_UNKNOWN)
465 seq_printf(seq, "present rate: unknown\n");
466 else
467 seq_printf(seq, "present rate: %d %s\n",
468 (u32) bst->present_rate, units);
470 if (bst->remaining_capacity == ACPI_BATTERY_VALUE_UNKNOWN)
471 seq_printf(seq, "remaining capacity: unknown\n");
472 else
473 seq_printf(seq, "remaining capacity: %d %sh\n",
474 (u32) bst->remaining_capacity, units);
476 if (bst->present_voltage == ACPI_BATTERY_VALUE_UNKNOWN)
477 seq_printf(seq, "present voltage: unknown\n");
478 else
479 seq_printf(seq, "present voltage: %d mV\n",
480 (u32) bst->present_voltage);
482 end:
483 kfree(bst);
485 return 0;
486 }
488 static int acpi_battery_state_open_fs(struct inode *inode, struct file *file)
489 {
490 return single_open(file, acpi_battery_read_state, PDE(inode)->data);
491 }
493 static int acpi_battery_read_alarm(struct seq_file *seq, void *offset)
494 {
495 struct acpi_battery *battery = (struct acpi_battery *)seq->private;
496 char *units = "?";
499 if (!battery)
500 goto end;
502 if (!battery->flags.present) {
503 seq_printf(seq, "present: no\n");
504 goto end;
505 }
507 /* Battery Units */
509 units =
510 battery->flags.
511 power_unit ? ACPI_BATTERY_UNITS_AMPS : ACPI_BATTERY_UNITS_WATTS;
513 /* Battery Alarm */
515 seq_printf(seq, "alarm: ");
516 if (!battery->alarm)
517 seq_printf(seq, "unsupported\n");
518 else
519 seq_printf(seq, "%d %sh\n", (u32) battery->alarm, units);
521 end:
522 return 0;
523 }
525 static ssize_t
526 acpi_battery_write_alarm(struct file *file,
527 const char __user * buffer,
528 size_t count, loff_t * ppos)
529 {
530 int result = 0;
531 char alarm_string[12] = { '\0' };
532 struct seq_file *m = (struct seq_file *)file->private_data;
533 struct acpi_battery *battery = (struct acpi_battery *)m->private;
536 if (!battery || (count > sizeof(alarm_string) - 1))
537 return -EINVAL;
539 if (!battery->flags.present)
540 return -ENODEV;
542 if (copy_from_user(alarm_string, buffer, count))
543 return -EFAULT;
545 alarm_string[count] = '\0';
547 result = acpi_battery_set_alarm(battery,
548 simple_strtoul(alarm_string, NULL, 0));
549 if (result)
550 return result;
552 return count;
553 }
555 static int acpi_battery_alarm_open_fs(struct inode *inode, struct file *file)
556 {
557 return single_open(file, acpi_battery_read_alarm, PDE(inode)->data);
558 }
560 static const struct file_operations acpi_battery_info_ops = {
561 .open = acpi_battery_info_open_fs,
562 .read = seq_read,
563 .llseek = seq_lseek,
564 .release = single_release,
565 .owner = THIS_MODULE,
566 };
568 static const struct file_operations acpi_battery_state_ops = {
569 .open = acpi_battery_state_open_fs,
570 .read = seq_read,
571 .llseek = seq_lseek,
572 .release = single_release,
573 .owner = THIS_MODULE,
574 };
576 static const struct file_operations acpi_battery_alarm_ops = {
577 .open = acpi_battery_alarm_open_fs,
578 .read = seq_read,
579 .write = acpi_battery_write_alarm,
580 .llseek = seq_lseek,
581 .release = single_release,
582 .owner = THIS_MODULE,
583 };
585 static int acpi_battery_add_fs(struct acpi_device *device)
586 {
587 struct proc_dir_entry *entry = NULL;
590 if (!acpi_device_dir(device)) {
591 acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device),
592 acpi_battery_dir);
593 if (!acpi_device_dir(device))
594 return -ENODEV;
595 acpi_device_dir(device)->owner = THIS_MODULE;
596 }
598 /* 'info' [R] */
599 entry = create_proc_entry(ACPI_BATTERY_FILE_INFO,
600 S_IRUGO, acpi_device_dir(device));
601 if (!entry)
602 return -ENODEV;
603 else {
604 entry->proc_fops = &acpi_battery_info_ops;
605 entry->data = acpi_driver_data(device);
606 entry->owner = THIS_MODULE;
607 }
609 /* 'status' [R] */
610 entry = create_proc_entry(ACPI_BATTERY_FILE_STATUS,
611 S_IRUGO, acpi_device_dir(device));
612 if (!entry)
613 return -ENODEV;
614 else {
615 entry->proc_fops = &acpi_battery_state_ops;
616 entry->data = acpi_driver_data(device);
617 entry->owner = THIS_MODULE;
618 }
620 /* 'alarm' [R/W] */
621 entry = create_proc_entry(ACPI_BATTERY_FILE_ALARM,
622 S_IFREG | S_IRUGO | S_IWUSR,
623 acpi_device_dir(device));
624 if (!entry)
625 return -ENODEV;
626 else {
627 entry->proc_fops = &acpi_battery_alarm_ops;
628 entry->data = acpi_driver_data(device);
629 entry->owner = THIS_MODULE;
630 }
632 return 0;
633 }
635 static int acpi_battery_remove_fs(struct acpi_device *device)
636 {
638 if (acpi_device_dir(device)) {
639 remove_proc_entry(ACPI_BATTERY_FILE_ALARM,
640 acpi_device_dir(device));
641 remove_proc_entry(ACPI_BATTERY_FILE_STATUS,
642 acpi_device_dir(device));
643 remove_proc_entry(ACPI_BATTERY_FILE_INFO,
644 acpi_device_dir(device));
646 remove_proc_entry(acpi_device_bid(device), acpi_battery_dir);
647 acpi_device_dir(device) = NULL;
648 }
650 return 0;
651 }
653 /* --------------------------------------------------------------------------
654 Driver Interface
655 -------------------------------------------------------------------------- */
657 static void acpi_battery_notify(acpi_handle handle, u32 event, void *data)
658 {
659 struct acpi_battery *battery = (struct acpi_battery *)data;
660 struct acpi_device *device = NULL;
663 if (!battery)
664 return;
666 device = battery->device;
668 switch (event) {
669 case ACPI_BATTERY_NOTIFY_STATUS:
670 case ACPI_BATTERY_NOTIFY_INFO:
671 case ACPI_NOTIFY_BUS_CHECK:
672 case ACPI_NOTIFY_DEVICE_CHECK:
673 acpi_battery_check(battery);
674 acpi_bus_generate_event(device, event, battery->flags.present);
675 break;
676 default:
677 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
678 "Unsupported event [0x%x]\n", event));
679 break;
680 }
682 return;
683 }
685 static int acpi_battery_add(struct acpi_device *device)
686 {
687 int result = 0;
688 acpi_status status = 0;
689 struct acpi_battery *battery = NULL;
692 if (!device)
693 return -EINVAL;
695 battery = kmalloc(sizeof(struct acpi_battery), GFP_KERNEL);
696 if (!battery)
697 return -ENOMEM;
698 memset(battery, 0, sizeof(struct acpi_battery));
700 battery->device = device;
701 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
702 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
703 acpi_driver_data(device) = battery;
705 result = acpi_battery_check(battery);
706 if (result)
707 goto end;
709 result = acpi_battery_add_fs(device);
710 if (result)
711 goto end;
713 status = acpi_install_notify_handler(device->handle,
714 ACPI_ALL_NOTIFY,
715 acpi_battery_notify, battery);
716 if (ACPI_FAILURE(status)) {
717 result = -ENODEV;
718 goto end;
719 }
721 printk(KERN_INFO PREFIX "%s Slot [%s] (battery %s)\n",
722 ACPI_BATTERY_DEVICE_NAME, acpi_device_bid(device),
723 device->status.battery_present ? "present" : "absent");
725 end:
726 if (result) {
727 acpi_battery_remove_fs(device);
728 kfree(battery);
729 }
731 return result;
732 }
734 static int acpi_battery_remove(struct acpi_device *device, int type)
735 {
736 acpi_status status = 0;
737 struct acpi_battery *battery = NULL;
740 if (!device || !acpi_driver_data(device))
741 return -EINVAL;
743 battery = (struct acpi_battery *)acpi_driver_data(device);
745 status = acpi_remove_notify_handler(device->handle,
746 ACPI_ALL_NOTIFY,
747 acpi_battery_notify);
749 acpi_battery_remove_fs(device);
751 kfree(battery);
753 return 0;
754 }
756 static int __init acpi_battery_init(void)
757 {
758 int result;
760 if (acpi_disabled)
761 return -ENODEV;
763 acpi_battery_dir = acpi_lock_battery_dir();
764 if (!acpi_battery_dir)
765 return -ENODEV;
767 result = acpi_bus_register_driver(&acpi_battery_driver);
768 if (result < 0) {
769 acpi_unlock_battery_dir(acpi_battery_dir);
770 return -ENODEV;
771 }
773 return 0;
774 }
776 static void __exit acpi_battery_exit(void)
777 {
779 acpi_bus_unregister_driver(&acpi_battery_driver);
781 acpi_unlock_battery_dir(acpi_battery_dir);
783 return;
784 }
786 module_init(acpi_battery_init);
787 module_exit(acpi_battery_exit);