diff -Nru thermald-1.4.3/debian/changelog thermald-1.4.3/debian/changelog --- thermald-1.4.3/debian/changelog 2015-08-21 18:48:32.000000000 +0000 +++ thermald-1.4.3/debian/changelog 2016-01-29 10:22:39.000000000 +0000 @@ -1,3 +1,14 @@ +thermald (1.4.3-5ubuntu1) wily; urgency=medium + + * Fix frequency scaling issue on specific Intel CPUs (LP: #1480349) + - roll earlier patches that allow us to cleanly patch the issue + - Error recovery when sysfs attrib read fails + - Remove wild card for loading + - Move parser init to thd_engine + - Add white list of the cpu ids + + -- Colin King Tue, 26 Jan 2016 10:15:11 +0000 + thermald (1.4.3-5) unstable; urgency=medium * cdev: turn some info messages to debug to reduce syslog spamming diff -Nru thermald-1.4.3/debian/patches/0100-Remove-trailing-from-THD-engine-failure-message.patch thermald-1.4.3/debian/patches/0100-Remove-trailing-from-THD-engine-failure-message.patch --- thermald-1.4.3/debian/patches/0100-Remove-trailing-from-THD-engine-failure-message.patch 1970-01-01 00:00:00.000000000 +0000 +++ thermald-1.4.3/debian/patches/0100-Remove-trailing-from-THD-engine-failure-message.patch 2016-01-26 11:08:41.000000000 +0000 @@ -0,0 +1,39 @@ +From 9cb58a6fc554b4c005bef7df29cb254dca18935c Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Thu, 10 Sep 2015 12:47:37 +0100 +Subject: [PATCH] Remove trailing ':' from THD engine failure message + +Running thermald on a machine with no thermal zones or sensors one +sees the final log messages as follows: + +ML zone: invalid sensor type TSKN +Zone update failed: unable to bind +No Thermal Zones found +No thermal sensors found +THD engine start failed: + +..the final message ends with a ':' making one wonder if there +are any following messages, which there are none. Remove the trailing +':' as it is confusing to the user. + +Signed-off-by: Colin Ian King +--- + src/thd_engine_default.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/thd_engine_default.cpp b/src/thd_engine_default.cpp +index d10ae59..1ebee6e 100644 +--- a/src/thd_engine_default.cpp ++++ b/src/thd_engine_default.cpp +@@ -629,7 +629,7 @@ int thd_engine_create_default_engine(bool ignore_cpuid_check, + // Initialize thermald objects + thd_engine->set_poll_interval(thd_poll_interval); + if (thd_engine->thd_engine_start(ignore_cpuid_check) != THD_SUCCESS) { +- thd_log_error("THD engine start failed:\n"); ++ thd_log_error("THD engine start failed\n"); + return THD_ERROR; + } + +-- +2.7.0.rc3 + diff -Nru thermald-1.4.3/debian/patches/0101-Remove-from-No-coretemp-sysfs-found.patch thermald-1.4.3/debian/patches/0101-Remove-from-No-coretemp-sysfs-found.patch --- thermald-1.4.3/debian/patches/0101-Remove-from-No-coretemp-sysfs-found.patch 1970-01-01 00:00:00.000000000 +0000 +++ thermald-1.4.3/debian/patches/0101-Remove-from-No-coretemp-sysfs-found.patch 2016-01-26 11:08:41.000000000 +0000 @@ -0,0 +1,29 @@ +From 061730cf6a2d6302b205f323545c4483bf3a8e23 Mon Sep 17 00:00:00 2001 +From: Colin Ian King +Date: Fri, 31 Jul 2015 10:30:58 +0100 +Subject: [PATCH] Remove !! from "No coretemp sysfs found" + +Users are getting alarmed by the double exclamation marks in this +message, remove the !! exclamation marks + +Signed-off-by: Colin Ian King +--- + src/thd_engine_default.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/thd_engine_default.cpp b/src/thd_engine_default.cpp +index 1680920..d10ae59 100644 +--- a/src/thd_engine_default.cpp ++++ b/src/thd_engine_default.cpp +@@ -185,7 +185,7 @@ int cthd_engine_default::read_thermal_sensors() { + } + if (index == current_sensor_index) { + // No coretemp sysfs exist, try hwmon +- thd_log_warn("Thermal DTS: No coretemp sysfs found!!\n"); ++ thd_log_warn("Thermal DTS: No coretemp sysfs found\n"); + } + current_sensor_index = index; + // Add from XML sensor config +-- +2.7.0.rc3 + diff -Nru thermald-1.4.3/debian/patches/0102-Add-new-option-for-config-file.patch thermald-1.4.3/debian/patches/0102-Add-new-option-for-config-file.patch --- thermald-1.4.3/debian/patches/0102-Add-new-option-for-config-file.patch 1970-01-01 00:00:00.000000000 +0000 +++ thermald-1.4.3/debian/patches/0102-Add-new-option-for-config-file.patch 2016-01-26 11:08:41.000000000 +0000 @@ -0,0 +1,234 @@ +From 5f9f81c7bdcd6c008cfc8bc83eccf84209418293 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Tue, 20 Oct 2015 09:13:00 -0700 +Subject: [PATCH] Add new option for config file + +Added option so that config file can be provided via command line +option. +--- + src/android_main.cpp | 4 ++-- + src/main.cpp | 15 ++++++++------- + src/thd_dbus_interface.cpp | 9 ++++++++- + src/thd_engine.h | 7 +++++++ + src/thd_engine_default.cpp | 7 +++++-- + src/thd_engine_default.h | 3 +-- + src/thd_parse.cpp | 25 ++++++++++++++++--------- + src/thd_parse.h | 2 +- + 8 files changed, 48 insertions(+), 24 deletions(-) + +diff --git a/src/android_main.cpp b/src/android_main.cpp +index 39d4155..96dc046 100644 +--- a/src/android_main.cpp ++++ b/src/android_main.cpp +@@ -213,8 +213,8 @@ int main(int argc, char *argv[]) { + "Linux Thermal Daemon is starting mode %d : poll_interval %d :ex_control %d\n", + no_daemon, thd_poll_interval, exclusive_control); + +- if (thd_engine_create_default_engine(false, +- exclusive_control) != THD_SUCCESS) { ++ if (thd_engine_create_default_engine(false, exclusive_control, ++ NULL) != THD_SUCCESS) { + exit(EXIT_FAILURE); + } + +diff --git a/src/main.cpp b/src/main.cpp +index 2b1befb..b04b04e 100644 +--- a/src/main.cpp ++++ b/src/main.cpp +@@ -111,8 +111,8 @@ void thd_logger(const gchar *log_domain, GLogLevelFlags log_level, + + void clean_up_lockfile(void) { + if (lock_file_handle != -1) { +- (void)close(lock_file_handle); +- (void)unlink(lock_file); ++ (void) close(lock_file_handle); ++ (void) unlink(lock_file); + } + } + +@@ -153,6 +153,7 @@ int main(int argc, char *argv[]) { + gboolean log_debug = FALSE; + gboolean no_daemon = FALSE; + gboolean test_mode = FALSE; ++ gchar *conf_file = NULL; + gint poll_interval = -1; + gboolean success; + GOptionContext *opt_ctx; +@@ -178,9 +179,9 @@ int main(int argc, char *argv[]) { + G_OPTION_ARG_NONE, &exclusive_control, N_( + "Take over thermal control from kernel thermal driver."), + NULL }, { "ignore-cpuid-check", 0, 0, G_OPTION_ARG_NONE, +- &ignore_cpuid_check, N_("Ignore CPU ID check."), NULL }, +- +- { NULL } }; ++ &ignore_cpuid_check, N_("Ignore CPU ID check."), NULL }, { ++ "config-file", 0, 0, G_OPTION_ARG_STRING, &conf_file, N_( ++ "configuration file"), NULL }, { NULL } }; + + if (!g_module_supported()) { + fprintf(stderr, "GModules are not supported on your platform!\n"); +@@ -286,8 +287,8 @@ int main(int argc, char *argv[]) { + } + } + +- if (thd_engine_create_default_engine((bool)ignore_cpuid_check, +- (bool)exclusive_control) != THD_SUCCESS) { ++ if (thd_engine_create_default_engine((bool) ignore_cpuid_check, ++ (bool) exclusive_control, conf_file) != THD_SUCCESS) { + clean_up_lockfile(); + closelog(); + exit(EXIT_FAILURE); +diff --git a/src/thd_dbus_interface.cpp b/src/thd_dbus_interface.cpp +index 8fe974c..daa7849 100644 +--- a/src/thd_dbus_interface.cpp ++++ b/src/thd_dbus_interface.cpp +@@ -205,7 +205,14 @@ gboolean thd_dbus_interface_reinit(PrefObject *obj, GError **error) { + sleep(2); + if (thd_engine->get_control_mode() == EXCLUSIVE) + exclusive_control = true; +- if (thd_engine_create_default_engine(true, exclusive_control) != THD_SUCCESS) { ++ ++ std::string config_file = thd_engine->get_config_file(); ++ const char *conf_file = NULL; ++ if (!config_file.empty()) ++ conf_file = config_file.c_str(); ++ ++ if (thd_engine_create_default_engine(true, exclusive_control, ++ conf_file) != THD_SUCCESS) { + return FALSE; + } + +diff --git a/src/thd_engine.h b/src/thd_engine.h +index 89dc383..2f23466 100644 +--- a/src/thd_engine.h ++++ b/src/thd_engine.h +@@ -100,6 +100,7 @@ private: + int poll_interval_sec; + cthd_preference thd_pref; + unsigned int poll_sensor_mask; ++ std::string config_file; + + pthread_t thd_engine; + pthread_attr_t thd_attr; +@@ -208,6 +209,12 @@ public: + int get_preference() { + return preference; + } ++ void set_config_file(std::string conf_file) { ++ config_file = conf_file; ++ } ++ std::string get_config_file() { ++ return config_file; ++ } + cthd_zone *search_zone(std::string name); + cthd_cdev *search_cdev(std::string name); + cthd_sensor *search_sensor(std::string name); +diff --git a/src/thd_engine_default.cpp b/src/thd_engine_default.cpp +index 1ebee6e..cac300a 100644 +--- a/src/thd_engine_default.cpp ++++ b/src/thd_engine_default.cpp +@@ -69,7 +69,7 @@ cthd_engine_default::~cthd_engine_default() { + int cthd_engine_default::parser_init() { + if (parser_init_done) + return THD_SUCCESS; +- if (parser.parser_init() == THD_SUCCESS) { ++ if (parser.parser_init(get_config_file()) == THD_SUCCESS) { + if (parser.start_parse() == THD_SUCCESS) { + parser.dump_thermal_conf(); + parser_init_done = true; +@@ -621,13 +621,16 @@ int cthd_engine_default::read_cooling_devices() { + cthd_engine *thd_engine; + + int thd_engine_create_default_engine(bool ignore_cpuid_check, +- bool exclusive_control) { ++ bool exclusive_control, const char *conf_file) { + thd_engine = new cthd_engine_default(); + if (exclusive_control) + thd_engine->set_control_mode(EXCLUSIVE); + + // Initialize thermald objects + thd_engine->set_poll_interval(thd_poll_interval); ++ if (conf_file) ++ thd_engine->set_config_file(conf_file); ++ + if (thd_engine->thd_engine_start(ignore_cpuid_check) != THD_SUCCESS) { + thd_log_error("THD engine start failed\n"); + return THD_ERROR; +diff --git a/src/thd_engine_default.h b/src/thd_engine_default.h +index 6041626..8f0b58a 100644 +--- a/src/thd_engine_default.h ++++ b/src/thd_engine_default.h +@@ -50,6 +50,5 @@ public: + }; + + int thd_engine_create_default_engine(bool ignore_cpuid_check, +- bool exclusive_control); +- ++ bool exclusive_control, const char *config_file); + #endif /* THD_ENGINE_DEFAULT_H_ */ +diff --git a/src/thd_parse.cpp b/src/thd_parse.cpp +index 1c9ccc2..5c35f04 100644 +--- a/src/thd_parse.cpp ++++ b/src/thd_parse.cpp +@@ -46,9 +46,9 @@ void cthd_parse::string_trim(std::string &str) { + // Very simple version just checking for 0x20 not other white space chars + bool isspace(int c) { + if (c == ' ') +- return true; ++ return true; + else +- return false; ++ return false; + } + #endif + +@@ -76,19 +76,26 @@ cthd_parse::cthd_parse() : + filename_auto = name_run + "/" + "thermal-conf.xml.auto"; + } + +-int cthd_parse::parser_init() { ++int cthd_parse::parser_init(std::string config_file) { + cthd_acpi_rel rel; ++ const char *xml_config_file; + int ret; + +- ret = rel.generate_conf(filename_auto); +- if (!ret) { +- thd_log_warn("Using generated %s\n", filename_auto.c_str()); +- doc = xmlReadFile(filename_auto.c_str(), NULL, 0); ++ if (config_file.empty()) { ++ ret = rel.generate_conf(filename_auto); ++ if (!ret) { ++ thd_log_warn("Using generated %s\n", filename_auto.c_str()); ++ xml_config_file = filename_auto.c_str(); ++ } else { ++ xml_config_file = filename.c_str(); ++ } + } else { +- doc = xmlReadFile(filename.c_str(), NULL, 0); ++ xml_config_file = config_file.c_str(); + } ++ ++ doc = xmlReadFile(xml_config_file, NULL, 0); + if (doc == NULL) { +- thd_log_warn("error: could not parse file %s\n", filename.c_str()); ++ thd_log_warn("error: could not parse file %s\n", xml_config_file); + return THD_ERROR; + } + root_element = xmlDocGetRootElement(doc); +diff --git a/src/thd_parse.h b/src/thd_parse.h +index 7570c9a..ecb382b 100644 +--- a/src/thd_parse.h ++++ b/src/thd_parse.h +@@ -162,7 +162,7 @@ private: + + public: + cthd_parse(); +- int parser_init(); ++ int parser_init(std::string config_file); + void parser_deinit(); + int start_parse(); + void dump_thermal_conf(); +-- +2.7.0.rc3 + diff -Nru thermald-1.4.3/debian/patches/0103-Support-target-state.patch thermald-1.4.3/debian/patches/0103-Support-target-state.patch --- thermald-1.4.3/debian/patches/0103-Support-target-state.patch 1970-01-01 00:00:00.000000000 +0000 +++ thermald-1.4.3/debian/patches/0103-Support-target-state.patch 2016-01-26 11:08:41.000000000 +0000 @@ -0,0 +1,537 @@ +From 29b741f450d8bbbd153ebf5156f80678c2c78abd Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Tue, 20 Oct 2015 13:04:44 -0700 +Subject: [PATCH] Support target state + +When multiple trips are defined for same cdev, it is likely that +they want to limit the compensation for each trip to a value. + +For example in the below config file, when temperature reaches +40c, the max limit is 3 and when 50 it is 6 and when 60 it +is like current without any target state and will only be limited +by the max state. + + + + + THD_TEST_0 + * + QUIET + + + thd_test_ex_0 + + + thd_test_0 + 40000 + passive + + thd_cdev_0 + 3 + + + + thd_test_0 + 50000 + passive + + thd_cdev_0 + 6 + + + + thd_test_0 + 60000 + passive + + thd_cdev_0 + + + + + + + + +--- + src/thd_cdev.cpp | 111 +++++++++++++++++++++++++++++++++++++++++---- + src/thd_cdev.h | 33 +++++++++++++- + src/thd_engine_default.cpp | 6 ++- + src/thd_parse.cpp | 13 +++++- + src/thd_parse.h | 1 + + src/thd_trip_point.cpp | 18 ++++++-- + src/thd_trip_point.h | 5 +- + src/thd_zone.cpp | 9 ++-- + src/thd_zone.h | 3 +- + src/thd_zone_generic.cpp | 3 +- + 10 files changed, 178 insertions(+), 24 deletions(-) + +diff --git a/src/thd_cdev.cpp b/src/thd_cdev.cpp +index 109874e..569afaa 100644 +--- a/src/thd_cdev.cpp ++++ b/src/thd_cdev.cpp +@@ -59,8 +59,8 @@ int cthd_cdev::thd_cdev_exponential_controller(int set_point, int target_temp, + ++curr_pow; + state = base_pow_state + int_2_pow(curr_pow) * inc_dec_val; + thd_log_info( +- "consecutive call, increment exponentially state %d\n", +- state); ++ "cdev index:%d consecutive call, increment exponentially state %d\n", ++ index, state); + if ((min_state < max_state && state >= max_state) + || (min_state > max_state && state <= max_state)) { + state = max_state; +@@ -96,23 +96,51 @@ int cthd_cdev::thd_cdev_exponential_controller(int set_point, int target_temp, + } + } + +- thd_log_debug("Set : %d, %d, %d, %d, %d\n", set_point, temperature, index, +- get_curr_state(), max_state); ++ thd_log_info( ++ "Set : threshold:%d, temperature:%d, cdev:%d(%s), curr_state:%d, max_state:%d\n", ++ set_point, temperature, index, type_str.c_str(), get_curr_state(), ++ max_state); + + thd_log_debug("<>thd_cdev_set_state index:%d state:%d :%d:%d\n", index, +- state, zone_id, trip_id); ++ thd_log_debug(">>thd_cdev_set_state index:%d state:%d :%d:%d:%d\n", index, ++ state, zone_id, trip_id, target_value); + if (last_state == state && (tm - last_action_time) <= debounce_interval) { + thd_log_debug( + "Ignore: delay < debounce interval : %d, %d, %d, %d, %d\n", +@@ -123,6 +151,37 @@ int cthd_cdev::thd_cdev_set_state(int set_point, int target_temp, + if (state) { + zone_mask |= (1 << zone_id); + trip_mask |= (1 << trip_id); ++ ++ if (target_value != TRIP_PT_INVALID_TARGET_STATE) { ++ zone_trip_limits_t limit; ++ bool found = false; ++ ++ for (unsigned int i = 0; i < zone_trip_limits.size(); ++i) { ++ if (zone_trip_limits[i].zone == zone_id ++ && zone_trip_limits[i].trip == trip_id) { ++ found = true; ++ break; ++ } ++ } ++ if (!found) { ++ limit.zone = zone_id; ++ limit.trip = trip_id; ++ limit.target_value = target_value; ++ thd_log_debug("Added zone %d trip %d clamp %d\n", limit.zone, ++ limit.trip, limit.target_value); ++ zone_trip_limits.push_back(limit); ++ std::sort(zone_trip_limits.begin(), zone_trip_limits.end(), ++ sort_clamp_values); ++ } ++ set_curr_state_raw(target_value, zone_id); ++ curr_state = target_value; ++ last_action_time = tm; ++ thd_log_info( ++ "Set : threshold:%d, temperature:%d, cdev:%d(%s), curr_state:%d, max_state:%d\n", ++ set_point, temperature, index, type_str.c_str(), ++ get_curr_state(), max_state); ++ return THD_SUCCESS; ++ } + } else { + + if (zone_mask & (1 << zone_id)) { +@@ -131,7 +190,43 @@ int cthd_cdev::thd_cdev_set_state(int set_point, int target_temp, + zone_mask &= ~(1 << zone_id); + } + } +- if (zone_mask != 0 || trip_mask != 0) { ++ ++ if (zone_trip_limits.size() > 0) { ++ int length = zone_trip_limits.size(); ++ int i; ++ ++ // Just remove the current zone requesting to turn off ++ for (i = 0; i < length; ++i) { ++ if (zone_trip_limits[i].zone == zone_id ++ && zone_trip_limits[i].trip == trip_id) { ++ zone_trip_limits.erase(zone_trip_limits.begin() + i); ++ thd_log_debug("Erased [%d: %d\n", zone_id, trip_id); ++ break; ++ } ++ } ++ zone_trip_limits_t limit; ++ ++ if (zone_trip_limits.size() == 0) { ++ limit.target_value = get_min_state(); ++ limit.zone = zone_id; ++ limit.trip = trip_id; ++ } else { ++ limit = zone_trip_limits[zone_trip_limits.size() - 1]; ++ } ++ ++ if (cmp_current_state(limit.target_value) < 0) { ++ thd_log_info( ++ "new active zone; next in line %d trip %d clamp %d\n", ++ limit.zone, limit.trip, limit.target_value); ++ set_curr_state_raw(limit.target_value, zone_id); ++ thd_log_info( ++ "Set : threshold:%d, temperature:%d, cdev:%d(%s), curr_state:%d, max_state:%d\n", ++ set_point, temperature, index, type_str.c_str(), ++ get_curr_state(), max_state); ++ } ++ return THD_SUCCESS; ++ ++ } else if (zone_mask != 0 || trip_mask != 0) { + thd_log_debug( + "skip to reduce current state as this is controlled by two zone or trip actions and one is still on %lx:%lx\n", + zone_mask, trip_mask); +diff --git a/src/thd_cdev.h b/src/thd_cdev.h +index 9280d8e..dec4b3b 100644 +--- a/src/thd_cdev.h ++++ b/src/thd_cdev.h +@@ -26,11 +26,20 @@ + #define THD_CDEV_H + + #include ++#include + #include "thd_common.h" + #include "thd_sys_fs.h" + #include "thd_preference.h" + #include "thd_pid.h" + ++typedef struct { ++ int zone; ++ int trip; ++ int target_value; ++} zone_trip_limits_t; ++ ++#define ZONE_TRIP_LIMIT_COUNT 12 ++ + class cthd_cdev { + + protected: +@@ -55,6 +64,7 @@ protected: + bool pid_enable; + cthd_pid pid_ctrl; + int last_state; ++ std::vector zone_trip_limits; + + private: + unsigned int int_2_pow(int pow) { +@@ -81,7 +91,8 @@ public: + virtual ~cthd_cdev() { + } + virtual int thd_cdev_set_state(int set_point, int target_temp, +- int temperature, int state, int zone_id, int trip_id); ++ int temperature, int state, int zone_id, int trip_id, ++ int target_value); + + virtual int thd_cdev_set_min_state(int zone_id); + +@@ -163,6 +174,26 @@ public: + return false; + } + ++ int cmp_current_state(int state) { ++ if (get_curr_state() == state) ++ return 0; ++ ++ if (min_state < max_state) { ++ if (state > get_curr_state()) ++ return 1; ++ else ++ return -1; ++ } ++ ++ if (min_state > max_state) { ++ if (state > get_curr_state()) ++ return -1; ++ else ++ return 1; ++ } ++ return 0; ++ } ++ + std::string get_cdev_type() { + return type_str; + } +diff --git a/src/thd_engine_default.cpp b/src/thd_engine_default.cpp +index cac300a..40db7ae 100644 +--- a/src/thd_engine_default.cpp ++++ b/src/thd_engine_default.cpp +@@ -361,7 +361,8 @@ int cthd_engine_default::read_thermal_zones() { + if (cdev) { + trip_pt.thd_trip_point_add_cdev(*cdev, + trip_pt_config.cdev_trips[j].influence, +- trip_pt_config.cdev_trips[j].sampling_period); ++ trip_pt_config.cdev_trips[j].sampling_period, ++ trip_pt_config.cdev_trips[j].target_state); + zone->zone_cdev_set_binded(); + activate = true; + } +@@ -385,7 +386,8 @@ int cthd_engine_default::read_thermal_zones() { + if (zone->bind_cooling_device( + trip_pt_config.trip_pt_type, 0, cdev, + trip_pt_config.cdev_trips[j].influence, +- trip_pt_config.cdev_trips[j].sampling_period) == THD_SUCCESS) { ++ trip_pt_config.cdev_trips[j].sampling_period, ++ trip_pt_config.cdev_trips[j].target_state) == THD_SUCCESS) { + thd_log_debug( + "bind %s to trip to sensor %s\n", + cdev->get_cdev_type().c_str(), +diff --git a/src/thd_parse.cpp b/src/thd_parse.cpp +index 5c35f04..7f29d73 100644 +--- a/src/thd_parse.cpp ++++ b/src/thd_parse.cpp +@@ -46,9 +46,9 @@ void cthd_parse::string_trim(std::string &str) { + // Very simple version just checking for 0x20 not other white space chars + bool isspace(int c) { + if (c == ' ') +- return true; ++ return true; + else +- return false; ++ return false; + } + #endif + +@@ -126,6 +126,9 @@ int cthd_parse::parse_new_trip_cdev(xmlNode * a_node, xmlDoc *doc, + } else if (!strcasecmp((const char*) cur_node->name, + "SamplingPeriod")) { + trip_cdev->sampling_period = atoi(tmp_value); ++ } else if (!strcasecmp((const char*) cur_node->name, ++ "TargetState")) { ++ trip_cdev->target_state = atoi(tmp_value); + } + if (tmp_value) + xmlFree(tmp_value); +@@ -157,6 +160,7 @@ int cthd_parse::parse_new_trip_point(xmlNode * a_node, xmlDoc *doc, + "CoolingDevice")) { + trip_cdev.influence = 0; + trip_cdev.sampling_period = 0; ++ trip_cdev.target_state = TRIP_PT_INVALID_TARGET_STATE; + trip_cdev.type.clear(); + parse_new_trip_cdev(cur_node->children, doc, &trip_cdev); + trip_pt->cdev_trips.push_back(trip_cdev); +@@ -635,6 +639,11 @@ void cthd_parse::dump_thermal_conf() { + thermal_info_list[i].zones[j].trip_pts[k].cdev_trips[l].influence); + thd_log_info("\t\t\t SamplingPeriod %d \n", + thermal_info_list[i].zones[j].trip_pts[k].cdev_trips[l].sampling_period); ++ if (thermal_info_list[i].zones[j].trip_pts[k].cdev_trips[l].target_state ++ != TRIP_PT_INVALID_TARGET_STATE) ++ thd_log_info("\t\t\t TargetState %d \n", ++ thermal_info_list[i].zones[j].trip_pts[k].cdev_trips[l].target_state); ++ + } + } + } +diff --git a/src/thd_parse.h b/src/thd_parse.h +index ecb382b..3b19a8e 100644 +--- a/src/thd_parse.h ++++ b/src/thd_parse.h +@@ -71,6 +71,7 @@ typedef struct { + std::string type; + int influence; + int sampling_period; ++ int target_state; + } trip_cdev_t; + + typedef struct { +diff --git a/src/thd_trip_point.cpp b/src/thd_trip_point.cpp +index 944747a..086537f 100644 +--- a/src/thd_trip_point.cpp ++++ b/src/thd_trip_point.cpp +@@ -141,13 +141,21 @@ bool cthd_trip_point::thd_trip_point_check(int id, unsigned int read_temp, + } + thd_log_debug("cdev at index %d:%s\n", cdev->thd_cdev_get_index(), + cdev->get_cdev_type().c_str()); +- if (cdev->in_max_state()) { ++ /* ++ * When the cdev is already in max state, we skip this cdev. ++ * Also when the target state if any for the current trip is greater ++ * or equal than the current state of the cdev, then also skip. ++ */ ++ if (cdev->in_max_state() ++ || (cdevs[i].target_state != TRIP_PT_INVALID_TARGET_STATE ++ && cdev->cmp_current_state(cdevs[i].target_state) ++ <= 0)) { + thd_log_debug("Need to switch to next cdev \n"); + // No scope of control with this cdev + continue; + } + ret = cdev->thd_cdev_set_state(temp, temp, read_temp, 1, zone_id, +- index); ++ index, cdevs[i].target_state); + if (control_type == SEQUENTIAL && ret == THD_SUCCESS) { + // Only one cdev activation + break; +@@ -166,7 +174,8 @@ bool cthd_trip_point::thd_trip_point_check(int id, unsigned int read_temp, + // No scope of control with this cdev + continue; + } +- cdev->thd_cdev_set_state(temp, temp, read_temp, 0, zone_id, index); ++ cdev->thd_cdev_set_state(temp, temp, read_temp, 0, zone_id, index, ++ TRIP_PT_INVALID_TARGET_STATE); + if (control_type == SEQUENTIAL) { + // Only one cdev activation + break; +@@ -178,12 +187,13 @@ bool cthd_trip_point::thd_trip_point_check(int id, unsigned int read_temp, + } + + void cthd_trip_point::thd_trip_point_add_cdev(cthd_cdev &cdev, int influence, +- int sampling_period) { ++ int sampling_period, int target_state) { + trip_pt_cdev_t thd_cdev; + thd_cdev.cdev = &cdev; + thd_cdev.influence = influence; + thd_cdev.sampling_priod = sampling_period; + thd_cdev.last_op_time = 0; ++ thd_cdev.target_state = target_state; + trip_cdev_add(thd_cdev); + } + +diff --git a/src/thd_trip_point.h b/src/thd_trip_point.h +index 86598ee..a5d5de0 100644 +--- a/src/thd_trip_point.h ++++ b/src/thd_trip_point.h +@@ -43,11 +43,13 @@ typedef enum { + SEQUENTIAL // one after other once the previous cdev reaches its max state + } trip_control_type_t; + ++#define TRIP_PT_INVALID_TARGET_STATE 0xffffff + typedef struct { + cthd_cdev *cdev; + int influence; + int sampling_priod; + time_t last_op_time; ++ int target_state; + } trip_pt_cdev_t; + + #define DEFAULT_SENSOR_ID 0xFFFF +@@ -88,7 +90,8 @@ public: + bool *reset); + + void thd_trip_point_add_cdev(cthd_cdev &cdev, int influence, +- int sampling_period = 0); ++ int sampling_period = 0, int target_state = ++ TRIP_PT_INVALID_TARGET_STATE); + + void thd_trip_cdev_state_reset(); + int thd_trip_point_value() { +diff --git a/src/thd_zone.cpp b/src/thd_zone.cpp +index 29068ea..9f327fd 100644 +--- a/src/thd_zone.cpp ++++ b/src/thd_zone.cpp +@@ -52,7 +52,7 @@ void cthd_zone::thermal_zone_temp_change(int id, unsigned int temp, int pref) { + bool reset = false; + + count = trip_points.size(); +- for (i = count - 1; i >= 0; --i) { ++ for (i = 0; i < count; ++i) { + cthd_trip_point &trip_point = trip_points[i]; + if (trip_point.get_trip_type() == MAX) { + thd_model.add_sample(zone_temp); +@@ -159,7 +159,8 @@ int cthd_zone::zone_update() { + unsigned int max_trip_temp = 0; + + std::sort(trip_points.begin(), trip_points.end(), trip_sort); +- thd_log_info("Sorted trip dump :\n"); ++ thd_log_info("Sorted trip dump zone index:%d type:%s:\n", index, ++ type_str.c_str()); + for (unsigned int i = 0; i < trip_points.size(); ++i) { + trip_points[i].trip_dump(); + } +@@ -267,7 +268,7 @@ void cthd_zone::zone_reset() { + + int cthd_zone::bind_cooling_device(trip_point_type_t type, + unsigned int trip_temp, cthd_cdev *cdev, int influence, +- int sampling_period) { ++ int sampling_period, int target_state) { + int i, count; + bool added = false; + +@@ -279,7 +280,7 @@ int cthd_zone::bind_cooling_device(trip_point_type_t type, + && (trip_point.get_trip_temp() > 0) + && (trip_temp == 0 || trip_point.get_trip_temp() == trip_temp)) { + trip_point.thd_trip_point_add_cdev(*cdev, influence, +- sampling_period); ++ sampling_period, target_state); + added = true; + zone_cdev_set_binded(); + break; +diff --git a/src/thd_zone.h b/src/thd_zone.h +index 04b512f..5ae8719 100644 +--- a/src/thd_zone.h ++++ b/src/thd_zone.h +@@ -153,7 +153,8 @@ public: + int read_user_set_psv_temp(); + + int bind_cooling_device(trip_point_type_t type, unsigned int trip_temp, +- cthd_cdev *cdev, int influence, int sampling_period = 0); ++ cthd_cdev *cdev, int influence, int sampling_period = 0, ++ int target_state = TRIP_PT_INVALID_TARGET_STATE); + + int get_sensor_count() { + return sensors.size(); +diff --git a/src/thd_zone_generic.cpp b/src/thd_zone_generic.cpp +index e549c9a..389cad2 100644 +--- a/src/thd_zone_generic.cpp ++++ b/src/thd_zone_generic.cpp +@@ -71,7 +71,8 @@ int cthd_zone_generic::read_trip_points() { + if (cdev) { + trip_pt.thd_trip_point_add_cdev(*cdev, + trip_pt_config.cdev_trips[j].influence, +- trip_pt_config.cdev_trips[j].sampling_period); ++ trip_pt_config.cdev_trips[j].sampling_period, ++ trip_pt_config.cdev_trips[j].target_state); + zone_cdev_set_binded(); + } + } +-- +2.7.0.rc3 + diff -Nru thermald-1.4.3/debian/patches/0200-Error-recovery-when-sysfs-attrib-read-fails.patch thermald-1.4.3/debian/patches/0200-Error-recovery-when-sysfs-attrib-read-fails.patch --- thermald-1.4.3/debian/patches/0200-Error-recovery-when-sysfs-attrib-read-fails.patch 1970-01-01 00:00:00.000000000 +0000 +++ thermald-1.4.3/debian/patches/0200-Error-recovery-when-sysfs-attrib-read-fails.patch 2016-01-26 11:08:41.000000000 +0000 @@ -0,0 +1,27 @@ +From ba4fe1e7bb77d09530544cda860fba559603ec83 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Mon, 25 Jan 2016 13:22:39 -0800 +Subject: [PATCH 200/203] Error recovery when sysfs attrib read fails + +When can't read sysfs file, catch all exceptions. The current +ifstream exceptions are not enough. +--- + src/thd_sys_fs.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/thd_sys_fs.cpp b/src/thd_sys_fs.cpp +index 0b1db66..5da8b00 100644 +--- a/src/thd_sys_fs.cpp ++++ b/src/thd_sys_fs.cpp +@@ -163,7 +163,7 @@ int csys_fs::read(const std::string &path, std::string &buf) { + } + f.close(); + #ifndef ANDROID +- } catch (const std::ifstream::failure& e) { ++ } catch (...) { + thd_log_warn("csys_fs::read exception %s\n", path.c_str()); + + ret = -EIO; +-- +2.7.0.rc3 + diff -Nru thermald-1.4.3/debian/patches/0201-Remove-wild-card-for-loading.patch thermald-1.4.3/debian/patches/0201-Remove-wild-card-for-loading.patch --- thermald-1.4.3/debian/patches/0201-Remove-wild-card-for-loading.patch 1970-01-01 00:00:00.000000000 +0000 +++ thermald-1.4.3/debian/patches/0201-Remove-wild-card-for-loading.patch 2016-01-26 11:08:41.000000000 +0000 @@ -0,0 +1,26 @@ +From 6749427098434ccad81fa8c5f2a3e102fc1644f7 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Mon, 25 Jan 2016 13:25:08 -0800 +Subject: [PATCH 201/203] Remove wild card for loading + +This is an example config, so don't let it load. +--- + data/thermal-conf.xml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/data/thermal-conf.xml b/data/thermal-conf.xml +index c24675e..837bc78 100644 +--- a/data/thermal-conf.xml ++++ b/data/thermal-conf.xml +@@ -8,7 +8,7 @@ use "man thermal-conf.xml" for details + + + Generic X86 Laptop Device +- * ++ EXAMPLE_SYSTEM + QUIET + + +-- +2.7.0.rc3 + diff -Nru thermald-1.4.3/debian/patches/0202-Move-parser-init-to-thd_engine.patch thermald-1.4.3/debian/patches/0202-Move-parser-init-to-thd_engine.patch --- thermald-1.4.3/debian/patches/0202-Move-parser-init-to-thd_engine.patch 1970-01-01 00:00:00.000000000 +0000 +++ thermald-1.4.3/debian/patches/0202-Move-parser-init-to-thd_engine.patch 2016-01-26 11:08:41.000000000 +0000 @@ -0,0 +1,144 @@ +From 18d1574230c6b9b4e8876c0b6739c074a24205e6 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Mon, 25 Jan 2016 14:01:20 -0800 +Subject: [PATCH 202/203] Move parser init to thd_engine + +Move the parser_init and parser_deinit to parent class. +--- + src/thd_engine.cpp | 26 +++++++++++++++++++++++++- + src/thd_engine.h | 4 ++++ + src/thd_engine_default.cpp | 23 ----------------------- + src/thd_engine_default.h | 5 +---- + 4 files changed, 30 insertions(+), 28 deletions(-) + +diff --git a/src/thd_engine.cpp b/src/thd_engine.cpp +index b1e1354..9b9b014 100644 +--- a/src/thd_engine.cpp ++++ b/src/thd_engine.cpp +@@ -52,7 +52,7 @@ cthd_engine::cthd_engine() : + 0), preference(0), status(true), thz_last_uevent_time(0), thz_last_temp_ind_time( + 0), terminate(false), genuine_intel(0), has_invariant_tsc(0), has_aperf( + 0), proc_list_matched(false), poll_interval_sec(0), poll_sensor_mask( +- 0), poll_fd_cnt(0), rt_kernel(false) { ++ 0), poll_fd_cnt(0), rt_kernel(false), parser_init_done(false) { + thd_engine = pthread_t(); + thd_attr = pthread_attr_t(); + +@@ -65,6 +65,9 @@ cthd_engine::cthd_engine() : + cthd_engine::~cthd_engine() { + unsigned int i; + ++ if (parser_init_done) ++ parser.parser_deinit(); ++ + for (i = 0; i < sensors.size(); ++i) { + delete sensors[i]; + } +@@ -1078,3 +1081,24 @@ int cthd_engine::user_add_cdev(std::string cdev_name, std::string cdev_path, + + return THD_SUCCESS; + } ++ ++int cthd_engine::parser_init() { ++ if (parser_init_done) ++ return THD_SUCCESS; ++ if (parser.parser_init(get_config_file()) == THD_SUCCESS) { ++ if (parser.start_parse() == THD_SUCCESS) { ++ parser.dump_thermal_conf(); ++ parser_init_done = true; ++ return THD_SUCCESS; ++ } ++ } ++ ++ return THD_ERROR; ++} ++ ++void cthd_engine::parser_deinit() { ++ if (parser_init_done) { ++ parser.parser_deinit(); ++ parser_init_done = false; ++ } ++} +diff --git a/src/thd_engine.h b/src/thd_engine.h +index 2f23466..be4adcd 100644 +--- a/src/thd_engine.h ++++ b/src/thd_engine.h +@@ -114,6 +114,7 @@ private: + int poll_fd_cnt; + bool rt_kernel; + cthd_kobj_uevent kobj_uevent; ++ bool parser_init_done; + + int proc_message(message_capsul_t *msg); + void process_pref_change(); +@@ -261,6 +262,9 @@ public: + int user_add_cdev(std::string cdev_name, std::string cdev_path, + int min_state, int max_state, int step); + cthd_cdev *user_get_cdev(unsigned int index); ++ ++ int parser_init(); ++ void parser_deinit(); + }; + + #endif /* THD_ENGINE_H_ */ +diff --git a/src/thd_engine_default.cpp b/src/thd_engine_default.cpp +index 8d1efff..b4f39ba 100644 +--- a/src/thd_engine_default.cpp ++++ b/src/thd_engine_default.cpp +@@ -62,29 +62,6 @@ static cooling_dev_t cpu_def_cooling_devices[] = { { true, CDEV_DEF_BIT_UNIT_VAL + 0.0, 0.0 } } }; + + cthd_engine_default::~cthd_engine_default() { +- if (parser_init_done) +- parser.parser_deinit(); +-} +- +-int cthd_engine_default::parser_init() { +- if (parser_init_done) +- return THD_SUCCESS; +- if (parser.parser_init(get_config_file()) == THD_SUCCESS) { +- if (parser.start_parse() == THD_SUCCESS) { +- parser.dump_thermal_conf(); +- parser_init_done = true; +- return THD_SUCCESS; +- } +- } +- +- return THD_ERROR; +-} +- +-void cthd_engine_default::parser_deinit() { +- if (parser_init_done) { +- parser.parser_deinit(); +- parser_init_done = false; +- } + } + + int cthd_engine_default::read_thermal_sensors() { +diff --git a/src/thd_engine_default.h b/src/thd_engine_default.h +index 8f0b58a..641bb4c 100644 +--- a/src/thd_engine_default.h ++++ b/src/thd_engine_default.h +@@ -30,18 +30,15 @@ + + class cthd_engine_default: public cthd_engine { + private: +- int parser_init(); +- void parser_deinit(); + int add_replace_cdev(cooling_dev_t *config); + +- bool parser_init_done; + cthd_cpu_default_binding def_binding; + + public: + static const int power_clamp_reduction_percent = 5; + + cthd_engine_default() : +- cthd_engine(), parser_init_done(false) { ++ cthd_engine() { + } + ~cthd_engine_default(); + int read_thermal_zones(); +-- +2.7.0.rc3 + diff -Nru thermald-1.4.3/debian/patches/0203-Add-white-list-of-the-cpu-ids.patch thermald-1.4.3/debian/patches/0203-Add-white-list-of-the-cpu-ids.patch --- thermald-1.4.3/debian/patches/0203-Add-white-list-of-the-cpu-ids.patch 1970-01-01 00:00:00.000000000 +0000 +++ thermald-1.4.3/debian/patches/0203-Add-white-list-of-the-cpu-ids.patch 2016-01-26 11:08:41.000000000 +0000 @@ -0,0 +1,65 @@ +From f4e316ef4d8d8c9a558ef5bfa74e25303c46a985 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Mon, 25 Jan 2016 14:27:42 -0800 +Subject: [PATCH 203/203] Add white list of the cpu ids + +To avoid surprises add all whiltelist of Intel client CPUs which is upto +date till 2016. +User can overide this by either command line parameter +--ignore-cpuid-check or define a thermal-conf.xml. So this still +can be used on AMD or other unsupported models. +--- + src/thd_engine.cpp | 27 ++++++++++++++++++++++----- + 1 file changed, 22 insertions(+), 5 deletions(-) + +diff --git a/src/thd_engine.cpp b/src/thd_engine.cpp +index 9b9b014..d75d268 100644 +--- a/src/thd_engine.cpp ++++ b/src/thd_engine.cpp +@@ -169,9 +169,19 @@ int cthd_engine::thd_engine_start(bool ignore_cpuid_check) { + if (ignore_cpuid_check) { + thd_log_debug("Ignore CPU ID check for MSRs \n"); + proc_list_matched = true; +- } else ++ } else { + check_cpu_id(); + ++ if (!proc_list_matched) { ++ if ((parser_init() == THD_SUCCESS) && parser.platform_matched()) { ++ thd_log_warn("Unsupported cpu model, using thermal-conf.xml only \n"); ++ } else { ++ thd_log_warn("Unsupported cpu model, use thermal-conf.xml file or run with --ignore-cpuid-check \n"); ++ return THD_FATAL_ERROR; ++ } ++ } ++ } ++ + check_for_rt_kernel(); + + // Pipe is used for communication between two processes +@@ -576,11 +586,18 @@ void cthd_engine::thd_engine_reload_zones() { + } + + // Add any tested platform ids in this table +-static supported_ids_t id_table[] = { { 6, 0x2a }, // Sandybridge +- { 6, 0x2d }, // Sandybridge ++static supported_ids_t id_table[] = { ++ { 6, 0x2a }, // Sandybridge + { 6, 0x3a }, // IvyBridge +- { 6, 0x3c }, { 6, 0x3e }, { 6, 0x3f }, { 6, 0x45 }, // Haswell ULT */ +- { 6, 0x46 }, // Haswell ULT */ ++ { 6, 0x3c }, // Haswell ++ { 6, 0x45 }, // Haswell ULT ++ { 6, 0x46 }, // Haswell ULT ++ { 6, 0x3d }, // Broadwell ++ { 6, 0x37 }, // Valleyview BYT ++ { 6, 0x4c }, // Brasewell ++ { 6, 0x4e }, // skylake ++ { 6, 0x5e }, // skylake ++ { 6, 0x5c }, // Broxton + + { 0, 0 } // Last Invalid entry + }; +-- +2.7.0.rc3 + diff -Nru thermald-1.4.3/debian/patches/series thermald-1.4.3/debian/patches/series --- thermald-1.4.3/debian/patches/series 2015-08-21 18:48:00.000000000 +0000 +++ thermald-1.4.3/debian/patches/series 2016-01-26 11:08:41.000000000 +0000 @@ -9,3 +9,11 @@ 0009-Report-multiple-instances-of-thermald-with-thd_log_f.patch 0010-cdev-RAPL-turn-some-info-messages-to-debug-to-reduce.patch 0011-cdev-turn-some-info-messages-to-debug-to-reduce-sysl.patch +0100-Remove-trailing-from-THD-engine-failure-message.patch +0101-Remove-from-No-coretemp-sysfs-found.patch +0102-Add-new-option-for-config-file.patch +0103-Support-target-state.patch +0200-Error-recovery-when-sysfs-attrib-read-fails.patch +0201-Remove-wild-card-for-loading.patch +0202-Move-parser-init-to-thd_engine.patch +0203-Add-white-list-of-the-cpu-ids.patch