diff options
Diffstat (limited to 'drivers/thermal/thermal_sys.c')
-rw-r--r-- | drivers/thermal/thermal_sys.c | 321 |
1 files changed, 200 insertions, 121 deletions
diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index efd81bb25e01..9ee42ca4d289 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c | |||
@@ -41,15 +41,25 @@ MODULE_AUTHOR("Zhang Rui"); | |||
41 | MODULE_DESCRIPTION("Generic thermal management sysfs support"); | 41 | MODULE_DESCRIPTION("Generic thermal management sysfs support"); |
42 | MODULE_LICENSE("GPL"); | 42 | MODULE_LICENSE("GPL"); |
43 | 43 | ||
44 | struct thermal_cooling_device_instance { | 44 | #define THERMAL_NO_TARGET -1UL |
45 | /* | ||
46 | * This structure is used to describe the behavior of | ||
47 | * a certain cooling device on a certain trip point | ||
48 | * in a certain thermal zone | ||
49 | */ | ||
50 | struct thermal_instance { | ||
45 | int id; | 51 | int id; |
46 | char name[THERMAL_NAME_LENGTH]; | 52 | char name[THERMAL_NAME_LENGTH]; |
47 | struct thermal_zone_device *tz; | 53 | struct thermal_zone_device *tz; |
48 | struct thermal_cooling_device *cdev; | 54 | struct thermal_cooling_device *cdev; |
49 | int trip; | 55 | int trip; |
56 | unsigned long upper; /* Highest cooling state for this trip point */ | ||
57 | unsigned long lower; /* Lowest cooling state for this trip point */ | ||
58 | unsigned long target; /* expected cooling state */ | ||
50 | char attr_name[THERMAL_NAME_LENGTH]; | 59 | char attr_name[THERMAL_NAME_LENGTH]; |
51 | struct device_attribute attr; | 60 | struct device_attribute attr; |
52 | struct list_head node; | 61 | struct list_head tz_node; /* node in tz->thermal_instances */ |
62 | struct list_head cdev_node; /* node in cdev->thermal_instances */ | ||
53 | }; | 63 | }; |
54 | 64 | ||
55 | static DEFINE_IDR(thermal_tz_idr); | 65 | static DEFINE_IDR(thermal_tz_idr); |
@@ -308,8 +318,9 @@ passive_store(struct device *dev, struct device_attribute *attr, | |||
308 | if (!strncmp("Processor", cdev->type, | 318 | if (!strncmp("Processor", cdev->type, |
309 | sizeof("Processor"))) | 319 | sizeof("Processor"))) |
310 | thermal_zone_bind_cooling_device(tz, | 320 | thermal_zone_bind_cooling_device(tz, |
311 | THERMAL_TRIPS_NONE, | 321 | THERMAL_TRIPS_NONE, cdev, |
312 | cdev); | 322 | THERMAL_NO_LIMIT, |
323 | THERMAL_NO_LIMIT); | ||
313 | } | 324 | } |
314 | mutex_unlock(&thermal_list_lock); | 325 | mutex_unlock(&thermal_list_lock); |
315 | if (!tz->passive_delay) | 326 | if (!tz->passive_delay) |
@@ -327,9 +338,6 @@ passive_store(struct device *dev, struct device_attribute *attr, | |||
327 | tz->passive_delay = 0; | 338 | tz->passive_delay = 0; |
328 | } | 339 | } |
329 | 340 | ||
330 | tz->tc1 = 1; | ||
331 | tz->tc2 = 1; | ||
332 | |||
333 | tz->forced_passive = state; | 341 | tz->forced_passive = state; |
334 | 342 | ||
335 | thermal_zone_device_update(tz); | 343 | thermal_zone_device_update(tz); |
@@ -425,10 +433,10 @@ static ssize_t | |||
425 | thermal_cooling_device_trip_point_show(struct device *dev, | 433 | thermal_cooling_device_trip_point_show(struct device *dev, |
426 | struct device_attribute *attr, char *buf) | 434 | struct device_attribute *attr, char *buf) |
427 | { | 435 | { |
428 | struct thermal_cooling_device_instance *instance; | 436 | struct thermal_instance *instance; |
429 | 437 | ||
430 | instance = | 438 | instance = |
431 | container_of(attr, struct thermal_cooling_device_instance, attr); | 439 | container_of(attr, struct thermal_instance, attr); |
432 | 440 | ||
433 | if (instance->trip == THERMAL_TRIPS_NONE) | 441 | if (instance->trip == THERMAL_TRIPS_NONE) |
434 | return sprintf(buf, "-1\n"); | 442 | return sprintf(buf, "-1\n"); |
@@ -590,7 +598,7 @@ thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) | |||
590 | temp->tz = tz; | 598 | temp->tz = tz; |
591 | hwmon->count++; | 599 | hwmon->count++; |
592 | 600 | ||
593 | snprintf(temp->temp_input.name, THERMAL_NAME_LENGTH, | 601 | snprintf(temp->temp_input.name, sizeof(temp->temp_input.name), |
594 | "temp%d_input", hwmon->count); | 602 | "temp%d_input", hwmon->count); |
595 | temp->temp_input.attr.attr.name = temp->temp_input.name; | 603 | temp->temp_input.attr.attr.name = temp->temp_input.name; |
596 | temp->temp_input.attr.attr.mode = 0444; | 604 | temp->temp_input.attr.attr.mode = 0444; |
@@ -603,7 +611,8 @@ thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) | |||
603 | if (tz->ops->get_crit_temp) { | 611 | if (tz->ops->get_crit_temp) { |
604 | unsigned long temperature; | 612 | unsigned long temperature; |
605 | if (!tz->ops->get_crit_temp(tz, &temperature)) { | 613 | if (!tz->ops->get_crit_temp(tz, &temperature)) { |
606 | snprintf(temp->temp_crit.name, THERMAL_NAME_LENGTH, | 614 | snprintf(temp->temp_crit.name, |
615 | sizeof(temp->temp_crit.name), | ||
607 | "temp%d_crit", hwmon->count); | 616 | "temp%d_crit", hwmon->count); |
608 | temp->temp_crit.attr.attr.name = temp->temp_crit.name; | 617 | temp->temp_crit.attr.attr.name = temp->temp_crit.name; |
609 | temp->temp_crit.attr.attr.mode = 0444; | 618 | temp->temp_crit.attr.attr.mode = 0444; |
@@ -704,74 +713,6 @@ static void thermal_zone_device_set_polling(struct thermal_zone_device *tz, | |||
704 | cancel_delayed_work(&tz->poll_queue); | 713 | cancel_delayed_work(&tz->poll_queue); |
705 | } | 714 | } |
706 | 715 | ||
707 | static void thermal_zone_device_passive(struct thermal_zone_device *tz, | ||
708 | int temp, int trip_temp, int trip) | ||
709 | { | ||
710 | int trend = 0; | ||
711 | struct thermal_cooling_device_instance *instance; | ||
712 | struct thermal_cooling_device *cdev; | ||
713 | long state, max_state; | ||
714 | |||
715 | /* | ||
716 | * Above Trip? | ||
717 | * ----------- | ||
718 | * Calculate the thermal trend (using the passive cooling equation) | ||
719 | * and modify the performance limit for all passive cooling devices | ||
720 | * accordingly. Note that we assume symmetry. | ||
721 | */ | ||
722 | if (temp >= trip_temp) { | ||
723 | tz->passive = true; | ||
724 | |||
725 | trend = (tz->tc1 * (temp - tz->last_temperature)) + | ||
726 | (tz->tc2 * (temp - trip_temp)); | ||
727 | |||
728 | /* Heating up? */ | ||
729 | if (trend > 0) { | ||
730 | list_for_each_entry(instance, &tz->cooling_devices, | ||
731 | node) { | ||
732 | if (instance->trip != trip) | ||
733 | continue; | ||
734 | cdev = instance->cdev; | ||
735 | cdev->ops->get_cur_state(cdev, &state); | ||
736 | cdev->ops->get_max_state(cdev, &max_state); | ||
737 | if (state++ < max_state) | ||
738 | cdev->ops->set_cur_state(cdev, state); | ||
739 | } | ||
740 | } else if (trend < 0) { /* Cooling off? */ | ||
741 | list_for_each_entry(instance, &tz->cooling_devices, | ||
742 | node) { | ||
743 | if (instance->trip != trip) | ||
744 | continue; | ||
745 | cdev = instance->cdev; | ||
746 | cdev->ops->get_cur_state(cdev, &state); | ||
747 | cdev->ops->get_max_state(cdev, &max_state); | ||
748 | if (state > 0) | ||
749 | cdev->ops->set_cur_state(cdev, --state); | ||
750 | } | ||
751 | } | ||
752 | return; | ||
753 | } | ||
754 | |||
755 | /* | ||
756 | * Below Trip? | ||
757 | * ----------- | ||
758 | * Implement passive cooling hysteresis to slowly increase performance | ||
759 | * and avoid thrashing around the passive trip point. Note that we | ||
760 | * assume symmetry. | ||
761 | */ | ||
762 | list_for_each_entry(instance, &tz->cooling_devices, node) { | ||
763 | if (instance->trip != trip) | ||
764 | continue; | ||
765 | cdev = instance->cdev; | ||
766 | cdev->ops->get_cur_state(cdev, &state); | ||
767 | cdev->ops->get_max_state(cdev, &max_state); | ||
768 | if (state > 0) | ||
769 | cdev->ops->set_cur_state(cdev, --state); | ||
770 | if (state == 0) | ||
771 | tz->passive = false; | ||
772 | } | ||
773 | } | ||
774 | |||
775 | static void thermal_zone_device_check(struct work_struct *work) | 716 | static void thermal_zone_device_check(struct work_struct *work) |
776 | { | 717 | { |
777 | struct thermal_zone_device *tz = container_of(work, struct | 718 | struct thermal_zone_device *tz = container_of(work, struct |
@@ -791,12 +732,14 @@ static void thermal_zone_device_check(struct work_struct *work) | |||
791 | */ | 732 | */ |
792 | int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, | 733 | int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, |
793 | int trip, | 734 | int trip, |
794 | struct thermal_cooling_device *cdev) | 735 | struct thermal_cooling_device *cdev, |
736 | unsigned long upper, unsigned long lower) | ||
795 | { | 737 | { |
796 | struct thermal_cooling_device_instance *dev; | 738 | struct thermal_instance *dev; |
797 | struct thermal_cooling_device_instance *pos; | 739 | struct thermal_instance *pos; |
798 | struct thermal_zone_device *pos1; | 740 | struct thermal_zone_device *pos1; |
799 | struct thermal_cooling_device *pos2; | 741 | struct thermal_cooling_device *pos2; |
742 | unsigned long max_state; | ||
800 | int result; | 743 | int result; |
801 | 744 | ||
802 | if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE)) | 745 | if (trip >= tz->trips || (trip < 0 && trip != THERMAL_TRIPS_NONE)) |
@@ -814,13 +757,26 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, | |||
814 | if (tz != pos1 || cdev != pos2) | 757 | if (tz != pos1 || cdev != pos2) |
815 | return -EINVAL; | 758 | return -EINVAL; |
816 | 759 | ||
760 | cdev->ops->get_max_state(cdev, &max_state); | ||
761 | |||
762 | /* lower default 0, upper default max_state */ | ||
763 | lower = lower == THERMAL_NO_LIMIT ? 0 : lower; | ||
764 | upper = upper == THERMAL_NO_LIMIT ? max_state : upper; | ||
765 | |||
766 | if (lower > upper || upper > max_state) | ||
767 | return -EINVAL; | ||
768 | |||
817 | dev = | 769 | dev = |
818 | kzalloc(sizeof(struct thermal_cooling_device_instance), GFP_KERNEL); | 770 | kzalloc(sizeof(struct thermal_instance), GFP_KERNEL); |
819 | if (!dev) | 771 | if (!dev) |
820 | return -ENOMEM; | 772 | return -ENOMEM; |
821 | dev->tz = tz; | 773 | dev->tz = tz; |
822 | dev->cdev = cdev; | 774 | dev->cdev = cdev; |
823 | dev->trip = trip; | 775 | dev->trip = trip; |
776 | dev->upper = upper; | ||
777 | dev->lower = lower; | ||
778 | dev->target = THERMAL_NO_TARGET; | ||
779 | |||
824 | result = get_idr(&tz->idr, &tz->lock, &dev->id); | 780 | result = get_idr(&tz->idr, &tz->lock, &dev->id); |
825 | if (result) | 781 | if (result) |
826 | goto free_mem; | 782 | goto free_mem; |
@@ -841,13 +797,17 @@ int thermal_zone_bind_cooling_device(struct thermal_zone_device *tz, | |||
841 | goto remove_symbol_link; | 797 | goto remove_symbol_link; |
842 | 798 | ||
843 | mutex_lock(&tz->lock); | 799 | mutex_lock(&tz->lock); |
844 | list_for_each_entry(pos, &tz->cooling_devices, node) | 800 | mutex_lock(&cdev->lock); |
801 | list_for_each_entry(pos, &tz->thermal_instances, tz_node) | ||
845 | if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { | 802 | if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { |
846 | result = -EEXIST; | 803 | result = -EEXIST; |
847 | break; | 804 | break; |
848 | } | 805 | } |
849 | if (!result) | 806 | if (!result) { |
850 | list_add_tail(&dev->node, &tz->cooling_devices); | 807 | list_add_tail(&dev->tz_node, &tz->thermal_instances); |
808 | list_add_tail(&dev->cdev_node, &cdev->thermal_instances); | ||
809 | } | ||
810 | mutex_unlock(&cdev->lock); | ||
851 | mutex_unlock(&tz->lock); | 811 | mutex_unlock(&tz->lock); |
852 | 812 | ||
853 | if (!result) | 813 | if (!result) |
@@ -877,16 +837,20 @@ int thermal_zone_unbind_cooling_device(struct thermal_zone_device *tz, | |||
877 | int trip, | 837 | int trip, |
878 | struct thermal_cooling_device *cdev) | 838 | struct thermal_cooling_device *cdev) |
879 | { | 839 | { |
880 | struct thermal_cooling_device_instance *pos, *next; | 840 | struct thermal_instance *pos, *next; |
881 | 841 | ||
882 | mutex_lock(&tz->lock); | 842 | mutex_lock(&tz->lock); |
883 | list_for_each_entry_safe(pos, next, &tz->cooling_devices, node) { | 843 | mutex_lock(&cdev->lock); |
844 | list_for_each_entry_safe(pos, next, &tz->thermal_instances, tz_node) { | ||
884 | if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { | 845 | if (pos->tz == tz && pos->trip == trip && pos->cdev == cdev) { |
885 | list_del(&pos->node); | 846 | list_del(&pos->tz_node); |
847 | list_del(&pos->cdev_node); | ||
848 | mutex_unlock(&cdev->lock); | ||
886 | mutex_unlock(&tz->lock); | 849 | mutex_unlock(&tz->lock); |
887 | goto unbind; | 850 | goto unbind; |
888 | } | 851 | } |
889 | } | 852 | } |
853 | mutex_unlock(&cdev->lock); | ||
890 | mutex_unlock(&tz->lock); | 854 | mutex_unlock(&tz->lock); |
891 | 855 | ||
892 | return -ENODEV; | 856 | return -ENODEV; |
@@ -934,7 +898,7 @@ thermal_cooling_device_register(char *type, void *devdata, | |||
934 | struct thermal_zone_device *pos; | 898 | struct thermal_zone_device *pos; |
935 | int result; | 899 | int result; |
936 | 900 | ||
937 | if (strlen(type) >= THERMAL_NAME_LENGTH) | 901 | if (type && strlen(type) >= THERMAL_NAME_LENGTH) |
938 | return ERR_PTR(-EINVAL); | 902 | return ERR_PTR(-EINVAL); |
939 | 903 | ||
940 | if (!ops || !ops->get_max_state || !ops->get_cur_state || | 904 | if (!ops || !ops->get_max_state || !ops->get_cur_state || |
@@ -951,8 +915,11 @@ thermal_cooling_device_register(char *type, void *devdata, | |||
951 | return ERR_PTR(result); | 915 | return ERR_PTR(result); |
952 | } | 916 | } |
953 | 917 | ||
954 | strcpy(cdev->type, type); | 918 | strcpy(cdev->type, type ? : ""); |
919 | mutex_init(&cdev->lock); | ||
920 | INIT_LIST_HEAD(&cdev->thermal_instances); | ||
955 | cdev->ops = ops; | 921 | cdev->ops = ops; |
922 | cdev->updated = true; | ||
956 | cdev->device.class = &thermal_class; | 923 | cdev->device.class = &thermal_class; |
957 | cdev->devdata = devdata; | 924 | cdev->devdata = devdata; |
958 | dev_set_name(&cdev->device, "cooling_device%d", cdev->id); | 925 | dev_set_name(&cdev->device, "cooling_device%d", cdev->id); |
@@ -1044,6 +1011,136 @@ void thermal_cooling_device_unregister(struct | |||
1044 | } | 1011 | } |
1045 | EXPORT_SYMBOL(thermal_cooling_device_unregister); | 1012 | EXPORT_SYMBOL(thermal_cooling_device_unregister); |
1046 | 1013 | ||
1014 | static void thermal_cdev_do_update(struct thermal_cooling_device *cdev) | ||
1015 | { | ||
1016 | struct thermal_instance *instance; | ||
1017 | unsigned long target = 0; | ||
1018 | |||
1019 | /* cooling device is updated*/ | ||
1020 | if (cdev->updated) | ||
1021 | return; | ||
1022 | |||
1023 | mutex_lock(&cdev->lock); | ||
1024 | /* Make sure cdev enters the deepest cooling state */ | ||
1025 | list_for_each_entry(instance, &cdev->thermal_instances, cdev_node) { | ||
1026 | if (instance->target == THERMAL_NO_TARGET) | ||
1027 | continue; | ||
1028 | if (instance->target > target) | ||
1029 | target = instance->target; | ||
1030 | } | ||
1031 | mutex_unlock(&cdev->lock); | ||
1032 | cdev->ops->set_cur_state(cdev, target); | ||
1033 | cdev->updated = true; | ||
1034 | } | ||
1035 | |||
1036 | static void thermal_zone_do_update(struct thermal_zone_device *tz) | ||
1037 | { | ||
1038 | struct thermal_instance *instance; | ||
1039 | |||
1040 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) | ||
1041 | thermal_cdev_do_update(instance->cdev); | ||
1042 | } | ||
1043 | |||
1044 | /* | ||
1045 | * Cooling algorithm for both active and passive cooling | ||
1046 | * | ||
1047 | * 1. if the temperature is higher than a trip point, | ||
1048 | * a. if the trend is THERMAL_TREND_RAISING, use higher cooling | ||
1049 | * state for this trip point | ||
1050 | * b. if the trend is THERMAL_TREND_DROPPING, use lower cooling | ||
1051 | * state for this trip point | ||
1052 | * | ||
1053 | * 2. if the temperature is lower than a trip point, use lower | ||
1054 | * cooling state for this trip point | ||
1055 | * | ||
1056 | * Note that this behaves the same as the previous passive cooling | ||
1057 | * algorithm. | ||
1058 | */ | ||
1059 | |||
1060 | static void thermal_zone_trip_update(struct thermal_zone_device *tz, | ||
1061 | int trip, long temp) | ||
1062 | { | ||
1063 | struct thermal_instance *instance; | ||
1064 | struct thermal_cooling_device *cdev = NULL; | ||
1065 | unsigned long cur_state, max_state; | ||
1066 | long trip_temp; | ||
1067 | enum thermal_trip_type trip_type; | ||
1068 | enum thermal_trend trend; | ||
1069 | |||
1070 | if (trip == THERMAL_TRIPS_NONE) { | ||
1071 | trip_temp = tz->forced_passive; | ||
1072 | trip_type = THERMAL_TRIPS_NONE; | ||
1073 | } else { | ||
1074 | tz->ops->get_trip_temp(tz, trip, &trip_temp); | ||
1075 | tz->ops->get_trip_type(tz, trip, &trip_type); | ||
1076 | } | ||
1077 | |||
1078 | if (!tz->ops->get_trend || tz->ops->get_trend(tz, trip, &trend)) { | ||
1079 | /* | ||
1080 | * compare the current temperature and previous temperature | ||
1081 | * to get the thermal trend, if no special requirement | ||
1082 | */ | ||
1083 | if (tz->temperature > tz->last_temperature) | ||
1084 | trend = THERMAL_TREND_RAISING; | ||
1085 | else if (tz->temperature < tz->last_temperature) | ||
1086 | trend = THERMAL_TREND_DROPPING; | ||
1087 | else | ||
1088 | trend = THERMAL_TREND_STABLE; | ||
1089 | } | ||
1090 | |||
1091 | if (temp >= trip_temp) { | ||
1092 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) { | ||
1093 | if (instance->trip != trip) | ||
1094 | continue; | ||
1095 | |||
1096 | cdev = instance->cdev; | ||
1097 | |||
1098 | cdev->ops->get_cur_state(cdev, &cur_state); | ||
1099 | cdev->ops->get_max_state(cdev, &max_state); | ||
1100 | |||
1101 | if (trend == THERMAL_TREND_RAISING) { | ||
1102 | cur_state = cur_state < instance->upper ? | ||
1103 | (cur_state + 1) : instance->upper; | ||
1104 | } else if (trend == THERMAL_TREND_DROPPING) { | ||
1105 | cur_state = cur_state > instance->lower ? | ||
1106 | (cur_state - 1) : instance->lower; | ||
1107 | } | ||
1108 | |||
1109 | /* activate a passive thermal instance */ | ||
1110 | if ((trip_type == THERMAL_TRIP_PASSIVE || | ||
1111 | trip_type == THERMAL_TRIPS_NONE) && | ||
1112 | instance->target == THERMAL_NO_TARGET) | ||
1113 | tz->passive++; | ||
1114 | |||
1115 | instance->target = cur_state; | ||
1116 | cdev->updated = false; /* cooling device needs update */ | ||
1117 | } | ||
1118 | } else { /* below trip */ | ||
1119 | list_for_each_entry(instance, &tz->thermal_instances, tz_node) { | ||
1120 | if (instance->trip != trip) | ||
1121 | continue; | ||
1122 | |||
1123 | /* Do not use the inactive thermal instance */ | ||
1124 | if (instance->target == THERMAL_NO_TARGET) | ||
1125 | continue; | ||
1126 | cdev = instance->cdev; | ||
1127 | cdev->ops->get_cur_state(cdev, &cur_state); | ||
1128 | |||
1129 | cur_state = cur_state > instance->lower ? | ||
1130 | (cur_state - 1) : THERMAL_NO_TARGET; | ||
1131 | |||
1132 | /* deactivate a passive thermal instance */ | ||
1133 | if ((trip_type == THERMAL_TRIP_PASSIVE || | ||
1134 | trip_type == THERMAL_TRIPS_NONE) && | ||
1135 | cur_state == THERMAL_NO_TARGET) | ||
1136 | tz->passive--; | ||
1137 | instance->target = cur_state; | ||
1138 | cdev->updated = false; /* cooling device needs update */ | ||
1139 | } | ||
1140 | } | ||
1141 | |||
1142 | return; | ||
1143 | } | ||
1047 | /** | 1144 | /** |
1048 | * thermal_zone_device_update - force an update of a thermal zone's state | 1145 | * thermal_zone_device_update - force an update of a thermal zone's state |
1049 | * @ttz: the thermal zone to update | 1146 | * @ttz: the thermal zone to update |
@@ -1054,8 +1151,6 @@ void thermal_zone_device_update(struct thermal_zone_device *tz) | |||
1054 | int count, ret = 0; | 1151 | int count, ret = 0; |
1055 | long temp, trip_temp; | 1152 | long temp, trip_temp; |
1056 | enum thermal_trip_type trip_type; | 1153 | enum thermal_trip_type trip_type; |
1057 | struct thermal_cooling_device_instance *instance; | ||
1058 | struct thermal_cooling_device *cdev; | ||
1059 | 1154 | ||
1060 | mutex_lock(&tz->lock); | 1155 | mutex_lock(&tz->lock); |
1061 | 1156 | ||
@@ -1065,6 +1160,9 @@ void thermal_zone_device_update(struct thermal_zone_device *tz) | |||
1065 | goto leave; | 1160 | goto leave; |
1066 | } | 1161 | } |
1067 | 1162 | ||
1163 | tz->last_temperature = tz->temperature; | ||
1164 | tz->temperature = temp; | ||
1165 | |||
1068 | for (count = 0; count < tz->trips; count++) { | 1166 | for (count = 0; count < tz->trips; count++) { |
1069 | tz->ops->get_trip_type(tz, count, &trip_type); | 1167 | tz->ops->get_trip_type(tz, count, &trip_type); |
1070 | tz->ops->get_trip_temp(tz, count, &trip_temp); | 1168 | tz->ops->get_trip_temp(tz, count, &trip_temp); |
@@ -1088,32 +1186,18 @@ void thermal_zone_device_update(struct thermal_zone_device *tz) | |||
1088 | tz->ops->notify(tz, count, trip_type); | 1186 | tz->ops->notify(tz, count, trip_type); |
1089 | break; | 1187 | break; |
1090 | case THERMAL_TRIP_ACTIVE: | 1188 | case THERMAL_TRIP_ACTIVE: |
1091 | list_for_each_entry(instance, &tz->cooling_devices, | 1189 | thermal_zone_trip_update(tz, count, temp); |
1092 | node) { | ||
1093 | if (instance->trip != count) | ||
1094 | continue; | ||
1095 | |||
1096 | cdev = instance->cdev; | ||
1097 | |||
1098 | if (temp >= trip_temp) | ||
1099 | cdev->ops->set_cur_state(cdev, 1); | ||
1100 | else | ||
1101 | cdev->ops->set_cur_state(cdev, 0); | ||
1102 | } | ||
1103 | break; | 1190 | break; |
1104 | case THERMAL_TRIP_PASSIVE: | 1191 | case THERMAL_TRIP_PASSIVE: |
1105 | if (temp >= trip_temp || tz->passive) | 1192 | if (temp >= trip_temp || tz->passive) |
1106 | thermal_zone_device_passive(tz, temp, | 1193 | thermal_zone_trip_update(tz, count, temp); |
1107 | trip_temp, count); | ||
1108 | break; | 1194 | break; |
1109 | } | 1195 | } |
1110 | } | 1196 | } |
1111 | 1197 | ||
1112 | if (tz->forced_passive) | 1198 | if (tz->forced_passive) |
1113 | thermal_zone_device_passive(tz, temp, tz->forced_passive, | 1199 | thermal_zone_trip_update(tz, THERMAL_TRIPS_NONE, temp); |
1114 | THERMAL_TRIPS_NONE); | 1200 | thermal_zone_do_update(tz); |
1115 | |||
1116 | tz->last_temperature = temp; | ||
1117 | 1201 | ||
1118 | leave: | 1202 | leave: |
1119 | if (tz->passive) | 1203 | if (tz->passive) |
@@ -1236,8 +1320,6 @@ static void remove_trip_attrs(struct thermal_zone_device *tz) | |||
1236 | * @mask: a bit string indicating the writeablility of trip points | 1320 | * @mask: a bit string indicating the writeablility of trip points |
1237 | * @devdata: private device data | 1321 | * @devdata: private device data |
1238 | * @ops: standard thermal zone device callbacks | 1322 | * @ops: standard thermal zone device callbacks |
1239 | * @tc1: thermal coefficient 1 for passive calculations | ||
1240 | * @tc2: thermal coefficient 2 for passive calculations | ||
1241 | * @passive_delay: number of milliseconds to wait between polls when | 1323 | * @passive_delay: number of milliseconds to wait between polls when |
1242 | * performing passive cooling | 1324 | * performing passive cooling |
1243 | * @polling_delay: number of milliseconds to wait between polls when checking | 1325 | * @polling_delay: number of milliseconds to wait between polls when checking |
@@ -1245,13 +1327,12 @@ static void remove_trip_attrs(struct thermal_zone_device *tz) | |||
1245 | * driven systems) | 1327 | * driven systems) |
1246 | * | 1328 | * |
1247 | * thermal_zone_device_unregister() must be called when the device is no | 1329 | * thermal_zone_device_unregister() must be called when the device is no |
1248 | * longer needed. The passive cooling formula uses tc1 and tc2 as described in | 1330 | * longer needed. The passive cooling depends on the .get_trend() return value. |
1249 | * section 11.1.5.1 of the ACPI specification 3.0. | ||
1250 | */ | 1331 | */ |
1251 | struct thermal_zone_device *thermal_zone_device_register(const char *type, | 1332 | struct thermal_zone_device *thermal_zone_device_register(const char *type, |
1252 | int trips, int mask, void *devdata, | 1333 | int trips, int mask, void *devdata, |
1253 | const struct thermal_zone_device_ops *ops, | 1334 | const struct thermal_zone_device_ops *ops, |
1254 | int tc1, int tc2, int passive_delay, int polling_delay) | 1335 | int passive_delay, int polling_delay) |
1255 | { | 1336 | { |
1256 | struct thermal_zone_device *tz; | 1337 | struct thermal_zone_device *tz; |
1257 | struct thermal_cooling_device *pos; | 1338 | struct thermal_cooling_device *pos; |
@@ -1260,7 +1341,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, | |||
1260 | int count; | 1341 | int count; |
1261 | int passive = 0; | 1342 | int passive = 0; |
1262 | 1343 | ||
1263 | if (strlen(type) >= THERMAL_NAME_LENGTH) | 1344 | if (type && strlen(type) >= THERMAL_NAME_LENGTH) |
1264 | return ERR_PTR(-EINVAL); | 1345 | return ERR_PTR(-EINVAL); |
1265 | 1346 | ||
1266 | if (trips > THERMAL_MAX_TRIPS || trips < 0 || mask >> trips) | 1347 | if (trips > THERMAL_MAX_TRIPS || trips < 0 || mask >> trips) |
@@ -1273,7 +1354,7 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, | |||
1273 | if (!tz) | 1354 | if (!tz) |
1274 | return ERR_PTR(-ENOMEM); | 1355 | return ERR_PTR(-ENOMEM); |
1275 | 1356 | ||
1276 | INIT_LIST_HEAD(&tz->cooling_devices); | 1357 | INIT_LIST_HEAD(&tz->thermal_instances); |
1277 | idr_init(&tz->idr); | 1358 | idr_init(&tz->idr); |
1278 | mutex_init(&tz->lock); | 1359 | mutex_init(&tz->lock); |
1279 | result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id); | 1360 | result = get_idr(&thermal_tz_idr, &thermal_idr_lock, &tz->id); |
@@ -1282,13 +1363,11 @@ struct thermal_zone_device *thermal_zone_device_register(const char *type, | |||
1282 | return ERR_PTR(result); | 1363 | return ERR_PTR(result); |
1283 | } | 1364 | } |
1284 | 1365 | ||
1285 | strcpy(tz->type, type); | 1366 | strcpy(tz->type, type ? : ""); |
1286 | tz->ops = ops; | 1367 | tz->ops = ops; |
1287 | tz->device.class = &thermal_class; | 1368 | tz->device.class = &thermal_class; |
1288 | tz->devdata = devdata; | 1369 | tz->devdata = devdata; |
1289 | tz->trips = trips; | 1370 | tz->trips = trips; |
1290 | tz->tc1 = tc1; | ||
1291 | tz->tc2 = tc2; | ||
1292 | tz->passive_delay = passive_delay; | 1371 | tz->passive_delay = passive_delay; |
1293 | tz->polling_delay = polling_delay; | 1372 | tz->polling_delay = polling_delay; |
1294 | 1373 | ||