aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/thermal.c
diff options
context:
space:
mode:
authorMatthew Garrett <mjg59@srcf.ucam.org>2008-12-03 12:55:32 -0500
committerLen Brown <len.brown@intel.com>2009-02-20 18:41:56 -0500
commitb1569e99c795bf83b4ddf41c4f1c42761ab7f75e (patch)
treead45358dd111e0c4ce71d58565068c47c0171c3d /drivers/acpi/thermal.c
parent6503e5df08008b9a47022b5e9ebba658c8fa69af (diff)
ACPI: move thermal trip handling to generic thermal layer
The ACPI code currently carries its own thermal trip handling, meaning that any other thermal implementation will need to reimplement it. Move the code to the generic thermal layer. Signed-off-by: Matthew Garrett <mjg@redhat.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/thermal.c')
-rw-r--r--drivers/acpi/thermal.c458
1 files changed, 48 insertions, 410 deletions
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 1c410ef859c6..0ec48d2f85c5 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -37,7 +37,6 @@
37#include <linux/init.h> 37#include <linux/init.h>
38#include <linux/types.h> 38#include <linux/types.h>
39#include <linux/proc_fs.h> 39#include <linux/proc_fs.h>
40#include <linux/timer.h>
41#include <linux/jiffies.h> 40#include <linux/jiffies.h>
42#include <linux/kmod.h> 41#include <linux/kmod.h>
43#include <linux/seq_file.h> 42#include <linux/seq_file.h>
@@ -190,7 +189,6 @@ struct acpi_thermal {
190 struct acpi_thermal_state state; 189 struct acpi_thermal_state state;
191 struct acpi_thermal_trips trips; 190 struct acpi_thermal_trips trips;
192 struct acpi_handle_list devices; 191 struct acpi_handle_list devices;
193 struct timer_list timer;
194 struct thermal_zone_device *thermal_zone; 192 struct thermal_zone_device *thermal_zone;
195 int tz_enabled; 193 int tz_enabled;
196 struct mutex lock; 194 struct mutex lock;
@@ -290,6 +288,11 @@ static int acpi_thermal_set_polling(struct acpi_thermal *tz, int seconds)
290 288
291 tz->polling_frequency = seconds * 10; /* Convert value to deci-seconds */ 289 tz->polling_frequency = seconds * 10; /* Convert value to deci-seconds */
292 290
291 tz->thermal_zone->polling_delay = seconds * 1000;
292
293 if (tz->tz_enabled)
294 thermal_zone_device_update(tz->thermal_zone);
295
293 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 296 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
294 "Polling frequency set to %lu seconds\n", 297 "Polling frequency set to %lu seconds\n",
295 tz->polling_frequency/10)); 298 tz->polling_frequency/10));
@@ -569,386 +572,11 @@ static int acpi_thermal_get_trip_points(struct acpi_thermal *tz)
569 return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT); 572 return acpi_thermal_trips_update(tz, ACPI_TRIPS_INIT);
570} 573}
571 574
572static int acpi_thermal_critical(struct acpi_thermal *tz)
573{
574 if (!tz || !tz->trips.critical.flags.valid)
575 return -EINVAL;
576
577 if (tz->temperature >= tz->trips.critical.temperature) {
578 printk(KERN_WARNING PREFIX "Critical trip point\n");
579 tz->trips.critical.flags.enabled = 1;
580 } else if (tz->trips.critical.flags.enabled)
581 tz->trips.critical.flags.enabled = 0;
582
583 acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_CRITICAL,
584 tz->trips.critical.flags.enabled);
585 acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
586 dev_name(&tz->device->dev),
587 ACPI_THERMAL_NOTIFY_CRITICAL,
588 tz->trips.critical.flags.enabled);
589
590 /* take no action if nocrt is set */
591 if(!nocrt) {
592 printk(KERN_EMERG
593 "Critical temperature reached (%ld C), shutting down.\n",
594 KELVIN_TO_CELSIUS(tz->temperature));
595 orderly_poweroff(true);
596 }
597
598 return 0;
599}
600
601static int acpi_thermal_hot(struct acpi_thermal *tz)
602{
603 if (!tz || !tz->trips.hot.flags.valid)
604 return -EINVAL;
605
606 if (tz->temperature >= tz->trips.hot.temperature) {
607 printk(KERN_WARNING PREFIX "Hot trip point\n");
608 tz->trips.hot.flags.enabled = 1;
609 } else if (tz->trips.hot.flags.enabled)
610 tz->trips.hot.flags.enabled = 0;
611
612 acpi_bus_generate_proc_event(tz->device, ACPI_THERMAL_NOTIFY_HOT,
613 tz->trips.hot.flags.enabled);
614 acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
615 dev_name(&tz->device->dev),
616 ACPI_THERMAL_NOTIFY_HOT,
617 tz->trips.hot.flags.enabled);
618
619 /* TBD: Call user-mode "sleep(S4)" function if nocrt is cleared */
620
621 return 0;
622}
623
624static void acpi_thermal_passive(struct acpi_thermal *tz)
625{
626 int result = 1;
627 struct acpi_thermal_passive *passive = NULL;
628 int trend = 0;
629 int i = 0;
630
631
632 if (!tz || !tz->trips.passive.flags.valid)
633 return;
634
635 passive = &(tz->trips.passive);
636
637 /*
638 * Above Trip?
639 * -----------
640 * Calculate the thermal trend (using the passive cooling equation)
641 * and modify the performance limit for all passive cooling devices
642 * accordingly. Note that we assume symmetry.
643 */
644 if (tz->temperature >= passive->temperature) {
645 trend =
646 (passive->tc1 * (tz->temperature - tz->last_temperature)) +
647 (passive->tc2 * (tz->temperature - passive->temperature));
648 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
649 "trend[%d]=(tc1[%lu]*(tmp[%lu]-last[%lu]))+(tc2[%lu]*(tmp[%lu]-psv[%lu]))\n",
650 trend, passive->tc1, tz->temperature,
651 tz->last_temperature, passive->tc2,
652 tz->temperature, passive->temperature));
653 passive->flags.enabled = 1;
654 /* Heating up? */
655 if (trend > 0)
656 for (i = 0; i < passive->devices.count; i++)
657 acpi_processor_set_thermal_limit(passive->
658 devices.
659 handles[i],
660 ACPI_PROCESSOR_LIMIT_INCREMENT);
661 /* Cooling off? */
662 else if (trend < 0) {
663 for (i = 0; i < passive->devices.count; i++)
664 /*
665 * assume that we are on highest
666 * freq/lowest thrott and can leave
667 * passive mode, even in error case
668 */
669 if (!acpi_processor_set_thermal_limit
670 (passive->devices.handles[i],
671 ACPI_PROCESSOR_LIMIT_DECREMENT))
672 result = 0;
673 /*
674 * Leave cooling mode, even if the temp might
675 * higher than trip point This is because some
676 * machines might have long thermal polling
677 * frequencies (tsp) defined. We will fall back
678 * into passive mode in next cycle (probably quicker)
679 */
680 if (result) {
681 passive->flags.enabled = 0;
682 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
683 "Disabling passive cooling, still above threshold,"
684 " but we are cooling down\n"));
685 }
686 }
687 return;
688 }
689
690 /*
691 * Below Trip?
692 * -----------
693 * Implement passive cooling hysteresis to slowly increase performance
694 * and avoid thrashing around the passive trip point. Note that we
695 * assume symmetry.
696 */
697 if (!passive->flags.enabled)
698 return;
699 for (i = 0; i < passive->devices.count; i++)
700 if (!acpi_processor_set_thermal_limit
701 (passive->devices.handles[i],
702 ACPI_PROCESSOR_LIMIT_DECREMENT))
703 result = 0;
704 if (result) {
705 passive->flags.enabled = 0;
706 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
707 "Disabling passive cooling (zone is cool)\n"));
708 }
709}
710
711static void acpi_thermal_active(struct acpi_thermal *tz)
712{
713 int result = 0;
714 struct acpi_thermal_active *active = NULL;
715 int i = 0;
716 int j = 0;
717 unsigned long maxtemp = 0;
718
719
720 if (!tz)
721 return;
722
723 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
724 active = &(tz->trips.active[i]);
725 if (!active || !active->flags.valid)
726 break;
727 if (tz->temperature >= active->temperature) {
728 /*
729 * Above Threshold?
730 * ----------------
731 * If not already enabled, turn ON all cooling devices
732 * associated with this active threshold.
733 */
734 if (active->temperature > maxtemp)
735 tz->state.active_index = i;
736 maxtemp = active->temperature;
737 if (active->flags.enabled)
738 continue;
739 for (j = 0; j < active->devices.count; j++) {
740 result =
741 acpi_bus_set_power(active->devices.
742 handles[j],
743 ACPI_STATE_D0);
744 if (result) {
745 printk(KERN_WARNING PREFIX
746 "Unable to turn cooling device [%p] 'on'\n",
747 active->devices.
748 handles[j]);
749 continue;
750 }
751 active->flags.enabled = 1;
752 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
753 "Cooling device [%p] now 'on'\n",
754 active->devices.handles[j]));
755 }
756 continue;
757 }
758 if (!active->flags.enabled)
759 continue;
760 /*
761 * Below Threshold?
762 * ----------------
763 * Turn OFF all cooling devices associated with this
764 * threshold.
765 */
766 for (j = 0; j < active->devices.count; j++) {
767 result = acpi_bus_set_power(active->devices.handles[j],
768 ACPI_STATE_D3);
769 if (result) {
770 printk(KERN_WARNING PREFIX
771 "Unable to turn cooling device [%p] 'off'\n",
772 active->devices.handles[j]);
773 continue;
774 }
775 active->flags.enabled = 0;
776 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
777 "Cooling device [%p] now 'off'\n",
778 active->devices.handles[j]));
779 }
780 }
781}
782
783static void acpi_thermal_check(void *context);
784
785static void acpi_thermal_run(unsigned long data)
786{
787 struct acpi_thermal *tz = (struct acpi_thermal *)data;
788 if (!tz->zombie)
789 acpi_os_execute(OSL_GPE_HANDLER, acpi_thermal_check, (void *)data);
790}
791
792static void acpi_thermal_active_off(void *data)
793{
794 int result = 0;
795 struct acpi_thermal *tz = data;
796 int i = 0;
797 int j = 0;
798 struct acpi_thermal_active *active = NULL;
799
800 if (!tz) {
801 printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
802 return;
803 }
804
805 result = acpi_thermal_get_temperature(tz);
806 if (result)
807 return;
808
809 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
810 active = &(tz->trips.active[i]);
811 if (!active || !active->flags.valid)
812 break;
813 if (tz->temperature >= active->temperature) {
814 /*
815 * If the thermal temperature is greater than the
816 * active threshod, unnecessary to turn off the
817 * the active cooling device.
818 */
819 continue;
820 }
821 /*
822 * Below Threshold?
823 * ----------------
824 * Turn OFF all cooling devices associated with this
825 * threshold.
826 */
827 for (j = 0; j < active->devices.count; j++)
828 result = acpi_bus_set_power(active->devices.handles[j],
829 ACPI_STATE_D3);
830 }
831}
832
833static void acpi_thermal_check(void *data) 575static void acpi_thermal_check(void *data)
834{ 576{
835 int result = 0;
836 struct acpi_thermal *tz = data; 577 struct acpi_thermal *tz = data;
837 unsigned long sleep_time = 0;
838 unsigned long timeout_jiffies = 0;
839 int i = 0;
840 struct acpi_thermal_state state;
841
842
843 if (!tz) {
844 printk(KERN_ERR PREFIX "Invalid (NULL) context\n");
845 return;
846 }
847
848 /* Check if someone else is already running */
849 if (!mutex_trylock(&tz->lock))
850 return;
851
852 state = tz->state;
853
854 result = acpi_thermal_get_temperature(tz);
855 if (result)
856 goto unlock;
857
858 if (!tz->tz_enabled)
859 goto unlock;
860
861 memset(&tz->state, 0, sizeof(tz->state));
862
863 /*
864 * Check Trip Points
865 * -----------------
866 * Compare the current temperature to the trip point values to see
867 * if we've entered one of the thermal policy states. Note that
868 * this function determines when a state is entered, but the
869 * individual policy decides when it is exited (e.g. hysteresis).
870 */
871 if (tz->trips.critical.flags.valid)
872 state.critical |=
873 (tz->temperature >= tz->trips.critical.temperature);
874 if (tz->trips.hot.flags.valid)
875 state.hot |= (tz->temperature >= tz->trips.hot.temperature);
876 if (tz->trips.passive.flags.valid)
877 state.passive |=
878 (tz->temperature >= tz->trips.passive.temperature);
879 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
880 if (tz->trips.active[i].flags.valid)
881 state.active |=
882 (tz->temperature >=
883 tz->trips.active[i].temperature);
884
885 /*
886 * Invoke Policy
887 * -------------
888 * Separated from the above check to allow individual policy to
889 * determine when to exit a given state.
890 */
891 if (state.critical)
892 acpi_thermal_critical(tz);
893 if (state.hot)
894 acpi_thermal_hot(tz);
895 if (state.passive)
896 acpi_thermal_passive(tz);
897 if (state.active)
898 acpi_thermal_active(tz);
899
900 /*
901 * Calculate State
902 * ---------------
903 * Again, separated from the above two to allow independent policy
904 * decisions.
905 */
906 tz->state.critical = tz->trips.critical.flags.enabled;
907 tz->state.hot = tz->trips.hot.flags.enabled;
908 tz->state.passive = tz->trips.passive.flags.enabled;
909 tz->state.active = 0;
910 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++)
911 tz->state.active |= tz->trips.active[i].flags.enabled;
912
913 /*
914 * Calculate Sleep Time
915 * --------------------
916 * If we're in the passive state, use _TSP's value. Otherwise
917 * use the default polling frequency (e.g. _TZP). If no polling
918 * frequency is specified then we'll wait forever (at least until
919 * a thermal event occurs). Note that _TSP and _TZD values are
920 * given in 1/10th seconds (we must covert to milliseconds).
921 */
922 if (tz->state.passive) {
923 sleep_time = tz->trips.passive.tsp * 100;
924 timeout_jiffies = jiffies + (HZ * sleep_time) / 1000;
925 } else if (tz->polling_frequency > 0) {
926 sleep_time = tz->polling_frequency * 100;
927 timeout_jiffies = round_jiffies(jiffies + (HZ * sleep_time) / 1000);
928 }
929
930 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: temperature[%lu] sleep[%lu]\n",
931 tz->name, tz->temperature, sleep_time));
932 578
933 /* 579 thermal_zone_device_update(tz->thermal_zone);
934 * Schedule Next Poll
935 * ------------------
936 */
937 if (!sleep_time) {
938 if (timer_pending(&(tz->timer)))
939 del_timer(&(tz->timer));
940 } else {
941 if (timer_pending(&(tz->timer)))
942 mod_timer(&(tz->timer), timeout_jiffies);
943 else {
944 tz->timer.data = (unsigned long)tz;
945 tz->timer.function = acpi_thermal_run;
946 tz->timer.expires = timeout_jiffies;
947 add_timer(&(tz->timer));
948 }
949 }
950 unlock:
951 mutex_unlock(&tz->lock);
952} 580}
953 581
954/* sys I/F for generic thermal sysfs support */ 582/* sys I/F for generic thermal sysfs support */
@@ -1122,6 +750,29 @@ static int thermal_get_crit_temp(struct thermal_zone_device *thermal,
1122 return -EINVAL; 750 return -EINVAL;
1123} 751}
1124 752
753static int thermal_notify(struct thermal_zone_device *thermal, int trip,
754 enum thermal_trip_type trip_type)
755{
756 u8 type = 0;
757 struct acpi_thermal *tz = thermal->devdata;
758
759 if (trip_type == THERMAL_TRIP_CRITICAL)
760 type = ACPI_THERMAL_NOTIFY_CRITICAL;
761 else if (trip_type == THERMAL_TRIP_HOT)
762 type = ACPI_THERMAL_NOTIFY_HOT;
763 else
764 return 0;
765
766 acpi_bus_generate_proc_event(tz->device, type, 1);
767 acpi_bus_generate_netlink_event(tz->device->pnp.device_class,
768 tz->device->dev.bus_id, type, 1);
769
770 if (trip_type == THERMAL_TRIP_CRITICAL && nocrt)
771 return 1;
772
773 return 0;
774}
775
1125typedef int (*cb)(struct thermal_zone_device *, int, 776typedef int (*cb)(struct thermal_zone_device *, int,
1126 struct thermal_cooling_device *); 777 struct thermal_cooling_device *);
1127static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal, 778static int acpi_thermal_cooling_device_cb(struct thermal_zone_device *thermal,
@@ -1214,6 +865,7 @@ static struct thermal_zone_device_ops acpi_thermal_zone_ops = {
1214 .get_trip_type = thermal_get_trip_type, 865 .get_trip_type = thermal_get_trip_type,
1215 .get_trip_temp = thermal_get_trip_temp, 866 .get_trip_temp = thermal_get_trip_temp,
1216 .get_crit_temp = thermal_get_crit_temp, 867 .get_crit_temp = thermal_get_crit_temp,
868 .notify = thermal_notify,
1217}; 869};
1218 870
1219static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) 871static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
@@ -1234,8 +886,21 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz)
1234 886
1235 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && 887 for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE &&
1236 tz->trips.active[i].flags.valid; i++, trips++); 888 tz->trips.active[i].flags.valid; i++, trips++);
1237 tz->thermal_zone = thermal_zone_device_register("acpitz", 889
1238 trips, tz, &acpi_thermal_zone_ops); 890 if (tz->trips.passive.flags.valid)
891 tz->thermal_zone =
892 thermal_zone_device_register("acpitz", trips, tz,
893 &acpi_thermal_zone_ops,
894 tz->trips.passive.tc1,
895 tz->trips.passive.tc2,
896 tz->trips.passive.tsp*100,
897 tz->polling_frequency*100);
898 else
899 tz->thermal_zone =
900 thermal_zone_device_register("acpitz", trips, tz,
901 &acpi_thermal_zone_ops,
902 0, 0, 0,
903 tz->polling_frequency);
1239 if (IS_ERR(tz->thermal_zone)) 904 if (IS_ERR(tz->thermal_zone))
1240 return -ENODEV; 905 return -ENODEV;
1241 906
@@ -1467,13 +1132,13 @@ static int acpi_thermal_polling_seq_show(struct seq_file *seq, void *offset)
1467 if (!tz) 1132 if (!tz)
1468 goto end; 1133 goto end;
1469 1134
1470 if (!tz->polling_frequency) { 1135 if (!tz->thermal_zone->polling_delay) {
1471 seq_puts(seq, "<polling disabled>\n"); 1136 seq_puts(seq, "<polling disabled>\n");
1472 goto end; 1137 goto end;
1473 } 1138 }
1474 1139
1475 seq_printf(seq, "polling frequency: %lu seconds\n", 1140 seq_printf(seq, "polling frequency: %d seconds\n",
1476 (tz->polling_frequency / 10)); 1141 (tz->thermal_zone->polling_delay / 1000));
1477 1142
1478 end: 1143 end:
1479 return 0; 1144 return 0;
@@ -1703,12 +1368,6 @@ static int acpi_thermal_add(struct acpi_device *device)
1703 if (result) 1368 if (result)
1704 goto unregister_thermal_zone; 1369 goto unregister_thermal_zone;
1705 1370
1706 init_timer(&tz->timer);
1707
1708 acpi_thermal_active_off(tz);
1709
1710 acpi_thermal_check(tz);
1711
1712 status = acpi_install_notify_handler(device->handle, 1371 status = acpi_install_notify_handler(device->handle,
1713 ACPI_DEVICE_NOTIFY, 1372 ACPI_DEVICE_NOTIFY,
1714 acpi_thermal_notify, tz); 1373 acpi_thermal_notify, tz);
@@ -1737,36 +1396,15 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
1737 acpi_status status = AE_OK; 1396 acpi_status status = AE_OK;
1738 struct acpi_thermal *tz = NULL; 1397 struct acpi_thermal *tz = NULL;
1739 1398
1740
1741 if (!device || !acpi_driver_data(device)) 1399 if (!device || !acpi_driver_data(device))
1742 return -EINVAL; 1400 return -EINVAL;
1743 1401
1744 tz = acpi_driver_data(device); 1402 tz = acpi_driver_data(device);
1745 1403
1746 /* avoid timer adding new defer task */
1747 tz->zombie = 1;
1748 /* wait for running timer (on other CPUs) finish */
1749 del_timer_sync(&(tz->timer));
1750 /* synchronize deferred task */
1751 acpi_os_wait_events_complete(NULL);
1752 /* deferred task may reinsert timer */
1753 del_timer_sync(&(tz->timer));
1754
1755 status = acpi_remove_notify_handler(device->handle, 1404 status = acpi_remove_notify_handler(device->handle,
1756 ACPI_DEVICE_NOTIFY, 1405 ACPI_DEVICE_NOTIFY,
1757 acpi_thermal_notify); 1406 acpi_thermal_notify);
1758 1407
1759 /* Terminate policy */
1760 if (tz->trips.passive.flags.valid && tz->trips.passive.flags.enabled) {
1761 tz->trips.passive.flags.enabled = 0;
1762 acpi_thermal_passive(tz);
1763 }
1764 if (tz->trips.active[0].flags.valid
1765 && tz->trips.active[0].flags.enabled) {
1766 tz->trips.active[0].flags.enabled = 0;
1767 acpi_thermal_active(tz);
1768 }
1769
1770 acpi_thermal_remove_fs(device); 1408 acpi_thermal_remove_fs(device);
1771 acpi_thermal_unregister_thermal_zone(tz); 1409 acpi_thermal_unregister_thermal_zone(tz);
1772 mutex_destroy(&tz->lock); 1410 mutex_destroy(&tz->lock);