aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/asus_acpi.c1
-rw-r--r--drivers/acpi/battery.c47
-rw-r--r--drivers/acpi/bay.c2
-rw-r--r--drivers/acpi/dock.c6
-rw-r--r--drivers/acpi/ec.c113
-rw-r--r--drivers/acpi/tables/tbxface.c23
-rw-r--r--drivers/acpi/thermal.c143
7 files changed, 219 insertions, 116 deletions
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c
index 9c4bd220c44..86fd142f4bf 100644
--- a/drivers/acpi/asus_acpi.c
+++ b/drivers/acpi/asus_acpi.c
@@ -1192,6 +1192,7 @@ static int asus_hotk_get_info(void)
1192 break; 1192 break;
1193 default: 1193 default:
1194 kfree(model); 1194 kfree(model);
1195 model = NULL;
1195 break; 1196 break;
1196 } 1197 }
1197 } 1198 }
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 81651032791..d7b499fe0cd 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -113,7 +113,7 @@ struct acpi_battery_info {
113 acpi_string oem_info; 113 acpi_string oem_info;
114}; 114};
115 115
116enum acpi_battery_files{ 116enum acpi_battery_files {
117 ACPI_BATTERY_INFO = 0, 117 ACPI_BATTERY_INFO = 0,
118 ACPI_BATTERY_STATE, 118 ACPI_BATTERY_STATE,
119 ACPI_BATTERY_ALARM, 119 ACPI_BATTERY_ALARM,
@@ -129,13 +129,14 @@ struct acpi_battery_flags {
129}; 129};
130 130
131struct acpi_battery { 131struct acpi_battery {
132 struct mutex mutex;
133 struct acpi_device *device; 132 struct acpi_device *device;
134 struct acpi_battery_flags flags; 133 struct acpi_battery_flags flags;
135 struct acpi_buffer bif_data; 134 struct acpi_buffer bif_data;
136 struct acpi_buffer bst_data; 135 struct acpi_buffer bst_data;
136 struct mutex lock;
137 unsigned long alarm; 137 unsigned long alarm;
138 unsigned long update_time[ACPI_BATTERY_NUMFILES]; 138 unsigned long update_time[ACPI_BATTERY_NUMFILES];
139
139}; 140};
140 141
141inline int acpi_battery_present(struct acpi_battery *battery) 142inline int acpi_battery_present(struct acpi_battery *battery)
@@ -235,10 +236,10 @@ static int acpi_battery_get_info(struct acpi_battery *battery)
235 return 0; 236 return 0;
236 237
237 /* Evaluate _BIF */ 238 /* Evaluate _BIF */
238 239 mutex_lock(&battery->lock);
239 status = 240 status = acpi_evaluate_object(acpi_battery_handle(battery), "_BIF",
240 acpi_evaluate_object(acpi_battery_handle(battery), "_BIF", NULL, 241 NULL, &buffer);
241 &buffer); 242 mutex_unlock(&battery->lock);
242 if (ACPI_FAILURE(status)) { 243 if (ACPI_FAILURE(status)) {
243 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF")); 244 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BIF"));
244 return -ENODEV; 245 return -ENODEV;
@@ -285,10 +286,10 @@ static int acpi_battery_get_state(struct acpi_battery *battery)
285 return 0; 286 return 0;
286 287
287 /* Evaluate _BST */ 288 /* Evaluate _BST */
288 289 mutex_lock(&battery->lock);
289 status = 290 status = acpi_evaluate_object(acpi_battery_handle(battery), "_BST",
290 acpi_evaluate_object(acpi_battery_handle(battery), "_BST", NULL, 291 NULL, &buffer);
291 &buffer); 292 mutex_unlock(&battery->lock);
292 if (ACPI_FAILURE(status)) { 293 if (ACPI_FAILURE(status)) {
293 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST")); 294 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _BST"));
294 return -ENODEV; 295 return -ENODEV;
@@ -336,9 +337,10 @@ static int acpi_battery_set_alarm(struct acpi_battery *battery,
336 337
337 arg0.integer.value = alarm; 338 arg0.integer.value = alarm;
338 339
339 status = 340 mutex_lock(&battery->lock);
340 acpi_evaluate_object(acpi_battery_handle(battery), "_BTP", 341 status = acpi_evaluate_object(acpi_battery_handle(battery), "_BTP",
341 &arg_list, NULL); 342 &arg_list, NULL);
343 mutex_unlock(&battery->lock);
342 if (ACPI_FAILURE(status)) 344 if (ACPI_FAILURE(status))
343 return -ENODEV; 345 return -ENODEV;
344 346
@@ -658,8 +660,6 @@ acpi_battery_write_alarm(struct file *file,
658 if (!battery || (count > sizeof(alarm_string) - 1)) 660 if (!battery || (count > sizeof(alarm_string) - 1))
659 return -EINVAL; 661 return -EINVAL;
660 662
661 mutex_lock(&battery->mutex);
662
663 result = acpi_battery_update(battery, 1, &update_result); 663 result = acpi_battery_update(battery, 1, &update_result);
664 if (result) { 664 if (result) {
665 result = -ENODEV; 665 result = -ENODEV;
@@ -688,9 +688,7 @@ acpi_battery_write_alarm(struct file *file,
688 acpi_battery_check_result(battery, result); 688 acpi_battery_check_result(battery, result);
689 689
690 if (!result) 690 if (!result)
691 result = count; 691 return count;
692
693 mutex_unlock(&battery->mutex);
694 692
695 return result; 693 return result;
696} 694}
@@ -714,8 +712,6 @@ static int acpi_battery_read(int fid, struct seq_file *seq)
714 int update_result = ACPI_BATTERY_NONE_UPDATE; 712 int update_result = ACPI_BATTERY_NONE_UPDATE;
715 int update = 0; 713 int update = 0;
716 714
717 mutex_lock(&battery->mutex);
718
719 update = (get_seconds() - battery->update_time[fid] >= update_time); 715 update = (get_seconds() - battery->update_time[fid] >= update_time);
720 update = (update | battery->flags.update[fid]); 716 update = (update | battery->flags.update[fid]);
721 717
@@ -733,7 +729,6 @@ static int acpi_battery_read(int fid, struct seq_file *seq)
733 result = acpi_read_funcs[fid].print(seq, result); 729 result = acpi_read_funcs[fid].print(seq, result);
734 acpi_battery_check_result(battery, result); 730 acpi_battery_check_result(battery, result);
735 battery->flags.update[fid] = result; 731 battery->flags.update[fid] = result;
736 mutex_unlock(&battery->mutex);
737 return result; 732 return result;
738} 733}
739 734
@@ -897,10 +892,7 @@ static int acpi_battery_add(struct acpi_device *device)
897 if (!battery) 892 if (!battery)
898 return -ENOMEM; 893 return -ENOMEM;
899 894
900 mutex_init(&battery->mutex); 895 mutex_init(&battery->lock);
901
902 mutex_lock(&battery->mutex);
903
904 battery->device = device; 896 battery->device = device;
905 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); 897 strcpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME);
906 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS); 898 strcpy(acpi_device_class(device), ACPI_BATTERY_CLASS);
@@ -936,7 +928,6 @@ static int acpi_battery_add(struct acpi_device *device)
936 kfree(battery); 928 kfree(battery);
937 } 929 }
938 930
939 mutex_unlock(&battery->mutex);
940 931
941 return result; 932 return result;
942} 933}
@@ -951,8 +942,6 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
951 942
952 battery = acpi_driver_data(device); 943 battery = acpi_driver_data(device);
953 944
954 mutex_lock(&battery->mutex);
955
956 status = acpi_remove_notify_handler(device->handle, 945 status = acpi_remove_notify_handler(device->handle,
957 ACPI_ALL_NOTIFY, 946 ACPI_ALL_NOTIFY,
958 acpi_battery_notify); 947 acpi_battery_notify);
@@ -963,9 +952,7 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
963 952
964 kfree(battery->bst_data.pointer); 953 kfree(battery->bst_data.pointer);
965 954
966 mutex_unlock(&battery->mutex); 955 mutex_destroy(&battery->lock);
967
968 mutex_destroy(&battery->mutex);
969 956
970 kfree(battery); 957 kfree(battery);
971 958
diff --git a/drivers/acpi/bay.c b/drivers/acpi/bay.c
index 56a5b3fffeb..6daf6088ac8 100644
--- a/drivers/acpi/bay.c
+++ b/drivers/acpi/bay.c
@@ -337,7 +337,7 @@ static void bay_notify(acpi_handle handle, u32 event, void *data)
337 char *envp[] = { event_string, NULL }; 337 char *envp[] = { event_string, NULL };
338 338
339 bay_dprintk(handle, "Bay event"); 339 bay_dprintk(handle, "Bay event");
340 sprintf(event_string, "BAY_EVENT=%d\n", event); 340 sprintf(event_string, "BAY_EVENT=%d", event);
341 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp); 341 kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, envp);
342} 342}
343 343
diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c
index 6192c8be66d..1dabdf4c07b 100644
--- a/drivers/acpi/dock.c
+++ b/drivers/acpi/dock.c
@@ -336,13 +336,13 @@ static void hotplug_dock_devices(struct dock_station *ds, u32 event)
336static void dock_event(struct dock_station *ds, u32 event, int num) 336static void dock_event(struct dock_station *ds, u32 event, int num)
337{ 337{
338 struct device *dev = &dock_device->dev; 338 struct device *dev = &dock_device->dev;
339 char event_string[7]; 339 char event_string[13];
340 char *envp[] = { event_string, NULL }; 340 char *envp[] = { event_string, NULL };
341 341
342 if (num == UNDOCK_EVENT) 342 if (num == UNDOCK_EVENT)
343 sprintf(event_string, "UNDOCK"); 343 sprintf(event_string, "EVENT=undock");
344 else 344 else
345 sprintf(event_string, "DOCK"); 345 sprintf(event_string, "EVENT=dock");
346 346
347 /* 347 /*
348 * Indicate that the status of the dock station has 348 * Indicate that the status of the dock station has
diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c
index 469f3f57f88..2300d81bbc4 100644
--- a/drivers/acpi/ec.c
+++ b/drivers/acpi/ec.c
@@ -471,7 +471,6 @@ static void acpi_ec_gpe_query(void *ec_cxt)
471 } 471 }
472 } 472 }
473 mutex_unlock(&ec->lock); 473 mutex_unlock(&ec->lock);
474 printk(KERN_ERR PREFIX "Handler for query 0x%x is not found!\n", value);
475} 474}
476 475
477static u32 acpi_ec_gpe_handler(void *data) 476static u32 acpi_ec_gpe_handler(void *data)
@@ -653,42 +652,39 @@ static struct acpi_ec *make_acpi_ec(void)
653} 652}
654 653
655static acpi_status 654static acpi_status
656acpi_ec_register_query_methods(acpi_handle handle, u32 level, 655ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval)
657 void *context, void **return_value)
658{ 656{
659 struct acpi_namespace_node *node = handle; 657 acpi_status status;
660 struct acpi_ec *ec = context;
661 int value = 0;
662 if (sscanf(node->name.ascii, "_Q%x", &value) == 1) {
663 acpi_ec_add_query_handler(ec, value, handle, NULL, NULL);
664 }
665 return AE_OK;
666}
667 658
668static int ec_parse_device(struct acpi_ec *ec, acpi_handle handle) 659 struct acpi_ec *ec = context;
669{ 660 status = acpi_walk_resources(handle, METHOD_NAME__CRS,
670 if (ACPI_FAILURE(acpi_walk_resources(handle, METHOD_NAME__CRS, 661 ec_parse_io_ports, ec);
671 ec_parse_io_ports, ec))) 662 if (ACPI_FAILURE(status))
672 return -EINVAL; 663 return status;
673 664
674 /* Get GPE bit assignment (EC events). */ 665 /* Get GPE bit assignment (EC events). */
675 /* TODO: Add support for _GPE returning a package */ 666 /* TODO: Add support for _GPE returning a package */
676 if (ACPI_FAILURE(acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe))) 667 status = acpi_evaluate_integer(handle, "_GPE", NULL, &ec->gpe);
677 return -EINVAL; 668 if (ACPI_FAILURE(status))
669 return status;
678 670
679 /* Use the global lock for all EC transactions? */ 671 /* Use the global lock for all EC transactions? */
680 acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock); 672 acpi_evaluate_integer(handle, "_GLK", NULL, &ec->global_lock);
681 673
682 /* Find and register all query methods */
683 acpi_walk_namespace(ACPI_TYPE_METHOD, handle, 1,
684 acpi_ec_register_query_methods, ec, NULL);
685
686 ec->handle = handle; 674 ec->handle = handle;
687 675
688 printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx", 676 printk(KERN_INFO PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n",
689 ec->gpe, ec->command_addr, ec->data_addr); 677 ec->gpe, ec->command_addr, ec->data_addr);
690 678
691 return 0; 679 return AE_CTRL_TERMINATE;
680}
681
682static void ec_remove_handlers(struct acpi_ec *ec)
683{
684 acpi_remove_address_space_handler(ec->handle,
685 ACPI_ADR_SPACE_EC,
686 &acpi_ec_space_handler);
687 acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler);
692} 688}
693 689
694static int acpi_ec_add(struct acpi_device *device) 690static int acpi_ec_add(struct acpi_device *device)
@@ -705,7 +701,8 @@ static int acpi_ec_add(struct acpi_device *device)
705 if (!ec) 701 if (!ec)
706 return -ENOMEM; 702 return -ENOMEM;
707 703
708 if (ec_parse_device(ec, device->handle)) { 704 if (ec_parse_device(device->handle, 0, ec, NULL) !=
705 AE_CTRL_TERMINATE) {
709 kfree(ec); 706 kfree(ec);
710 return -EINVAL; 707 return -EINVAL;
711 } 708 }
@@ -713,16 +710,13 @@ static int acpi_ec_add(struct acpi_device *device)
713 /* Check if we found the boot EC */ 710 /* Check if we found the boot EC */
714 if (boot_ec) { 711 if (boot_ec) {
715 if (boot_ec->gpe == ec->gpe) { 712 if (boot_ec->gpe == ec->gpe) {
716 /* We might have incorrect info for GL at boot time */ 713 ec_remove_handlers(boot_ec);
717 mutex_lock(&boot_ec->lock); 714 mutex_destroy(&boot_ec->lock);
718 boot_ec->global_lock = ec->global_lock; 715 kfree(boot_ec);
719 /* Copy handlers from new ec into boot ec */ 716 first_ec = boot_ec = NULL;
720 list_splice(&ec->list, &boot_ec->list);
721 mutex_unlock(&boot_ec->lock);
722 kfree(ec);
723 ec = boot_ec;
724 } 717 }
725 } else 718 }
719 if (!first_ec)
726 first_ec = ec; 720 first_ec = ec;
727 ec->handle = device->handle; 721 ec->handle = device->handle;
728 acpi_driver_data(device) = ec; 722 acpi_driver_data(device) = ec;
@@ -734,14 +728,14 @@ static int acpi_ec_add(struct acpi_device *device)
734static int acpi_ec_remove(struct acpi_device *device, int type) 728static int acpi_ec_remove(struct acpi_device *device, int type)
735{ 729{
736 struct acpi_ec *ec; 730 struct acpi_ec *ec;
737 struct acpi_ec_query_handler *handler; 731 struct acpi_ec_query_handler *handler, *tmp;
738 732
739 if (!device) 733 if (!device)
740 return -EINVAL; 734 return -EINVAL;
741 735
742 ec = acpi_driver_data(device); 736 ec = acpi_driver_data(device);
743 mutex_lock(&ec->lock); 737 mutex_lock(&ec->lock);
744 list_for_each_entry(handler, &ec->list, node) { 738 list_for_each_entry_safe(handler, tmp, &ec->list, node) {
745 list_del(&handler->node); 739 list_del(&handler->node);
746 kfree(handler); 740 kfree(handler);
747 } 741 }
@@ -751,9 +745,6 @@ static int acpi_ec_remove(struct acpi_device *device, int type)
751 if (ec == first_ec) 745 if (ec == first_ec)
752 first_ec = NULL; 746 first_ec = NULL;
753 747
754 /* Don't touch boot EC */
755 if (boot_ec != ec)
756 kfree(ec);
757 return 0; 748 return 0;
758} 749}
759 750
@@ -817,9 +808,7 @@ static int acpi_ec_start(struct acpi_device *device)
817 if (!ec) 808 if (!ec)
818 return -EINVAL; 809 return -EINVAL;
819 810
820 /* Boot EC is already working */ 811 ret = ec_install_handlers(ec);
821 if (ec != boot_ec)
822 ret = ec_install_handlers(ec);
823 812
824 /* EC is fully operational, allow queries */ 813 /* EC is fully operational, allow queries */
825 atomic_set(&ec->query_pending, 0); 814 atomic_set(&ec->query_pending, 0);
@@ -829,7 +818,6 @@ static int acpi_ec_start(struct acpi_device *device)
829 818
830static int acpi_ec_stop(struct acpi_device *device, int type) 819static int acpi_ec_stop(struct acpi_device *device, int type)
831{ 820{
832 acpi_status status;
833 struct acpi_ec *ec; 821 struct acpi_ec *ec;
834 822
835 if (!device) 823 if (!device)
@@ -838,21 +826,7 @@ static int acpi_ec_stop(struct acpi_device *device, int type)
838 ec = acpi_driver_data(device); 826 ec = acpi_driver_data(device);
839 if (!ec) 827 if (!ec)
840 return -EINVAL; 828 return -EINVAL;
841 829 ec_remove_handlers(ec);
842 /* Don't touch boot EC */
843 if (ec == boot_ec)
844 return 0;
845
846 status = acpi_remove_address_space_handler(ec->handle,
847 ACPI_ADR_SPACE_EC,
848 &acpi_ec_space_handler);
849 if (ACPI_FAILURE(status))
850 return -ENODEV;
851
852 status = acpi_remove_gpe_handler(NULL, ec->gpe, &acpi_ec_gpe_handler);
853 if (ACPI_FAILURE(status))
854 return -ENODEV;
855
856 return 0; 830 return 0;
857} 831}
858 832
@@ -868,18 +842,21 @@ int __init acpi_ec_ecdt_probe(void)
868 /* 842 /*
869 * Generate a boot ec context 843 * Generate a boot ec context
870 */ 844 */
871
872 status = acpi_get_table(ACPI_SIG_ECDT, 1, 845 status = acpi_get_table(ACPI_SIG_ECDT, 1,
873 (struct acpi_table_header **)&ecdt_ptr); 846 (struct acpi_table_header **)&ecdt_ptr);
874 if (ACPI_FAILURE(status)) 847 if (ACPI_SUCCESS(status)) {
875 goto error; 848 printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n\n");
876 849 boot_ec->command_addr = ecdt_ptr->control.address;
877 printk(KERN_INFO PREFIX "EC description table is found, configuring boot EC\n"); 850 boot_ec->data_addr = ecdt_ptr->data.address;
878 851 boot_ec->gpe = ecdt_ptr->gpe;
879 boot_ec->command_addr = ecdt_ptr->control.address; 852 boot_ec->handle = ACPI_ROOT_OBJECT;
880 boot_ec->data_addr = ecdt_ptr->data.address; 853 } else {
881 boot_ec->gpe = ecdt_ptr->gpe; 854 printk(KERN_DEBUG PREFIX "Look up EC in DSDT\n");
882 boot_ec->handle = ACPI_ROOT_OBJECT; 855 status = acpi_get_devices(ec_device_ids[0].id, ec_parse_device,
856 boot_ec, NULL);
857 if (ACPI_FAILURE(status))
858 goto error;
859 }
883 860
884 ret = ec_install_handlers(boot_ec); 861 ret = ec_install_handlers(boot_ec);
885 if (!ret) { 862 if (!ret) {
diff --git a/drivers/acpi/tables/tbxface.c b/drivers/acpi/tables/tbxface.c
index 5b302c4e293..a9e3331fee5 100644
--- a/drivers/acpi/tables/tbxface.c
+++ b/drivers/acpi/tables/tbxface.c
@@ -52,6 +52,8 @@ ACPI_MODULE_NAME("tbxface")
52/* Local prototypes */ 52/* Local prototypes */
53static acpi_status acpi_tb_load_namespace(void); 53static acpi_status acpi_tb_load_namespace(void);
54 54
55static int no_auto_ssdt;
56
55/******************************************************************************* 57/*******************************************************************************
56 * 58 *
57 * FUNCTION: acpi_allocate_root_table 59 * FUNCTION: acpi_allocate_root_table
@@ -536,6 +538,10 @@ static acpi_status acpi_tb_load_namespace(void)
536 538
537 ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS")); 539 ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS"));
538 acpi_tb_print_table_header(0, table); 540 acpi_tb_print_table_header(0, table);
541
542 if (no_auto_ssdt == 0) {
543 printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"");
544 }
539 } 545 }
540 546
541 status = 547 status =
@@ -577,6 +583,11 @@ static acpi_status acpi_tb_load_namespace(void)
577 continue; 583 continue;
578 } 584 }
579 585
586 if (no_auto_ssdt) {
587 printk(KERN_WARNING "ACPI: SSDT ignored due to \"acpi_no_auto_ssdt\"\n");
588 continue;
589 }
590
580 /* Ignore errors while loading tables, get as many as possible */ 591 /* Ignore errors while loading tables, get as many as possible */
581 592
582 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 593 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
@@ -622,3 +633,15 @@ acpi_status acpi_load_tables(void)
622} 633}
623 634
624ACPI_EXPORT_SYMBOL(acpi_load_tables) 635ACPI_EXPORT_SYMBOL(acpi_load_tables)
636
637
638static int __init acpi_no_auto_ssdt_setup(char *s) {
639
640 printk(KERN_NOTICE "ACPI: SSDT auto-load disabled\n");
641
642 no_auto_ssdt = 1;
643
644 return 1;
645}
646
647__setup("acpi_no_auto_ssdt", acpi_no_auto_ssdt_setup);
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 5a62de1b7f2..1e06159fd9c 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -33,6 +33,7 @@
33 33
34#include <linux/kernel.h> 34#include <linux/kernel.h>
35#include <linux/module.h> 35#include <linux/module.h>
36#include <linux/dmi.h>
36#include <linux/init.h> 37#include <linux/init.h>
37#include <linux/types.h> 38#include <linux/types.h>
38#include <linux/proc_fs.h> 39#include <linux/proc_fs.h>
@@ -74,10 +75,26 @@ MODULE_AUTHOR("Paul Diefenbaugh");
74MODULE_DESCRIPTION("ACPI Thermal Zone Driver"); 75MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
75MODULE_LICENSE("GPL"); 76MODULE_LICENSE("GPL");
76 77
78static int act;
79module_param(act, int, 0644);
80MODULE_PARM_DESC(act, "Disable or override all lowest active trip points.\n");
81
77static int tzp; 82static int tzp;
78module_param(tzp, int, 0); 83module_param(tzp, int, 0444);
79MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n"); 84MODULE_PARM_DESC(tzp, "Thermal zone polling frequency, in 1/10 seconds.\n");
80 85
86static int nocrt;
87module_param(nocrt, int, 0);
88MODULE_PARM_DESC(nocrt, "Set to disable action on ACPI thermal zone critical and hot trips.\n");
89
90static int off;
91module_param(off, int, 0);
92MODULE_PARM_DESC(off, "Set to disable ACPI thermal support.\n");
93
94static int psv;
95module_param(psv, int, 0644);
96MODULE_PARM_DESC(psv, "Disable or override all passive trip points.\n");
97
81static int acpi_thermal_add(struct acpi_device *device); 98static int acpi_thermal_add(struct acpi_device *device);
82static int acpi_thermal_remove(struct acpi_device *device, int type); 99static int acpi_thermal_remove(struct acpi_device *device, int type);
83static int acpi_thermal_resume(struct acpi_device *device); 100static int acpi_thermal_resume(struct acpi_device *device);
@@ -339,9 +356,16 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
339 356
340 /* Passive: Processors (optional) */ 357 /* Passive: Processors (optional) */
341 358
342 status = 359 if (psv == -1) {
343 acpi_evaluate_integer(tz->device->handle, "_PSV", NULL, 360 status = AE_SUPPORT;
344 &tz->trips.passive.temperature); 361 } else if (psv > 0) {
362 tz->trips.passive.temperature = CELSIUS_TO_KELVIN(psv);
363 status = AE_OK;
364 } else {
365 status = acpi_evaluate_integer(tz->device->handle,
366 "_PSV", NULL, &tz->trips.passive.temperature);
367 }
368
345 if (ACPI_FAILURE(status)) { 369 if (ACPI_FAILURE(status)) {
346 tz->trips.passive.flags.valid = 0; 370 tz->trips.passive.flags.valid = 0;
347 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n")); 371 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No passive threshold\n"));
@@ -386,11 +410,33 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
386 410
387 char name[5] = { '_', 'A', 'C', ('0' + i), '\0' }; 411 char name[5] = { '_', 'A', 'C', ('0' + i), '\0' };
388 412
389 status = 413 if (act == -1)
390 acpi_evaluate_integer(tz->device->handle, name, NULL, 414 break; /* disable all active trip points */
391 &tz->trips.active[i].temperature); 415
392 if (ACPI_FAILURE(status)) 416 status = acpi_evaluate_integer(tz->device->handle,
417 name, NULL, &tz->trips.active[i].temperature);
418
419 if (ACPI_FAILURE(status)) {
420 if (i == 0) /* no active trip points */
421 break;
422 if (act <= 0) /* no override requested */
423 break;
424 if (i == 1) { /* 1 trip point */
425 tz->trips.active[0].temperature =
426 CELSIUS_TO_KELVIN(act);
427 } else { /* multiple trips */
428 /*
429 * Don't allow override higher than
430 * the next higher trip point
431 */
432 tz->trips.active[i - 1].temperature =
433 (tz->trips.active[i - 2].temperature <
434 CELSIUS_TO_KELVIN(act) ?
435 tz->trips.active[i - 2].temperature :
436 CELSIUS_TO_KELVIN(act));
437 }
393 break; 438 break;
439 }
394 440
395 name[2] = 'L'; 441 name[2] = 'L';
396 status = 442 status =
@@ -427,7 +473,7 @@ static int acpi_thermal_get_devices(struct acpi_thermal *tz)
427 473
428static int acpi_thermal_critical(struct acpi_thermal *tz) 474static int acpi_thermal_critical(struct acpi_thermal *tz)
429{ 475{
430 if (!tz || !tz->trips.critical.flags.valid) 476 if (!tz || !tz->trips.critical.flags.valid || nocrt)
431 return -EINVAL; 477 return -EINVAL;
432 478
433 if (tz->temperature >= tz->trips.critical.temperature) { 479 if (tz->temperature >= tz->trips.critical.temperature) {
@@ -449,7 +495,7 @@ static int acpi_thermal_critical(struct acpi_thermal *tz)
449 495
450static int acpi_thermal_hot(struct acpi_thermal *tz) 496static int acpi_thermal_hot(struct acpi_thermal *tz)
451{ 497{
452 if (!tz || !tz->trips.hot.flags.valid) 498 if (!tz || !tz->trips.hot.flags.valid || nocrt)
453 return -EINVAL; 499 return -EINVAL;
454 500
455 if (tz->temperature >= tz->trips.hot.temperature) { 501 if (tz->temperature >= tz->trips.hot.temperature) {
@@ -824,12 +870,14 @@ static int acpi_thermal_trip_seq_show(struct seq_file *seq, void *offset)
824 goto end; 870 goto end;
825 871
826 if (tz->trips.critical.flags.valid) 872 if (tz->trips.critical.flags.valid)
827 seq_printf(seq, "critical (S5): %ld C\n", 873 seq_printf(seq, "critical (S5): %ld C%s",
828 KELVIN_TO_CELSIUS(tz->trips.critical.temperature)); 874 KELVIN_TO_CELSIUS(tz->trips.critical.temperature),
875 nocrt ? " <disabled>\n" : "\n");
829 876
830 if (tz->trips.hot.flags.valid) 877 if (tz->trips.hot.flags.valid)
831 seq_printf(seq, "hot (S4): %ld C\n", 878 seq_printf(seq, "hot (S4): %ld C%s",
832 KELVIN_TO_CELSIUS(tz->trips.hot.temperature)); 879 KELVIN_TO_CELSIUS(tz->trips.hot.temperature),
880 nocrt ? " <disabled>\n" : "\n");
833 881
834 if (tz->trips.passive.flags.valid) { 882 if (tz->trips.passive.flags.valid) {
835 seq_printf(seq, 883 seq_printf(seq,
@@ -1281,11 +1329,78 @@ static int acpi_thermal_resume(struct acpi_device *device)
1281 return AE_OK; 1329 return AE_OK;
1282} 1330}
1283 1331
1332#ifdef CONFIG_DMI
1333static int thermal_act(struct dmi_system_id *d) {
1334
1335 if (act == 0) {
1336 printk(KERN_NOTICE "ACPI: %s detected: "
1337 "disabling all active thermal trip points\n", d->ident);
1338 act = -1;
1339 }
1340 return 0;
1341}
1342static int thermal_tzp(struct dmi_system_id *d) {
1343
1344 if (tzp == 0) {
1345 printk(KERN_NOTICE "ACPI: %s detected: "
1346 "enabling thermal zone polling\n", d->ident);
1347 tzp = 300; /* 300 dS = 30 Seconds */
1348 }
1349 return 0;
1350}
1351static int thermal_psv(struct dmi_system_id *d) {
1352
1353 if (psv == 0) {
1354 printk(KERN_NOTICE "ACPI: %s detected: "
1355 "disabling all passive thermal trip points\n", d->ident);
1356 psv = -1;
1357 }
1358 return 0;
1359}
1360
1361static struct dmi_system_id thermal_dmi_table[] __initdata = {
1362 /*
1363 * Award BIOS on this AOpen makes thermal control almost worthless.
1364 * http://bugzilla.kernel.org/show_bug.cgi?id=8842
1365 */
1366 {
1367 .callback = thermal_act,
1368 .ident = "AOpen i915GMm-HFS",
1369 .matches = {
1370 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1371 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1372 },
1373 },
1374 {
1375 .callback = thermal_psv,
1376 .ident = "AOpen i915GMm-HFS",
1377 .matches = {
1378 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1379 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1380 },
1381 },
1382 {
1383 .callback = thermal_tzp,
1384 .ident = "AOpen i915GMm-HFS",
1385 .matches = {
1386 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
1387 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
1388 },
1389 },
1390 {}
1391};
1392#endif /* CONFIG_DMI */
1393
1284static int __init acpi_thermal_init(void) 1394static int __init acpi_thermal_init(void)
1285{ 1395{
1286 int result = 0; 1396 int result = 0;
1287 1397
1398 dmi_check_system(thermal_dmi_table);
1288 1399
1400 if (off) {
1401 printk(KERN_NOTICE "ACPI: thermal control disabled\n");
1402 return -ENODEV;
1403 }
1289 acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir); 1404 acpi_thermal_dir = proc_mkdir(ACPI_THERMAL_CLASS, acpi_root_dir);
1290 if (!acpi_thermal_dir) 1405 if (!acpi_thermal_dir)
1291 return -ENODEV; 1406 return -ENODEV;