diff options
Diffstat (limited to 'drivers/acpi/sbs.c')
-rw-r--r-- | drivers/acpi/sbs.c | 577 |
1 files changed, 319 insertions, 258 deletions
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c index 395664528dd1..c1bae106833c 100644 --- a/drivers/acpi/sbs.c +++ b/drivers/acpi/sbs.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
32 | #include <linux/acpi.h> | 32 | #include <linux/acpi.h> |
33 | #include <linux/timer.h> | 33 | #include <linux/timer.h> |
34 | #include <linux/jiffies.h> | ||
34 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
35 | 36 | ||
36 | #define ACPI_SBS_COMPONENT 0x00080000 | 37 | #define ACPI_SBS_COMPONENT 0x00080000 |
@@ -109,29 +110,19 @@ extern void acpi_unlock_battery_dir(struct proc_dir_entry *acpi_battery_dir); | |||
109 | #define ACPI_SBS_WORD_DATA 1 | 110 | #define ACPI_SBS_WORD_DATA 1 |
110 | #define ACPI_SBS_BLOCK_DATA 2 | 111 | #define ACPI_SBS_BLOCK_DATA 2 |
111 | 112 | ||
112 | static struct semaphore sbs_sem; | 113 | #define UPDATE_DELAY 10 |
113 | 114 | ||
114 | #define UPDATE_MODE QUEUE_UPDATE_MODE | 115 | /* 0 - every time, > 0 - by update_time */ |
115 | /* REQUEST_UPDATE_MODE QUEUE_UPDATE_MODE */ | 116 | static unsigned int update_time = 120; |
116 | #define UPDATE_INFO_MODE 0 | ||
117 | #define UPDATE_TIME 60 | ||
118 | #define UPDATE_TIME2 0 | ||
119 | 117 | ||
120 | static int capacity_mode = CAPACITY_UNIT; | 118 | static unsigned int capacity_mode = CAPACITY_UNIT; |
121 | static int update_mode = UPDATE_MODE; | ||
122 | static int update_info_mode = UPDATE_INFO_MODE; | ||
123 | static int update_time = UPDATE_TIME; | ||
124 | static int update_time2 = UPDATE_TIME2; | ||
125 | 119 | ||
126 | module_param(capacity_mode, int, 0); | 120 | module_param(update_time, uint, 0644); |
127 | module_param(update_mode, int, 0); | 121 | module_param(capacity_mode, uint, 0444); |
128 | module_param(update_info_mode, int, 0); | ||
129 | module_param(update_time, int, 0); | ||
130 | module_param(update_time2, int, 0); | ||
131 | 122 | ||
132 | static int acpi_sbs_add(struct acpi_device *device); | 123 | static int acpi_sbs_add(struct acpi_device *device); |
133 | static int acpi_sbs_remove(struct acpi_device *device, int type); | 124 | static int acpi_sbs_remove(struct acpi_device *device, int type); |
134 | static void acpi_sbs_update_queue(void *data); | 125 | static int acpi_sbs_resume(struct acpi_device *device); |
135 | 126 | ||
136 | static struct acpi_driver acpi_sbs_driver = { | 127 | static struct acpi_driver acpi_sbs_driver = { |
137 | .name = "sbs", | 128 | .name = "sbs", |
@@ -140,9 +131,14 @@ static struct acpi_driver acpi_sbs_driver = { | |||
140 | .ops = { | 131 | .ops = { |
141 | .add = acpi_sbs_add, | 132 | .add = acpi_sbs_add, |
142 | .remove = acpi_sbs_remove, | 133 | .remove = acpi_sbs_remove, |
134 | .resume = acpi_sbs_resume, | ||
143 | }, | 135 | }, |
144 | }; | 136 | }; |
145 | 137 | ||
138 | struct acpi_ac { | ||
139 | int ac_present; | ||
140 | }; | ||
141 | |||
146 | struct acpi_battery_info { | 142 | struct acpi_battery_info { |
147 | int capacity_mode; | 143 | int capacity_mode; |
148 | s16 full_charge_capacity; | 144 | s16 full_charge_capacity; |
@@ -160,9 +156,7 @@ struct acpi_battery_state { | |||
160 | s16 voltage; | 156 | s16 voltage; |
161 | s16 amperage; | 157 | s16 amperage; |
162 | s16 remaining_capacity; | 158 | s16 remaining_capacity; |
163 | s16 average_time_to_empty; | 159 | s16 battery_state; |
164 | s16 average_time_to_full; | ||
165 | s16 battery_status; | ||
166 | }; | 160 | }; |
167 | 161 | ||
168 | struct acpi_battery_alarm { | 162 | struct acpi_battery_alarm { |
@@ -171,9 +165,9 @@ struct acpi_battery_alarm { | |||
171 | 165 | ||
172 | struct acpi_battery { | 166 | struct acpi_battery { |
173 | int alive; | 167 | int alive; |
174 | int battery_present; | ||
175 | int id; | 168 | int id; |
176 | int init_state; | 169 | int init_state; |
170 | int battery_present; | ||
177 | struct acpi_sbs *sbs; | 171 | struct acpi_sbs *sbs; |
178 | struct acpi_battery_info info; | 172 | struct acpi_battery_info info; |
179 | struct acpi_battery_state state; | 173 | struct acpi_battery_state state; |
@@ -185,18 +179,22 @@ struct acpi_sbs { | |||
185 | acpi_handle handle; | 179 | acpi_handle handle; |
186 | int base; | 180 | int base; |
187 | struct acpi_device *device; | 181 | struct acpi_device *device; |
182 | struct acpi_ec_smbus *smbus; | ||
183 | struct mutex mutex; | ||
188 | int sbsm_present; | 184 | int sbsm_present; |
189 | int sbsm_batteries_supported; | 185 | int sbsm_batteries_supported; |
190 | int ac_present; | ||
191 | struct proc_dir_entry *ac_entry; | 186 | struct proc_dir_entry *ac_entry; |
187 | struct acpi_ac ac; | ||
192 | struct acpi_battery battery[MAX_SBS_BAT]; | 188 | struct acpi_battery battery[MAX_SBS_BAT]; |
193 | int update_info_mode; | ||
194 | int zombie; | 189 | int zombie; |
195 | int update_time; | ||
196 | int update_time2; | ||
197 | struct timer_list update_timer; | 190 | struct timer_list update_timer; |
191 | int run_cnt; | ||
192 | int update_proc_flg; | ||
198 | }; | 193 | }; |
199 | 194 | ||
195 | static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type); | ||
196 | static void acpi_sbs_update_time(void *data); | ||
197 | |||
200 | union sbs_rw_data { | 198 | union sbs_rw_data { |
201 | u16 word; | 199 | u16 word; |
202 | u8 block[ACPI_SBS_BLOCK_MAX + 2]; | 200 | u8 block[ACPI_SBS_BLOCK_MAX + 2]; |
@@ -205,8 +203,6 @@ union sbs_rw_data { | |||
205 | static int acpi_ec_sbs_access(struct acpi_sbs *sbs, u16 addr, | 203 | static int acpi_ec_sbs_access(struct acpi_sbs *sbs, u16 addr, |
206 | char read_write, u8 command, int size, | 204 | char read_write, u8 command, int size, |
207 | union sbs_rw_data *data); | 205 | union sbs_rw_data *data); |
208 | static void acpi_update_delay(struct acpi_sbs *sbs); | ||
209 | static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type); | ||
210 | 206 | ||
211 | /* -------------------------------------------------------------------------- | 207 | /* -------------------------------------------------------------------------- |
212 | SMBus Communication | 208 | SMBus Communication |
@@ -383,11 +379,49 @@ acpi_sbs_write_word(struct acpi_sbs *sbs, int addr, int func, int word) | |||
383 | return result; | 379 | return result; |
384 | } | 380 | } |
385 | 381 | ||
382 | static int sbs_zombie(struct acpi_sbs *sbs) | ||
383 | { | ||
384 | return (sbs->zombie); | ||
385 | } | ||
386 | |||
387 | static int sbs_mutex_lock(struct acpi_sbs *sbs) | ||
388 | { | ||
389 | if (sbs_zombie(sbs)) { | ||
390 | return -ENODEV; | ||
391 | } | ||
392 | mutex_lock(&sbs->mutex); | ||
393 | return 0; | ||
394 | } | ||
395 | |||
396 | static void sbs_mutex_unlock(struct acpi_sbs *sbs) | ||
397 | { | ||
398 | mutex_unlock(&sbs->mutex); | ||
399 | } | ||
400 | |||
386 | /* -------------------------------------------------------------------------- | 401 | /* -------------------------------------------------------------------------- |
387 | Smart Battery System Management | 402 | Smart Battery System Management |
388 | -------------------------------------------------------------------------- */ | 403 | -------------------------------------------------------------------------- */ |
389 | 404 | ||
390 | /* Smart Battery */ | 405 | static int acpi_check_update_proc(struct acpi_sbs *sbs) |
406 | { | ||
407 | acpi_status status = AE_OK; | ||
408 | |||
409 | if (update_time == 0) { | ||
410 | sbs->update_proc_flg = 0; | ||
411 | return 0; | ||
412 | } | ||
413 | if (sbs->update_proc_flg == 0) { | ||
414 | status = acpi_os_execute(OSL_GPE_HANDLER, | ||
415 | acpi_sbs_update_time, sbs); | ||
416 | if (status != AE_OK) { | ||
417 | ACPI_EXCEPTION((AE_INFO, status, | ||
418 | "acpi_os_execute() failed")); | ||
419 | return 1; | ||
420 | } | ||
421 | sbs->update_proc_flg = 1; | ||
422 | } | ||
423 | return 0; | ||
424 | } | ||
391 | 425 | ||
392 | static int acpi_sbs_generate_event(struct acpi_device *device, | 426 | static int acpi_sbs_generate_event(struct acpi_device *device, |
393 | int event, int state, char *bid, char *class) | 427 | int event, int state, char *bid, char *class) |
@@ -430,16 +464,6 @@ static int acpi_battery_get_present(struct acpi_battery *battery) | |||
430 | return result; | 464 | return result; |
431 | } | 465 | } |
432 | 466 | ||
433 | static int acpi_battery_is_present(struct acpi_battery *battery) | ||
434 | { | ||
435 | return (battery->battery_present); | ||
436 | } | ||
437 | |||
438 | static int acpi_ac_is_present(struct acpi_sbs *sbs) | ||
439 | { | ||
440 | return (sbs->ac_present); | ||
441 | } | ||
442 | |||
443 | static int acpi_battery_select(struct acpi_battery *battery) | 467 | static int acpi_battery_select(struct acpi_battery *battery) |
444 | { | 468 | { |
445 | struct acpi_sbs *sbs = battery->sbs; | 469 | struct acpi_sbs *sbs = battery->sbs; |
@@ -447,7 +471,7 @@ static int acpi_battery_select(struct acpi_battery *battery) | |||
447 | s16 state; | 471 | s16 state; |
448 | int foo; | 472 | int foo; |
449 | 473 | ||
450 | if (battery->sbs->sbsm_present) { | 474 | if (sbs->sbsm_present) { |
451 | 475 | ||
452 | /* Take special care not to knobble other nibbles of | 476 | /* Take special care not to knobble other nibbles of |
453 | * state (aka selector_state), since | 477 | * state (aka selector_state), since |
@@ -523,6 +547,8 @@ static int acpi_battery_get_info(struct acpi_battery *battery) | |||
523 | &battery->info.design_capacity); | 547 | &battery->info.design_capacity); |
524 | 548 | ||
525 | if (result) { | 549 | if (result) { |
550 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
551 | "acpi_sbs_read_word() failed")); | ||
526 | goto end; | 552 | goto end; |
527 | } | 553 | } |
528 | 554 | ||
@@ -573,6 +599,8 @@ static int acpi_battery_get_info(struct acpi_battery *battery) | |||
573 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x1c, | 599 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x1c, |
574 | &battery->info.serial_number); | 600 | &battery->info.serial_number); |
575 | if (result) { | 601 | if (result) { |
602 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
603 | "acpi_sbs_read_word() failed")); | ||
576 | goto end; | 604 | goto end; |
577 | } | 605 | } |
578 | 606 | ||
@@ -604,22 +632,11 @@ static int acpi_battery_get_info(struct acpi_battery *battery) | |||
604 | return result; | 632 | return result; |
605 | } | 633 | } |
606 | 634 | ||
607 | static void acpi_update_delay(struct acpi_sbs *sbs) | ||
608 | { | ||
609 | if (sbs->zombie) { | ||
610 | return; | ||
611 | } | ||
612 | if (sbs->update_time2 > 0) { | ||
613 | msleep(sbs->update_time2 * 1000); | ||
614 | } | ||
615 | } | ||
616 | |||
617 | static int acpi_battery_get_state(struct acpi_battery *battery) | 635 | static int acpi_battery_get_state(struct acpi_battery *battery) |
618 | { | 636 | { |
619 | struct acpi_sbs *sbs = battery->sbs; | 637 | struct acpi_sbs *sbs = battery->sbs; |
620 | int result = 0; | 638 | int result = 0; |
621 | 639 | ||
622 | acpi_update_delay(battery->sbs); | ||
623 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x09, | 640 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x09, |
624 | &battery->state.voltage); | 641 | &battery->state.voltage); |
625 | if (result) { | 642 | if (result) { |
@@ -628,7 +645,6 @@ static int acpi_battery_get_state(struct acpi_battery *battery) | |||
628 | goto end; | 645 | goto end; |
629 | } | 646 | } |
630 | 647 | ||
631 | acpi_update_delay(battery->sbs); | ||
632 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0a, | 648 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0a, |
633 | &battery->state.amperage); | 649 | &battery->state.amperage); |
634 | if (result) { | 650 | if (result) { |
@@ -637,7 +653,6 @@ static int acpi_battery_get_state(struct acpi_battery *battery) | |||
637 | goto end; | 653 | goto end; |
638 | } | 654 | } |
639 | 655 | ||
640 | acpi_update_delay(battery->sbs); | ||
641 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0f, | 656 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x0f, |
642 | &battery->state.remaining_capacity); | 657 | &battery->state.remaining_capacity); |
643 | if (result) { | 658 | if (result) { |
@@ -646,35 +661,14 @@ static int acpi_battery_get_state(struct acpi_battery *battery) | |||
646 | goto end; | 661 | goto end; |
647 | } | 662 | } |
648 | 663 | ||
649 | acpi_update_delay(battery->sbs); | ||
650 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x12, | ||
651 | &battery->state.average_time_to_empty); | ||
652 | if (result) { | ||
653 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
654 | "acpi_sbs_read_word() failed")); | ||
655 | goto end; | ||
656 | } | ||
657 | |||
658 | acpi_update_delay(battery->sbs); | ||
659 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x13, | ||
660 | &battery->state.average_time_to_full); | ||
661 | if (result) { | ||
662 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
663 | "acpi_sbs_read_word() failed")); | ||
664 | goto end; | ||
665 | } | ||
666 | |||
667 | acpi_update_delay(battery->sbs); | ||
668 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x16, | 664 | result = acpi_sbs_read_word(sbs, ACPI_SB_SMBUS_ADDR, 0x16, |
669 | &battery->state.battery_status); | 665 | &battery->state.battery_state); |
670 | if (result) { | 666 | if (result) { |
671 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 667 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
672 | "acpi_sbs_read_word() failed")); | 668 | "acpi_sbs_read_word() failed")); |
673 | goto end; | 669 | goto end; |
674 | } | 670 | } |
675 | 671 | ||
676 | acpi_update_delay(battery->sbs); | ||
677 | |||
678 | end: | 672 | end: |
679 | return result; | 673 | return result; |
680 | } | 674 | } |
@@ -692,8 +686,6 @@ static int acpi_battery_get_alarm(struct acpi_battery *battery) | |||
692 | goto end; | 686 | goto end; |
693 | } | 687 | } |
694 | 688 | ||
695 | acpi_update_delay(battery->sbs); | ||
696 | |||
697 | end: | 689 | end: |
698 | 690 | ||
699 | return result; | 691 | return result; |
@@ -751,6 +743,7 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery, | |||
751 | 743 | ||
752 | static int acpi_battery_set_mode(struct acpi_battery *battery) | 744 | static int acpi_battery_set_mode(struct acpi_battery *battery) |
753 | { | 745 | { |
746 | struct acpi_sbs *sbs = battery->sbs; | ||
754 | int result = 0; | 747 | int result = 0; |
755 | s16 battery_mode; | 748 | s16 battery_mode; |
756 | 749 | ||
@@ -758,7 +751,7 @@ static int acpi_battery_set_mode(struct acpi_battery *battery) | |||
758 | goto end; | 751 | goto end; |
759 | } | 752 | } |
760 | 753 | ||
761 | result = acpi_sbs_read_word(battery->sbs, | 754 | result = acpi_sbs_read_word(sbs, |
762 | ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode); | 755 | ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode); |
763 | if (result) { | 756 | if (result) { |
764 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 757 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
@@ -771,7 +764,7 @@ static int acpi_battery_set_mode(struct acpi_battery *battery) | |||
771 | } else { | 764 | } else { |
772 | battery_mode |= 0x8000; | 765 | battery_mode |= 0x8000; |
773 | } | 766 | } |
774 | result = acpi_sbs_write_word(battery->sbs, | 767 | result = acpi_sbs_write_word(sbs, |
775 | ACPI_SB_SMBUS_ADDR, 0x03, battery_mode); | 768 | ACPI_SB_SMBUS_ADDR, 0x03, battery_mode); |
776 | if (result) { | 769 | if (result) { |
777 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 770 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
@@ -779,7 +772,7 @@ static int acpi_battery_set_mode(struct acpi_battery *battery) | |||
779 | goto end; | 772 | goto end; |
780 | } | 773 | } |
781 | 774 | ||
782 | result = acpi_sbs_read_word(battery->sbs, | 775 | result = acpi_sbs_read_word(sbs, |
783 | ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode); | 776 | ACPI_SB_SMBUS_ADDR, 0x03, &battery_mode); |
784 | if (result) { | 777 | if (result) { |
785 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 778 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
@@ -798,7 +791,7 @@ static int acpi_battery_init(struct acpi_battery *battery) | |||
798 | result = acpi_battery_select(battery); | 791 | result = acpi_battery_select(battery); |
799 | if (result) { | 792 | if (result) { |
800 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 793 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
801 | "acpi_battery_init() failed")); | 794 | "acpi_battery_select() failed")); |
802 | goto end; | 795 | goto end; |
803 | } | 796 | } |
804 | 797 | ||
@@ -848,7 +841,7 @@ static int acpi_ac_get_present(struct acpi_sbs *sbs) | |||
848 | goto end; | 841 | goto end; |
849 | } | 842 | } |
850 | 843 | ||
851 | sbs->ac_present = (charger_status & 0x8000) >> 15; | 844 | sbs->ac.ac_present = (charger_status & 0x8000) >> 15; |
852 | 845 | ||
853 | end: | 846 | end: |
854 | 847 | ||
@@ -945,24 +938,27 @@ static struct proc_dir_entry *acpi_battery_dir = NULL; | |||
945 | static int acpi_battery_read_info(struct seq_file *seq, void *offset) | 938 | static int acpi_battery_read_info(struct seq_file *seq, void *offset) |
946 | { | 939 | { |
947 | struct acpi_battery *battery = seq->private; | 940 | struct acpi_battery *battery = seq->private; |
941 | struct acpi_sbs *sbs = battery->sbs; | ||
948 | int cscale; | 942 | int cscale; |
949 | int result = 0; | 943 | int result = 0; |
950 | 944 | ||
951 | if (battery->sbs->zombie) { | 945 | if (sbs_mutex_lock(sbs)) { |
952 | return -ENODEV; | 946 | return -ENODEV; |
953 | } | 947 | } |
954 | 948 | ||
955 | down(&sbs_sem); | 949 | result = acpi_check_update_proc(sbs); |
950 | if (result) | ||
951 | goto end; | ||
956 | 952 | ||
957 | if (update_mode == REQUEST_UPDATE_MODE) { | 953 | if (update_time == 0) { |
958 | result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_INFO); | 954 | result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_INFO); |
959 | if (result) { | 955 | if (result) { |
960 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 956 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
961 | "acpi_sbs_update_run() failed")); | 957 | "acpi_sbs_update_run() failed")); |
962 | } | 958 | } |
963 | } | 959 | } |
964 | 960 | ||
965 | if (acpi_battery_is_present(battery)) { | 961 | if (battery->battery_present) { |
966 | seq_printf(seq, "present: yes\n"); | 962 | seq_printf(seq, "present: yes\n"); |
967 | } else { | 963 | } else { |
968 | seq_printf(seq, "present: no\n"); | 964 | seq_printf(seq, "present: no\n"); |
@@ -974,13 +970,13 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset) | |||
974 | } else { | 970 | } else { |
975 | cscale = battery->info.ipscale; | 971 | cscale = battery->info.ipscale; |
976 | } | 972 | } |
977 | seq_printf(seq, "design capacity: %i%s", | 973 | seq_printf(seq, "design capacity: %i%s\n", |
978 | battery->info.design_capacity * cscale, | 974 | battery->info.design_capacity * cscale, |
979 | battery->info.capacity_mode ? "0 mWh\n" : " mAh\n"); | 975 | battery->info.capacity_mode ? "0 mWh" : " mAh"); |
980 | 976 | ||
981 | seq_printf(seq, "last full capacity: %i%s", | 977 | seq_printf(seq, "last full capacity: %i%s\n", |
982 | battery->info.full_charge_capacity * cscale, | 978 | battery->info.full_charge_capacity * cscale, |
983 | battery->info.capacity_mode ? "0 mWh\n" : " mAh\n"); | 979 | battery->info.capacity_mode ? "0 mWh" : " mAh"); |
984 | 980 | ||
985 | seq_printf(seq, "battery technology: rechargeable\n"); | 981 | seq_printf(seq, "battery technology: rechargeable\n"); |
986 | 982 | ||
@@ -1006,7 +1002,7 @@ static int acpi_battery_read_info(struct seq_file *seq, void *offset) | |||
1006 | 1002 | ||
1007 | end: | 1003 | end: |
1008 | 1004 | ||
1009 | up(&sbs_sem); | 1005 | sbs_mutex_unlock(sbs); |
1010 | 1006 | ||
1011 | return result; | 1007 | return result; |
1012 | } | 1008 | } |
@@ -1018,26 +1014,29 @@ static int acpi_battery_info_open_fs(struct inode *inode, struct file *file) | |||
1018 | 1014 | ||
1019 | static int acpi_battery_read_state(struct seq_file *seq, void *offset) | 1015 | static int acpi_battery_read_state(struct seq_file *seq, void *offset) |
1020 | { | 1016 | { |
1021 | struct acpi_battery *battery = (struct acpi_battery *)seq->private; | 1017 | struct acpi_battery *battery = seq->private; |
1018 | struct acpi_sbs *sbs = battery->sbs; | ||
1022 | int result = 0; | 1019 | int result = 0; |
1023 | int cscale; | 1020 | int cscale; |
1024 | int foo; | 1021 | int foo; |
1025 | 1022 | ||
1026 | if (battery->sbs->zombie) { | 1023 | if (sbs_mutex_lock(sbs)) { |
1027 | return -ENODEV; | 1024 | return -ENODEV; |
1028 | } | 1025 | } |
1029 | 1026 | ||
1030 | down(&sbs_sem); | 1027 | result = acpi_check_update_proc(sbs); |
1028 | if (result) | ||
1029 | goto end; | ||
1031 | 1030 | ||
1032 | if (update_mode == REQUEST_UPDATE_MODE) { | 1031 | if (update_time == 0) { |
1033 | result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_STATE); | 1032 | result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_STATE); |
1034 | if (result) { | 1033 | if (result) { |
1035 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 1034 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
1036 | "acpi_sbs_update_run() failed")); | 1035 | "acpi_sbs_update_run() failed")); |
1037 | } | 1036 | } |
1038 | } | 1037 | } |
1039 | 1038 | ||
1040 | if (acpi_battery_is_present(battery)) { | 1039 | if (battery->battery_present) { |
1041 | seq_printf(seq, "present: yes\n"); | 1040 | seq_printf(seq, "present: yes\n"); |
1042 | } else { | 1041 | } else { |
1043 | seq_printf(seq, "present: no\n"); | 1042 | seq_printf(seq, "present: no\n"); |
@@ -1050,7 +1049,7 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) | |||
1050 | cscale = battery->info.ipscale; | 1049 | cscale = battery->info.ipscale; |
1051 | } | 1050 | } |
1052 | 1051 | ||
1053 | if (battery->state.battery_status & 0x0010) { | 1052 | if (battery->state.battery_state & 0x0010) { |
1054 | seq_printf(seq, "capacity state: critical\n"); | 1053 | seq_printf(seq, "capacity state: critical\n"); |
1055 | } else { | 1054 | } else { |
1056 | seq_printf(seq, "capacity state: ok\n"); | 1055 | seq_printf(seq, "capacity state: ok\n"); |
@@ -1074,16 +1073,16 @@ static int acpi_battery_read_state(struct seq_file *seq, void *offset) | |||
1074 | battery->info.capacity_mode ? "mW" : "mA"); | 1073 | battery->info.capacity_mode ? "mW" : "mA"); |
1075 | } | 1074 | } |
1076 | 1075 | ||
1077 | seq_printf(seq, "remaining capacity: %i%s", | 1076 | seq_printf(seq, "remaining capacity: %i%s\n", |
1078 | battery->state.remaining_capacity * cscale, | 1077 | battery->state.remaining_capacity * cscale, |
1079 | battery->info.capacity_mode ? "0 mWh\n" : " mAh\n"); | 1078 | battery->info.capacity_mode ? "0 mWh" : " mAh"); |
1080 | 1079 | ||
1081 | seq_printf(seq, "present voltage: %i mV\n", | 1080 | seq_printf(seq, "present voltage: %i mV\n", |
1082 | battery->state.voltage * battery->info.vscale); | 1081 | battery->state.voltage * battery->info.vscale); |
1083 | 1082 | ||
1084 | end: | 1083 | end: |
1085 | 1084 | ||
1086 | up(&sbs_sem); | 1085 | sbs_mutex_unlock(sbs); |
1087 | 1086 | ||
1088 | return result; | 1087 | return result; |
1089 | } | 1088 | } |
@@ -1096,24 +1095,27 @@ static int acpi_battery_state_open_fs(struct inode *inode, struct file *file) | |||
1096 | static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) | 1095 | static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) |
1097 | { | 1096 | { |
1098 | struct acpi_battery *battery = seq->private; | 1097 | struct acpi_battery *battery = seq->private; |
1098 | struct acpi_sbs *sbs = battery->sbs; | ||
1099 | int result = 0; | 1099 | int result = 0; |
1100 | int cscale; | 1100 | int cscale; |
1101 | 1101 | ||
1102 | if (battery->sbs->zombie) { | 1102 | if (sbs_mutex_lock(sbs)) { |
1103 | return -ENODEV; | 1103 | return -ENODEV; |
1104 | } | 1104 | } |
1105 | 1105 | ||
1106 | down(&sbs_sem); | 1106 | result = acpi_check_update_proc(sbs); |
1107 | if (result) | ||
1108 | goto end; | ||
1107 | 1109 | ||
1108 | if (update_mode == REQUEST_UPDATE_MODE) { | 1110 | if (update_time == 0) { |
1109 | result = acpi_sbs_update_run(battery->sbs, DATA_TYPE_ALARM); | 1111 | result = acpi_sbs_update_run(sbs, battery->id, DATA_TYPE_ALARM); |
1110 | if (result) { | 1112 | if (result) { |
1111 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 1113 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
1112 | "acpi_sbs_update_run() failed")); | 1114 | "acpi_sbs_update_run() failed")); |
1113 | } | 1115 | } |
1114 | } | 1116 | } |
1115 | 1117 | ||
1116 | if (!acpi_battery_is_present(battery)) { | 1118 | if (!battery->battery_present) { |
1117 | seq_printf(seq, "present: no\n"); | 1119 | seq_printf(seq, "present: no\n"); |
1118 | goto end; | 1120 | goto end; |
1119 | } | 1121 | } |
@@ -1126,16 +1128,16 @@ static int acpi_battery_read_alarm(struct seq_file *seq, void *offset) | |||
1126 | 1128 | ||
1127 | seq_printf(seq, "alarm: "); | 1129 | seq_printf(seq, "alarm: "); |
1128 | if (battery->alarm.remaining_capacity) { | 1130 | if (battery->alarm.remaining_capacity) { |
1129 | seq_printf(seq, "%i%s", | 1131 | seq_printf(seq, "%i%s\n", |
1130 | battery->alarm.remaining_capacity * cscale, | 1132 | battery->alarm.remaining_capacity * cscale, |
1131 | battery->info.capacity_mode ? "0 mWh\n" : " mAh\n"); | 1133 | battery->info.capacity_mode ? "0 mWh" : " mAh"); |
1132 | } else { | 1134 | } else { |
1133 | seq_printf(seq, "disabled\n"); | 1135 | seq_printf(seq, "disabled\n"); |
1134 | } | 1136 | } |
1135 | 1137 | ||
1136 | end: | 1138 | end: |
1137 | 1139 | ||
1138 | up(&sbs_sem); | 1140 | sbs_mutex_unlock(sbs); |
1139 | 1141 | ||
1140 | return result; | 1142 | return result; |
1141 | } | 1143 | } |
@@ -1146,16 +1148,19 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer, | |||
1146 | { | 1148 | { |
1147 | struct seq_file *seq = file->private_data; | 1149 | struct seq_file *seq = file->private_data; |
1148 | struct acpi_battery *battery = seq->private; | 1150 | struct acpi_battery *battery = seq->private; |
1151 | struct acpi_sbs *sbs = battery->sbs; | ||
1149 | char alarm_string[12] = { '\0' }; | 1152 | char alarm_string[12] = { '\0' }; |
1150 | int result, old_alarm, new_alarm; | 1153 | int result, old_alarm, new_alarm; |
1151 | 1154 | ||
1152 | if (battery->sbs->zombie) { | 1155 | if (sbs_mutex_lock(sbs)) { |
1153 | return -ENODEV; | 1156 | return -ENODEV; |
1154 | } | 1157 | } |
1155 | 1158 | ||
1156 | down(&sbs_sem); | 1159 | result = acpi_check_update_proc(sbs); |
1160 | if (result) | ||
1161 | goto end; | ||
1157 | 1162 | ||
1158 | if (!acpi_battery_is_present(battery)) { | 1163 | if (!battery->battery_present) { |
1159 | result = -ENODEV; | 1164 | result = -ENODEV; |
1160 | goto end; | 1165 | goto end; |
1161 | } | 1166 | } |
@@ -1191,7 +1196,7 @@ acpi_battery_write_alarm(struct file *file, const char __user * buffer, | |||
1191 | } | 1196 | } |
1192 | 1197 | ||
1193 | end: | 1198 | end: |
1194 | up(&sbs_sem); | 1199 | sbs_mutex_unlock(sbs); |
1195 | 1200 | ||
1196 | if (result) { | 1201 | if (result) { |
1197 | return result; | 1202 | return result; |
@@ -1239,14 +1244,12 @@ static int acpi_ac_read_state(struct seq_file *seq, void *offset) | |||
1239 | struct acpi_sbs *sbs = seq->private; | 1244 | struct acpi_sbs *sbs = seq->private; |
1240 | int result; | 1245 | int result; |
1241 | 1246 | ||
1242 | if (sbs->zombie) { | 1247 | if (sbs_mutex_lock(sbs)) { |
1243 | return -ENODEV; | 1248 | return -ENODEV; |
1244 | } | 1249 | } |
1245 | 1250 | ||
1246 | down(&sbs_sem); | 1251 | if (update_time == 0) { |
1247 | 1252 | result = acpi_sbs_update_run(sbs, -1, DATA_TYPE_AC_STATE); | |
1248 | if (update_mode == REQUEST_UPDATE_MODE) { | ||
1249 | result = acpi_sbs_update_run(sbs, DATA_TYPE_AC_STATE); | ||
1250 | if (result) { | 1253 | if (result) { |
1251 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 1254 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
1252 | "acpi_sbs_update_run() failed")); | 1255 | "acpi_sbs_update_run() failed")); |
@@ -1254,9 +1257,9 @@ static int acpi_ac_read_state(struct seq_file *seq, void *offset) | |||
1254 | } | 1257 | } |
1255 | 1258 | ||
1256 | seq_printf(seq, "state: %s\n", | 1259 | seq_printf(seq, "state: %s\n", |
1257 | sbs->ac_present ? "on-line" : "off-line"); | 1260 | sbs->ac.ac_present ? "on-line" : "off-line"); |
1258 | 1261 | ||
1259 | up(&sbs_sem); | 1262 | sbs_mutex_unlock(sbs); |
1260 | 1263 | ||
1261 | return 0; | 1264 | return 0; |
1262 | } | 1265 | } |
@@ -1309,7 +1312,7 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) | |||
1309 | goto end; | 1312 | goto end; |
1310 | } | 1313 | } |
1311 | 1314 | ||
1312 | is_present = acpi_battery_is_present(battery); | 1315 | is_present = battery->battery_present; |
1313 | 1316 | ||
1314 | if (is_present) { | 1317 | if (is_present) { |
1315 | result = acpi_battery_init(battery); | 1318 | result = acpi_battery_init(battery); |
@@ -1336,6 +1339,10 @@ static int acpi_battery_add(struct acpi_sbs *sbs, int id) | |||
1336 | } | 1339 | } |
1337 | battery->alive = 1; | 1340 | battery->alive = 1; |
1338 | 1341 | ||
1342 | printk(KERN_INFO PREFIX "%s [%s]: Battery Slot [%s] (battery %s)\n", | ||
1343 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), dir_name, | ||
1344 | sbs->battery->battery_present ? "present" : "absent"); | ||
1345 | |||
1339 | end: | 1346 | end: |
1340 | return result; | 1347 | return result; |
1341 | } | 1348 | } |
@@ -1370,6 +1377,10 @@ static int acpi_ac_add(struct acpi_sbs *sbs) | |||
1370 | goto end; | 1377 | goto end; |
1371 | } | 1378 | } |
1372 | 1379 | ||
1380 | printk(KERN_INFO PREFIX "%s [%s]: AC Adapter [%s] (%s)\n", | ||
1381 | ACPI_SBS_DEVICE_NAME, acpi_device_bid(sbs->device), | ||
1382 | ACPI_AC_DIR_NAME, sbs->ac.ac_present ? "on-line" : "off-line"); | ||
1383 | |||
1373 | end: | 1384 | end: |
1374 | 1385 | ||
1375 | return result; | 1386 | return result; |
@@ -1383,29 +1394,48 @@ static void acpi_ac_remove(struct acpi_sbs *sbs) | |||
1383 | } | 1394 | } |
1384 | } | 1395 | } |
1385 | 1396 | ||
1386 | static void acpi_sbs_update_queue_run(unsigned long data) | 1397 | static void acpi_sbs_update_time_run(unsigned long data) |
1387 | { | 1398 | { |
1388 | acpi_os_execute(OSL_GPE_HANDLER, acpi_sbs_update_queue, (void *)data); | 1399 | acpi_os_execute(OSL_GPE_HANDLER, acpi_sbs_update_time, (void *)data); |
1389 | } | 1400 | } |
1390 | 1401 | ||
1391 | static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type) | 1402 | static int acpi_sbs_update_run(struct acpi_sbs *sbs, int id, int data_type) |
1392 | { | 1403 | { |
1393 | struct acpi_battery *battery; | 1404 | struct acpi_battery *battery; |
1394 | int result = 0; | 1405 | int result = 0, cnt; |
1395 | int old_ac_present; | 1406 | int old_ac_present = -1; |
1396 | int old_battery_present; | 1407 | int old_battery_present = -1; |
1397 | int new_ac_present; | 1408 | int new_ac_present = -1; |
1398 | int new_battery_present; | 1409 | int new_battery_present = -1; |
1399 | int id; | 1410 | int id_min = 0, id_max = MAX_SBS_BAT - 1; |
1400 | char dir_name[32]; | 1411 | char dir_name[32]; |
1401 | int do_battery_init, do_ac_init; | 1412 | int do_battery_init = 0, do_ac_init = 0; |
1402 | s16 old_remaining_capacity; | 1413 | int old_remaining_capacity = 0; |
1414 | int update_ac = 1, update_battery = 1; | ||
1415 | int up_tm = update_time; | ||
1416 | |||
1417 | if (sbs_zombie(sbs)) { | ||
1418 | goto end; | ||
1419 | } | ||
1403 | 1420 | ||
1404 | if (sbs->zombie) { | 1421 | if (id >= 0) { |
1422 | id_min = id_max = id; | ||
1423 | } | ||
1424 | |||
1425 | if (data_type == DATA_TYPE_COMMON && up_tm > 0) { | ||
1426 | cnt = up_tm / (up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm); | ||
1427 | if (sbs->run_cnt % cnt != 0) { | ||
1428 | update_battery = 0; | ||
1429 | } | ||
1430 | } | ||
1431 | |||
1432 | sbs->run_cnt++; | ||
1433 | |||
1434 | if (!update_ac && !update_battery) { | ||
1405 | goto end; | 1435 | goto end; |
1406 | } | 1436 | } |
1407 | 1437 | ||
1408 | old_ac_present = acpi_ac_is_present(sbs); | 1438 | old_ac_present = sbs->ac.ac_present; |
1409 | 1439 | ||
1410 | result = acpi_ac_get_present(sbs); | 1440 | result = acpi_ac_get_present(sbs); |
1411 | if (result) { | 1441 | if (result) { |
@@ -1413,15 +1443,36 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type) | |||
1413 | "acpi_ac_get_present() failed")); | 1443 | "acpi_ac_get_present() failed")); |
1414 | } | 1444 | } |
1415 | 1445 | ||
1416 | new_ac_present = acpi_ac_is_present(sbs); | 1446 | new_ac_present = sbs->ac.ac_present; |
1417 | 1447 | ||
1418 | do_ac_init = (old_ac_present != new_ac_present); | 1448 | do_ac_init = (old_ac_present != new_ac_present); |
1449 | if (sbs->run_cnt == 1 && data_type == DATA_TYPE_COMMON) { | ||
1450 | do_ac_init = 1; | ||
1451 | } | ||
1419 | 1452 | ||
1420 | if (data_type == DATA_TYPE_AC_STATE) { | 1453 | if (do_ac_init) { |
1454 | result = acpi_sbs_generate_event(sbs->device, | ||
1455 | ACPI_SBS_AC_NOTIFY_STATUS, | ||
1456 | new_ac_present, | ||
1457 | ACPI_AC_DIR_NAME, | ||
1458 | ACPI_AC_CLASS); | ||
1459 | if (result) { | ||
1460 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
1461 | "acpi_sbs_generate_event() failed")); | ||
1462 | } | ||
1463 | } | ||
1464 | |||
1465 | if (data_type == DATA_TYPE_COMMON) { | ||
1466 | if (!do_ac_init && !update_battery) { | ||
1467 | goto end; | ||
1468 | } | ||
1469 | } | ||
1470 | |||
1471 | if (data_type == DATA_TYPE_AC_STATE && !do_ac_init) { | ||
1421 | goto end; | 1472 | goto end; |
1422 | } | 1473 | } |
1423 | 1474 | ||
1424 | for (id = 0; id < MAX_SBS_BAT; id++) { | 1475 | for (id = id_min; id <= id_max; id++) { |
1425 | battery = &sbs->battery[id]; | 1476 | battery = &sbs->battery[id]; |
1426 | if (battery->alive == 0) { | 1477 | if (battery->alive == 0) { |
1427 | continue; | 1478 | continue; |
@@ -1429,41 +1480,27 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type) | |||
1429 | 1480 | ||
1430 | old_remaining_capacity = battery->state.remaining_capacity; | 1481 | old_remaining_capacity = battery->state.remaining_capacity; |
1431 | 1482 | ||
1432 | old_battery_present = acpi_battery_is_present(battery); | 1483 | old_battery_present = battery->battery_present; |
1433 | 1484 | ||
1434 | result = acpi_battery_select(battery); | 1485 | result = acpi_battery_select(battery); |
1435 | if (result) { | 1486 | if (result) { |
1436 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 1487 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
1437 | "acpi_battery_select() failed")); | 1488 | "acpi_battery_select() failed")); |
1438 | } | 1489 | } |
1439 | if (sbs->zombie) { | ||
1440 | goto end; | ||
1441 | } | ||
1442 | 1490 | ||
1443 | result = acpi_battery_get_present(battery); | 1491 | result = acpi_battery_get_present(battery); |
1444 | if (result) { | 1492 | if (result) { |
1445 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 1493 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
1446 | "acpi_battery_get_present() failed")); | 1494 | "acpi_battery_get_present() failed")); |
1447 | } | 1495 | } |
1448 | if (sbs->zombie) { | ||
1449 | goto end; | ||
1450 | } | ||
1451 | 1496 | ||
1452 | new_battery_present = acpi_battery_is_present(battery); | 1497 | new_battery_present = battery->battery_present; |
1453 | 1498 | ||
1454 | do_battery_init = ((old_battery_present != new_battery_present) | 1499 | do_battery_init = ((old_battery_present != new_battery_present) |
1455 | && new_battery_present); | 1500 | && new_battery_present); |
1456 | 1501 | if (!new_battery_present) | |
1457 | if (sbs->zombie) { | 1502 | goto event; |
1458 | goto end; | 1503 | if (do_ac_init || do_battery_init) { |
1459 | } | ||
1460 | if (do_ac_init || do_battery_init || | ||
1461 | update_info_mode || sbs->update_info_mode) { | ||
1462 | if (sbs->update_info_mode) { | ||
1463 | sbs->update_info_mode = 0; | ||
1464 | } else { | ||
1465 | sbs->update_info_mode = 1; | ||
1466 | } | ||
1467 | result = acpi_battery_init(battery); | 1504 | result = acpi_battery_init(battery); |
1468 | if (result) { | 1505 | if (result) { |
1469 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 1506 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
@@ -1471,52 +1508,64 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type) | |||
1471 | "failed")); | 1508 | "failed")); |
1472 | } | 1509 | } |
1473 | } | 1510 | } |
1474 | if (data_type == DATA_TYPE_INFO) { | 1511 | if (sbs_zombie(sbs)) { |
1475 | continue; | ||
1476 | } | ||
1477 | |||
1478 | if (sbs->zombie) { | ||
1479 | goto end; | 1512 | goto end; |
1480 | } | 1513 | } |
1481 | if (new_battery_present) { | 1514 | |
1482 | result = acpi_battery_get_alarm(battery); | 1515 | if ((data_type == DATA_TYPE_COMMON |
1516 | || data_type == DATA_TYPE_INFO) | ||
1517 | && new_battery_present) { | ||
1518 | result = acpi_battery_get_info(battery); | ||
1483 | if (result) { | 1519 | if (result) { |
1484 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 1520 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
1485 | "acpi_battery_get_alarm() " | 1521 | "acpi_battery_get_info() failed")); |
1486 | "failed")); | ||
1487 | } | ||
1488 | if (data_type == DATA_TYPE_ALARM) { | ||
1489 | continue; | ||
1490 | } | 1522 | } |
1523 | } | ||
1524 | if (data_type == DATA_TYPE_INFO) { | ||
1525 | continue; | ||
1526 | } | ||
1527 | if (sbs_zombie(sbs)) { | ||
1528 | goto end; | ||
1529 | } | ||
1491 | 1530 | ||
1531 | if ((data_type == DATA_TYPE_COMMON | ||
1532 | || data_type == DATA_TYPE_STATE) | ||
1533 | && new_battery_present) { | ||
1492 | result = acpi_battery_get_state(battery); | 1534 | result = acpi_battery_get_state(battery); |
1493 | if (result) { | 1535 | if (result) { |
1494 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 1536 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
1495 | "acpi_battery_get_state() " | 1537 | "acpi_battery_get_state() failed")); |
1496 | "failed")); | ||
1497 | } | 1538 | } |
1498 | } | 1539 | } |
1499 | if (sbs->zombie) { | 1540 | if (data_type == DATA_TYPE_STATE) { |
1500 | goto end; | 1541 | goto event; |
1501 | } | 1542 | } |
1502 | if (data_type != DATA_TYPE_COMMON) { | 1543 | if (sbs_zombie(sbs)) { |
1503 | continue; | 1544 | goto end; |
1504 | } | 1545 | } |
1505 | 1546 | ||
1506 | if (old_battery_present != new_battery_present) { | 1547 | if ((data_type == DATA_TYPE_COMMON |
1507 | sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); | 1548 | || data_type == DATA_TYPE_ALARM) |
1508 | result = acpi_sbs_generate_event(sbs->device, | 1549 | && new_battery_present) { |
1509 | ACPI_SBS_BATTERY_NOTIFY_STATUS, | 1550 | result = acpi_battery_get_alarm(battery); |
1510 | new_battery_present, | ||
1511 | dir_name, | ||
1512 | ACPI_BATTERY_CLASS); | ||
1513 | if (result) { | 1551 | if (result) { |
1514 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 1552 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
1515 | "acpi_sbs_generate_event() " | 1553 | "acpi_battery_get_alarm() " |
1516 | "failed")); | 1554 | "failed")); |
1517 | } | 1555 | } |
1518 | } | 1556 | } |
1519 | if (old_remaining_capacity != battery->state.remaining_capacity) { | 1557 | if (data_type == DATA_TYPE_ALARM) { |
1558 | continue; | ||
1559 | } | ||
1560 | if (sbs_zombie(sbs)) { | ||
1561 | goto end; | ||
1562 | } | ||
1563 | |||
1564 | event: | ||
1565 | |||
1566 | if (old_battery_present != new_battery_present || do_ac_init || | ||
1567 | old_remaining_capacity != | ||
1568 | battery->state.remaining_capacity) { | ||
1520 | sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); | 1569 | sprintf(dir_name, ACPI_BATTERY_DIR_NAME, id); |
1521 | result = acpi_sbs_generate_event(sbs->device, | 1570 | result = acpi_sbs_generate_event(sbs->device, |
1522 | ACPI_SBS_BATTERY_NOTIFY_STATUS, | 1571 | ACPI_SBS_BATTERY_NOTIFY_STATUS, |
@@ -1525,71 +1574,62 @@ static int acpi_sbs_update_run(struct acpi_sbs *sbs, int data_type) | |||
1525 | ACPI_BATTERY_CLASS); | 1574 | ACPI_BATTERY_CLASS); |
1526 | if (result) { | 1575 | if (result) { |
1527 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 1576 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
1528 | "acpi_sbs_generate_event() failed")); | 1577 | "acpi_sbs_generate_event() " |
1578 | "failed")); | ||
1529 | } | 1579 | } |
1530 | } | 1580 | } |
1531 | |||
1532 | } | ||
1533 | if (sbs->zombie) { | ||
1534 | goto end; | ||
1535 | } | ||
1536 | if (data_type != DATA_TYPE_COMMON) { | ||
1537 | goto end; | ||
1538 | } | ||
1539 | |||
1540 | if (old_ac_present != new_ac_present) { | ||
1541 | result = acpi_sbs_generate_event(sbs->device, | ||
1542 | ACPI_SBS_AC_NOTIFY_STATUS, | ||
1543 | new_ac_present, | ||
1544 | ACPI_AC_DIR_NAME, | ||
1545 | ACPI_AC_CLASS); | ||
1546 | if (result) { | ||
1547 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
1548 | "acpi_sbs_generate_event() failed")); | ||
1549 | } | ||
1550 | } | 1581 | } |
1551 | 1582 | ||
1552 | end: | 1583 | end: |
1584 | |||
1553 | return result; | 1585 | return result; |
1554 | } | 1586 | } |
1555 | 1587 | ||
1556 | static void acpi_sbs_update_queue(void *data) | 1588 | static void acpi_sbs_update_time(void *data) |
1557 | { | 1589 | { |
1558 | struct acpi_sbs *sbs = data; | 1590 | struct acpi_sbs *sbs = data; |
1559 | unsigned long delay = -1; | 1591 | unsigned long delay = -1; |
1560 | int result; | 1592 | int result; |
1593 | unsigned int up_tm = update_time; | ||
1561 | 1594 | ||
1562 | if (sbs->zombie) { | 1595 | if (sbs_mutex_lock(sbs)) |
1563 | goto end; | 1596 | return; |
1564 | } | ||
1565 | 1597 | ||
1566 | result = acpi_sbs_update_run(sbs, DATA_TYPE_COMMON); | 1598 | result = acpi_sbs_update_run(sbs, -1, DATA_TYPE_COMMON); |
1567 | if (result) { | 1599 | if (result) { |
1568 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 1600 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
1569 | "acpi_sbs_update_run() failed")); | 1601 | "acpi_sbs_update_run() failed")); |
1570 | } | 1602 | } |
1571 | 1603 | ||
1572 | if (sbs->zombie) { | 1604 | if (sbs_zombie(sbs)) { |
1573 | goto end; | 1605 | goto end; |
1574 | } | 1606 | } |
1575 | 1607 | ||
1576 | if (update_mode == REQUEST_UPDATE_MODE) { | 1608 | if (!up_tm) { |
1577 | goto end; | 1609 | if (timer_pending(&sbs->update_timer)) |
1610 | del_timer(&sbs->update_timer); | ||
1611 | } else { | ||
1612 | delay = (up_tm > UPDATE_DELAY ? UPDATE_DELAY : up_tm); | ||
1613 | delay = jiffies + HZ * delay; | ||
1614 | if (timer_pending(&sbs->update_timer)) { | ||
1615 | mod_timer(&sbs->update_timer, delay); | ||
1616 | } else { | ||
1617 | sbs->update_timer.data = (unsigned long)data; | ||
1618 | sbs->update_timer.function = acpi_sbs_update_time_run; | ||
1619 | sbs->update_timer.expires = delay; | ||
1620 | add_timer(&sbs->update_timer); | ||
1621 | } | ||
1578 | } | 1622 | } |
1579 | 1623 | ||
1580 | delay = jiffies + HZ * update_time; | ||
1581 | sbs->update_timer.data = (unsigned long)data; | ||
1582 | sbs->update_timer.function = acpi_sbs_update_queue_run; | ||
1583 | sbs->update_timer.expires = delay; | ||
1584 | add_timer(&sbs->update_timer); | ||
1585 | end: | 1624 | end: |
1586 | ; | 1625 | |
1626 | sbs_mutex_unlock(sbs); | ||
1587 | } | 1627 | } |
1588 | 1628 | ||
1589 | static int acpi_sbs_add(struct acpi_device *device) | 1629 | static int acpi_sbs_add(struct acpi_device *device) |
1590 | { | 1630 | { |
1591 | struct acpi_sbs *sbs = NULL; | 1631 | struct acpi_sbs *sbs = NULL; |
1592 | int result; | 1632 | int result = 0, remove_result = 0; |
1593 | unsigned long sbs_obj; | 1633 | unsigned long sbs_obj; |
1594 | int id; | 1634 | int id; |
1595 | acpi_status status = AE_OK; | 1635 | acpi_status status = AE_OK; |
@@ -1604,33 +1644,34 @@ static int acpi_sbs_add(struct acpi_device *device) | |||
1604 | 1644 | ||
1605 | sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); | 1645 | sbs = kzalloc(sizeof(struct acpi_sbs), GFP_KERNEL); |
1606 | if (!sbs) { | 1646 | if (!sbs) { |
1607 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "kmalloc() failed")); | 1647 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "kzalloc() failed")); |
1608 | return -ENOMEM; | 1648 | result = -ENOMEM; |
1649 | goto end; | ||
1609 | } | 1650 | } |
1610 | sbs->base = (val & 0xff00ull) >> 8; | ||
1611 | 1651 | ||
1652 | mutex_init(&sbs->mutex); | ||
1653 | |||
1654 | sbs_mutex_lock(sbs); | ||
1655 | |||
1656 | sbs->base = (val & 0xff00ull) >> 8; | ||
1612 | sbs->device = device; | 1657 | sbs->device = device; |
1613 | 1658 | ||
1614 | strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); | 1659 | strcpy(acpi_device_name(device), ACPI_SBS_DEVICE_NAME); |
1615 | strcpy(acpi_device_class(device), ACPI_SBS_CLASS); | 1660 | strcpy(acpi_device_class(device), ACPI_SBS_CLASS); |
1616 | acpi_driver_data(device) = sbs; | 1661 | acpi_driver_data(device) = sbs; |
1617 | 1662 | ||
1618 | sbs->update_time = 0; | ||
1619 | sbs->update_time2 = 0; | ||
1620 | |||
1621 | result = acpi_ac_add(sbs); | 1663 | result = acpi_ac_add(sbs); |
1622 | if (result) { | 1664 | if (result) { |
1623 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_ac_add() failed")); | 1665 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_ac_add() failed")); |
1624 | goto end; | 1666 | goto end; |
1625 | } | 1667 | } |
1626 | result = acpi_evaluate_integer(device->handle, "_SBS", NULL, &sbs_obj); | 1668 | status = acpi_evaluate_integer(device->handle, "_SBS", NULL, &sbs_obj); |
1627 | if (ACPI_FAILURE(result)) { | 1669 | if (status) { |
1628 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 1670 | ACPI_EXCEPTION((AE_INFO, status, |
1629 | "acpi_evaluate_integer() failed")); | 1671 | "acpi_evaluate_integer() failed")); |
1630 | result = -EIO; | 1672 | result = -EIO; |
1631 | goto end; | 1673 | goto end; |
1632 | } | 1674 | } |
1633 | |||
1634 | if (sbs_obj > 0) { | 1675 | if (sbs_obj > 0) { |
1635 | result = acpi_sbsm_get_info(sbs); | 1676 | result = acpi_sbsm_get_info(sbs); |
1636 | if (result) { | 1677 | if (result) { |
@@ -1640,6 +1681,7 @@ static int acpi_sbs_add(struct acpi_device *device) | |||
1640 | } | 1681 | } |
1641 | sbs->sbsm_present = 1; | 1682 | sbs->sbsm_present = 1; |
1642 | } | 1683 | } |
1684 | |||
1643 | if (sbs->sbsm_present == 0) { | 1685 | if (sbs->sbsm_present == 0) { |
1644 | result = acpi_battery_add(sbs, 0); | 1686 | result = acpi_battery_add(sbs, 0); |
1645 | if (result) { | 1687 | if (result) { |
@@ -1653,8 +1695,7 @@ static int acpi_sbs_add(struct acpi_device *device) | |||
1653 | result = acpi_battery_add(sbs, id); | 1695 | result = acpi_battery_add(sbs, id); |
1654 | if (result) { | 1696 | if (result) { |
1655 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 1697 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
1656 | "acpi_battery_add() " | 1698 | "acpi_battery_add() failed")); |
1657 | "failed")); | ||
1658 | goto end; | 1699 | goto end; |
1659 | } | 1700 | } |
1660 | } | 1701 | } |
@@ -1664,29 +1705,26 @@ static int acpi_sbs_add(struct acpi_device *device) | |||
1664 | sbs->handle = device->handle; | 1705 | sbs->handle = device->handle; |
1665 | 1706 | ||
1666 | init_timer(&sbs->update_timer); | 1707 | init_timer(&sbs->update_timer); |
1667 | if (update_mode == QUEUE_UPDATE_MODE) { | 1708 | result = acpi_check_update_proc(sbs); |
1668 | status = acpi_os_execute(OSL_GPE_HANDLER, | 1709 | if (result) |
1669 | acpi_sbs_update_queue, sbs); | 1710 | goto end; |
1670 | if (status != AE_OK) { | ||
1671 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
1672 | "acpi_os_execute() failed")); | ||
1673 | } | ||
1674 | } | ||
1675 | sbs->update_time = update_time; | ||
1676 | sbs->update_time2 = update_time2; | ||
1677 | |||
1678 | printk(KERN_INFO PREFIX "%s [%s]\n", | ||
1679 | acpi_device_name(device), acpi_device_bid(device)); | ||
1680 | 1711 | ||
1681 | end: | 1712 | end: |
1713 | |||
1714 | sbs_mutex_unlock(sbs); | ||
1715 | |||
1682 | if (result) { | 1716 | if (result) { |
1683 | acpi_sbs_remove(device, 0); | 1717 | remove_result = acpi_sbs_remove(device, 0); |
1718 | if (remove_result) { | ||
1719 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | ||
1720 | "acpi_sbs_remove() failed")); | ||
1721 | } | ||
1684 | } | 1722 | } |
1685 | 1723 | ||
1686 | return result; | 1724 | return result; |
1687 | } | 1725 | } |
1688 | 1726 | ||
1689 | int acpi_sbs_remove(struct acpi_device *device, int type) | 1727 | static int acpi_sbs_remove(struct acpi_device *device, int type) |
1690 | { | 1728 | { |
1691 | struct acpi_sbs *sbs; | 1729 | struct acpi_sbs *sbs; |
1692 | int id; | 1730 | int id; |
@@ -1695,15 +1733,14 @@ int acpi_sbs_remove(struct acpi_device *device, int type) | |||
1695 | return -EINVAL; | 1733 | return -EINVAL; |
1696 | } | 1734 | } |
1697 | 1735 | ||
1698 | sbs = (struct acpi_sbs *)acpi_driver_data(device); | 1736 | sbs = acpi_driver_data(device); |
1699 | |||
1700 | if (!sbs) { | 1737 | if (!sbs) { |
1701 | return -EINVAL; | 1738 | return -EINVAL; |
1702 | } | 1739 | } |
1703 | 1740 | ||
1741 | sbs_mutex_lock(sbs); | ||
1742 | |||
1704 | sbs->zombie = 1; | 1743 | sbs->zombie = 1; |
1705 | sbs->update_time = 0; | ||
1706 | sbs->update_time2 = 0; | ||
1707 | del_timer_sync(&sbs->update_timer); | 1744 | del_timer_sync(&sbs->update_timer); |
1708 | acpi_os_wait_events_complete(NULL); | 1745 | acpi_os_wait_events_complete(NULL); |
1709 | del_timer_sync(&sbs->update_timer); | 1746 | del_timer_sync(&sbs->update_timer); |
@@ -1714,13 +1751,41 @@ int acpi_sbs_remove(struct acpi_device *device, int type) | |||
1714 | 1751 | ||
1715 | acpi_ac_remove(sbs); | 1752 | acpi_ac_remove(sbs); |
1716 | 1753 | ||
1717 | acpi_driver_data(device) = NULL; | 1754 | sbs_mutex_unlock(sbs); |
1755 | |||
1756 | mutex_destroy(&sbs->mutex); | ||
1718 | 1757 | ||
1719 | kfree(sbs); | 1758 | kfree(sbs); |
1720 | 1759 | ||
1721 | return 0; | 1760 | return 0; |
1722 | } | 1761 | } |
1723 | 1762 | ||
1763 | static void acpi_sbs_rmdirs(void) | ||
1764 | { | ||
1765 | if (acpi_ac_dir) { | ||
1766 | acpi_unlock_ac_dir(acpi_ac_dir); | ||
1767 | acpi_ac_dir = NULL; | ||
1768 | } | ||
1769 | if (acpi_battery_dir) { | ||
1770 | acpi_unlock_battery_dir(acpi_battery_dir); | ||
1771 | acpi_battery_dir = NULL; | ||
1772 | } | ||
1773 | } | ||
1774 | |||
1775 | static int acpi_sbs_resume(struct acpi_device *device) | ||
1776 | { | ||
1777 | struct acpi_sbs *sbs; | ||
1778 | |||
1779 | if (!device) | ||
1780 | return -EINVAL; | ||
1781 | |||
1782 | sbs = device->driver_data; | ||
1783 | |||
1784 | sbs->run_cnt = 0; | ||
1785 | |||
1786 | return 0; | ||
1787 | } | ||
1788 | |||
1724 | static int __init acpi_sbs_init(void) | 1789 | static int __init acpi_sbs_init(void) |
1725 | { | 1790 | { |
1726 | int result = 0; | 1791 | int result = 0; |
@@ -1728,12 +1793,10 @@ static int __init acpi_sbs_init(void) | |||
1728 | if (acpi_disabled) | 1793 | if (acpi_disabled) |
1729 | return -ENODEV; | 1794 | return -ENODEV; |
1730 | 1795 | ||
1731 | init_MUTEX(&sbs_sem); | ||
1732 | |||
1733 | if (capacity_mode != DEF_CAPACITY_UNIT | 1796 | if (capacity_mode != DEF_CAPACITY_UNIT |
1734 | && capacity_mode != MAH_CAPACITY_UNIT | 1797 | && capacity_mode != MAH_CAPACITY_UNIT |
1735 | && capacity_mode != MWH_CAPACITY_UNIT) { | 1798 | && capacity_mode != MWH_CAPACITY_UNIT) { |
1736 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, "acpi_sbs_init: " | 1799 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
1737 | "invalid capacity_mode = %d", capacity_mode)); | 1800 | "invalid capacity_mode = %d", capacity_mode)); |
1738 | return -EINVAL; | 1801 | return -EINVAL; |
1739 | } | 1802 | } |
@@ -1749,6 +1812,7 @@ static int __init acpi_sbs_init(void) | |||
1749 | if (!acpi_battery_dir) { | 1812 | if (!acpi_battery_dir) { |
1750 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 1813 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
1751 | "acpi_lock_battery_dir() failed")); | 1814 | "acpi_lock_battery_dir() failed")); |
1815 | acpi_sbs_rmdirs(); | ||
1752 | return -ENODEV; | 1816 | return -ENODEV; |
1753 | } | 1817 | } |
1754 | 1818 | ||
@@ -1756,6 +1820,7 @@ static int __init acpi_sbs_init(void) | |||
1756 | if (result < 0) { | 1820 | if (result < 0) { |
1757 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, | 1821 | ACPI_EXCEPTION((AE_INFO, AE_ERROR, |
1758 | "acpi_bus_register_driver() failed")); | 1822 | "acpi_bus_register_driver() failed")); |
1823 | acpi_sbs_rmdirs(); | ||
1759 | return -ENODEV; | 1824 | return -ENODEV; |
1760 | } | 1825 | } |
1761 | 1826 | ||
@@ -1764,13 +1829,9 @@ static int __init acpi_sbs_init(void) | |||
1764 | 1829 | ||
1765 | static void __exit acpi_sbs_exit(void) | 1830 | static void __exit acpi_sbs_exit(void) |
1766 | { | 1831 | { |
1767 | |||
1768 | acpi_bus_unregister_driver(&acpi_sbs_driver); | 1832 | acpi_bus_unregister_driver(&acpi_sbs_driver); |
1769 | 1833 | ||
1770 | acpi_unlock_ac_dir(acpi_ac_dir); | 1834 | acpi_sbs_rmdirs(); |
1771 | acpi_ac_dir = NULL; | ||
1772 | acpi_unlock_battery_dir(acpi_battery_dir); | ||
1773 | acpi_battery_dir = NULL; | ||
1774 | 1835 | ||
1775 | return; | 1836 | return; |
1776 | } | 1837 | } |