diff -Nru thermald-2.4.9/debian/changelog thermald-2.4.9/debian/changelog --- thermald-2.4.9/debian/changelog 2023-03-08 19:28:23.000000000 +0800 +++ thermald-2.4.9/debian/changelog 2023-03-20 19:48:09.000000000 +0800 @@ -1,3 +1,26 @@ +thermald (2.4.9-1ubuntu0.3) jammy; urgency=medium + + * debian/patches/0013-Add-AlderLake-N.patch + - Add support for Adler Lake N (LP: #2012260) + * debian/patches/0007-Add-INT3400-base-path-for-Raptor-Lake.patch + - Fix RPL: Add INT3400 base path(LP: #1989044) + * debian/patches/0014-Process-ITMT-v2.patch + - Support ITMTv2 for Raptor Lake (LP: #2007579) + * debian/patches/0008-Install-passive-default.patch + - Fix throttled GPU (LP: #1981087) + * debian/patches/0012-Always-match-motion-0.patch + - Fix in-motion function doesn't work (LP: #2018275) + * debian/patches/0003-Parse-ITMT-Table.patch + * debian/patches/0004-Add-capability-for-min-max-per-trip.patch + * debian/patches/0005-Install-ITMT_target.patch + * debian/patches/0006-Use-per-trip-min-max.patch + * debian/patches/0009-Parse-idsp-and-trips.patch + * debian/patches/0010-use-PL1-max-min-from-PPCC-when-policies-match.patch + * debian/patches/0011-Parse-GDDV-before-thd_engine-init.patch + - Fix i9-12900k shutdown when run Prime95 and stress-ng (LP: #2018236) + + -- Koba Ko Mon, 20 Mar 2023 19:48:09 +0800 + thermald (2.4.9-1ubuntu0.2) jammy; urgency=medium * Add support for Raptor Lake S CPUs. (LP: #2009676) diff -Nru thermald-2.4.9/debian/patches/0003-Parse-ITMT-Table.patch thermald-2.4.9/debian/patches/0003-Parse-ITMT-Table.patch --- thermald-2.4.9/debian/patches/0003-Parse-ITMT-Table.patch 1970-01-01 08:00:00.000000000 +0800 +++ thermald-2.4.9/debian/patches/0003-Parse-ITMT-Table.patch 2023-03-20 19:48:09.000000000 +0800 @@ -0,0 +1,141 @@ +From 0dd53a0b2f2e9507e54ced9982c1804323642248 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Mon, 27 Jun 2022 15:15:16 -0700 +Subject: [PATCH] Parse ITMT Table + +Some of the newer device PSVT is replaced with ITMT table. Here +Adaptive Action table will point to ITMT table instead of PSVT. + +Parse ITMT, if present while parsing other adaptive tables. +--- + src/thd_engine_adaptive.cpp | 54 +++++++++++++++++++++++++++++++++++++ + src/thd_engine_adaptive.h | 16 +++++++++++ + 2 files changed, 70 insertions(+) + +Index: thermald-2.4.9/src/thd_engine_adaptive.cpp +=================================================================== +--- thermald-2.4.9.orig/src/thd_engine_adaptive.cpp ++++ thermald-2.4.9/src/thd_engine_adaptive.cpp +@@ -622,6 +622,52 @@ struct psvt* cthd_engine_adaptive::find_ + return NULL; + } + ++int cthd_engine_adaptive::parse_itmt(char *name, char *buf, int len) { ++ int offset = 0; ++ int version = get_uint64(buf, &offset); ++ struct itmt itmt; ++ ++ thd_log_debug(" ITMT version %d %s\n", (int) version, name); ++ ++ if (name == NULL) ++ itmt.name = "Default"; ++ else ++ itmt.name = name; ++ ++ while (offset < len) { ++ struct itmt_entry itmt_entry; ++ ++ itmt_entry.target = get_string(buf, &offset); ++ itmt_entry.trip_point = get_uint64(buf, &offset); ++ itmt_entry.pl1_min = get_string(buf, &offset); ++ itmt_entry.pl1_max = get_string(buf, &offset); ++ itmt_entry.unused = get_string(buf, &offset); ++ offset += 12; ++ ++ itmt.itmt_entries.push_back(itmt_entry); ++ } ++ ++ itmts.push_back(itmt); ++ ++ return 0; ++} ++ ++void cthd_engine_adaptive::dump_itmt() { ++ thd_log_info("..itmt dump begin.. \n"); ++ for (unsigned int i = 0; i < itmts.size(); ++i) { ++ std::vector itmt = itmts[i].itmt_entries; ++ ++ thd_log_info("Name :%s\n", itmts[i].name.c_str()); ++ for (unsigned int j = 0; j < itmt.size(); ++j) { ++ thd_log_info("\t target:%s trip_temp:%d pl1_min:%s pl1.max:%s\n", ++ itmt[j].target.c_str(), ++ DECI_KELVIN_TO_CELSIUS(itmt[j].trip_point), ++ itmt[j].pl1_min.c_str(), itmt[j].pl1_max.c_str()); ++ } ++ } ++ thd_log_info("itmt dump end\n"); ++} ++ + // From Common/esif_sdk_iface_esif.h: + #define ESIF_SERVICE_CONFIG_COMPRESSED 0x40000000/* Payload is Compressed */ + // From Common/esif_sdk.h +@@ -757,6 +803,13 @@ int cthd_engine_adaptive::parse_gddv_key + parse_apat(val, vallength); + } + ++ if (type && strcmp(type, "itmt") == 0) { ++ if (point == NULL) ++ parse_itmt(name, val, vallength); ++ else ++ parse_itmt(point, val, vallength); ++ } ++ + delete[] (key); + delete[] (val); + +@@ -1714,6 +1767,7 @@ int cthd_engine_adaptive::thd_engine_ini + + dump_ppcc(); + dump_psvt(); ++ dump_itmt(); + dump_apat(); + dump_apct(); + +Index: thermald-2.4.9/src/thd_engine_adaptive.h +=================================================================== +--- thermald-2.4.9.orig/src/thd_engine_adaptive.h ++++ thermald-2.4.9/src/thd_engine_adaptive.h +@@ -145,6 +145,19 @@ struct psvt { + std::vector psvs; + }; + ++struct itmt_entry { ++ std::string target; ++ int trip_point; ++ std::string pl1_min; ++ std::string pl1_max; ++ std::string unused; ++}; ++ ++struct itmt { ++ std::string name; ++ std::vector itmt_entries; ++}; ++ + class cthd_engine_adaptive: public cthd_engine_default { + protected: + std::vector ppccs; +@@ -152,6 +165,7 @@ protected: + std::vector custom_conditions; + std::vector targets; + std::vector psvts; ++ std::vector itmts; + std::string int3400_path; + UpClient *upower_client; + GDBusProxy *power_profiles_daemon; +@@ -179,6 +193,7 @@ protected: + int parse_apct(char *apct, int len); + int parse_ppcc(char *name, char *ppcc, int len); + int parse_psvt(char *name, char *psvt, int len); ++ int parse_itmt(char *name, char *itmt, int len); + int handle_compressed_gddv(char *buf, int size); + int parse_gddv_key(char *buf, int size, int *end_offset); + int parse_gddv(char *buf, int size, int *end_offset); +@@ -209,6 +224,7 @@ protected: + void dump_apct(); + void dump_ppcc(); + void dump_psvt(); ++ void dump_itmt(); + struct psvt *find_def_psvt(); + + public: diff -Nru thermald-2.4.9/debian/patches/0004-Add-capability-for-min-max-per-trip.patch thermald-2.4.9/debian/patches/0004-Add-capability-for-min-max-per-trip.patch --- thermald-2.4.9/debian/patches/0004-Add-capability-for-min-max-per-trip.patch 1970-01-01 08:00:00.000000000 +0800 +++ thermald-2.4.9/debian/patches/0004-Add-capability-for-min-max-per-trip.patch 2023-03-20 09:23:04.000000000 +0800 @@ -0,0 +1,108 @@ +From d7360035dfa823820c89f914ae5735557dd7a023 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Mon, 27 Jun 2022 15:22:32 -0700 +Subject: [PATCH 3/5] Add capability for min max per trip + +A trip currenly have +- A threshold temperature +- Sampling period +- Influence +- Target state + +Add also possible minimum and maximum state. This can be used +when target state is missing and minimum and maximum state +depends on cooling device minimum and maximum. With this +capability cooling device minimum and maximum state can be +limited per trip. +--- + src/thd_engine_adaptive.cpp | 2 +- + src/thd_trip_point.cpp | 11 ++++++++++- + src/thd_trip_point.h | 12 +++++++++++- + 3 files changed, 22 insertions(+), 3 deletions(-) + +diff --git a/src/thd_engine_adaptive.cpp b/src/thd_engine_adaptive.cpp +index 2a8eabc..53837e4 100644 +--- a/src/thd_engine_adaptive.cpp ++++ b/src/thd_engine_adaptive.cpp +@@ -1317,7 +1317,7 @@ int cthd_engine_adaptive::install_passive(struct psv *psv) { + psv->sample_period / 10, + target_state ? 1 : 0, + target_state, +- NULL); ++ NULL, 0, 0, 0); + zone->add_trip(trip_pt, 1); + zone->zone_cdev_set_binded(); + zone->set_zone_active(); +diff --git a/src/thd_trip_point.cpp b/src/thd_trip_point.cpp +index 0bb8bea..d1d33a3 100644 +--- a/src/thd_trip_point.cpp ++++ b/src/thd_trip_point.cpp +@@ -328,7 +328,8 @@ 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 target_state_valid, int target_state, +- pid_param_t *pid_param) { ++ pid_param_t *pid_param, int min_max_valid, int min_state, ++ int max_state) { + trip_pt_cdev_t thd_cdev; + thd_cdev.cdev = &cdev; + thd_cdev.influence = influence; +@@ -336,6 +337,14 @@ void cthd_trip_point::thd_trip_point_add_cdev(cthd_cdev &cdev, int influence, + thd_cdev.last_op_time = 0; + thd_cdev.target_state_valid = target_state_valid; + thd_cdev.target_state = target_state; ++ ++ thd_cdev.min_max_valid = min_max_valid; ++ ++ thd_log_info("min:%d max:%d\n", min_state, max_state); ++ if (min_max_valid) { ++ thd_cdev.min_state = min_state; ++ thd_cdev.max_state = max_state; ++ } + if (pid_param && pid_param->valid) { + thd_log_info("pid valid %f:%f:%f\n", pid_param->kp, pid_param->ki, + pid_param->kd); +diff --git a/src/thd_trip_point.h b/src/thd_trip_point.h +index e816251..cb46426 100644 +--- a/src/thd_trip_point.h ++++ b/src/thd_trip_point.h +@@ -62,6 +62,9 @@ typedef struct { + int target_state; + pid_param_t pid_param; + cthd_pid pid; ++ int min_max_valid; ++ int min_state; ++ int max_state; + } trip_pt_cdev_t; + + #define DEFAULT_SENSOR_ID 0xFFFF +@@ -112,7 +115,8 @@ public: + void thd_trip_point_add_cdev(cthd_cdev &cdev, int influence, + int sampling_period = 0, int target_state_valid = 0, + int target_state = +- TRIP_PT_INVALID_TARGET_STATE, pid_param_t *pid_param = NULL); ++ TRIP_PT_INVALID_TARGET_STATE, pid_param_t *pid_param = NULL, ++ int min_max_valid = 0, int min_state = 0, int max_state = 0); + + void delete_cdevs() { + cdevs.clear(); +@@ -254,10 +258,16 @@ public: + else + thd_log_info("\t target_state:not defined\n"); + ++ thd_log_info("min_max %d\n", cdevs[i].min_max_valid); ++ + if (cdevs[i].pid_param.valid) + thd_log_info("\t pid: kp=%g ki=%g kd=%g\n", + cdevs[i].pid_param.kp, cdevs[i].pid_param.ki, + cdevs[i].pid_param.kd); ++ if (cdevs[i].min_max_valid) { ++ thd_log_info("\t min_state:%d\n", cdevs[i].min_state); ++ thd_log_info("\t max_state:%d\n", cdevs[i].max_state); ++ } + } + } + }; +-- +2.34.1 + diff -Nru thermald-2.4.9/debian/patches/0005-Install-ITMT-target.patch thermald-2.4.9/debian/patches/0005-Install-ITMT-target.patch --- thermald-2.4.9/debian/patches/0005-Install-ITMT-target.patch 1970-01-01 08:00:00.000000000 +0800 +++ thermald-2.4.9/debian/patches/0005-Install-ITMT-target.patch 2023-03-20 19:48:09.000000000 +0800 @@ -0,0 +1,200 @@ +From abafe7611425a69cff9efe15d7fc67addd23dd5c Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Mon, 27 Jun 2022 15:37:55 -0700 +Subject: [PATCH 4/5] Install ITMT target + +Similar to PSVT install, implement ITMT install. When APAT calls +for ITMT instead of ITMT install ITMT target. The install portion +is much simpler. There can be only one trip in a ITMT entry so +no need to consolidate. + +An ITMT entry will have a trip, min and max value for RAPL PL1. +So create trip with this information and bind RAPL cooling device +to this. +--- + src/thd_engine_adaptive.cpp | 147 +++++++++++++++++++++++++++++++++++- + src/thd_engine_adaptive.h | 3 + + 2 files changed, 149 insertions(+), 1 deletion(-) + +Index: thermald-2.4.9/src/thd_engine_adaptive.cpp +=================================================================== +--- thermald-2.4.9.orig/src/thd_engine_adaptive.cpp ++++ thermald-2.4.9/src/thd_engine_adaptive.cpp +@@ -1228,6 +1228,16 @@ struct psvt* cthd_engine_adaptive::find_ + return NULL; + } + ++struct itmt* cthd_engine_adaptive::find_itmt(std::string name) { ++ for (int i = 0; i < (int) itmts.size(); i++) { ++ if (!strcasecmp(itmts[i].name.c_str(), name.c_str())) { ++ return &itmts[i]; ++ } ++ } ++ ++ return NULL; ++} ++ + int cthd_engine_adaptive::install_passive(struct psv *psv) { + std::string psv_zone; + +@@ -1426,9 +1436,144 @@ void cthd_engine_adaptive::psvt_consolid + } + } + ++#define DEFAULT_SAMPLE_TIME_SEC 5 ++ ++int cthd_engine_adaptive::install_itmt(struct itmt_entry *itmt_entry) { ++ std::string itmt_zone; ++ ++ size_t pos = itmt_entry->target.find_last_of("."); ++ if (pos == std::string::npos) ++ itmt_zone = itmt_entry->target; ++ else ++ itmt_zone = itmt_entry->target.substr(pos + 1); ++ ++ while (itmt_zone.back() == '_') { ++ itmt_zone.pop_back(); ++ } ++ ++ cthd_zone *zone = search_zone(itmt_zone); ++ if (!zone) { ++ if (!itmt_zone.compare(0, 4, "B0D4")) { ++ itmt_zone = "TCPU"; ++ zone = search_zone(itmt_zone); ++ } ++ ++ if (!zone) { ++ if (!itmt_zone.compare(0, 4, "TCPU")) { ++ itmt_zone = "B0D4"; ++ zone = search_zone(itmt_zone); ++ } ++ if (!zone) { ++ thd_log_warn("Unable to find a zone for %s\n", ++ itmt_zone.c_str()); ++ return THD_ERROR; ++ } ++ } ++ } ++ ++ cthd_cdev *cdev = search_cdev("rapl_controller_mmio"); ++ ++ if (!cdev) { ++ return THD_ERROR; ++ } ++ ++ cthd_sensor *sensor = search_sensor(itmt_zone); ++ if (!sensor) { ++ thd_log_warn("Unable to find a sensor for %s\n", itmt_zone.c_str()); ++ return THD_ERROR; ++ } ++ ++ int temp = (itmt_entry->trip_point - 2732) * 100; ++ int min_state = 0, max_state = 0; ++ ++ if (itmt_entry->pl1_max.length()) { ++ if (!strncasecmp(itmt_entry->pl1_max.c_str(), "MAX", 3)) { ++ max_state = TRIP_PT_INVALID_TARGET_STATE; ++ } else if (!strncasecmp(itmt_entry->pl1_max.c_str(), "MIN", 3)) { ++ max_state = 0; ++ } else { ++ std::istringstream buffer(itmt_entry->pl1_max); ++ buffer >> max_state; ++ max_state *= 1000; ++ } ++ } ++ ++ if (itmt_entry->pl1_min.length()) { ++ if (!strncasecmp(itmt_entry->pl1_min.c_str(), "MAX", 3)) { ++ min_state = TRIP_PT_INVALID_TARGET_STATE; ++ } else if (!strncasecmp(itmt_entry->pl1_min.c_str(), "MIN", 3)) { ++ min_state = 0; ++ } else { ++ std::istringstream buffer(itmt_entry->pl1_min); ++ buffer >> min_state; ++ min_state *= 1000; ++ } ++ } ++ ++ cthd_trip_point trip_pt(zone->get_trip_count(), PASSIVE, temp, 0, ++ zone->get_zone_index(), sensor->get_index(), SEQUENTIAL); ++ ++ trip_pt.thd_trip_point_add_cdev(*cdev, cthd_trip_point::default_influence, ++ DEFAULT_SAMPLE_TIME_SEC, 0, 0, ++ NULL, 1, max_state, min_state); ++ ++ zone->add_trip(trip_pt, 1); ++ zone->zone_cdev_set_binded(); ++ zone->set_zone_active(); ++ ++ return 0; ++} ++ ++int cthd_engine_adaptive::set_itmt_target(struct adaptive_target target) { ++ struct itmt *itmt; ++ ++ thd_log_info("set_int3400 ITMT target %s\n", target.argument.c_str()); ++ ++ itmt = find_itmt(target.argument); ++ if (!itmt) { ++ return THD_ERROR; ++ } ++ ++ for (unsigned int i = 0; i < zones.size(); ++i) { ++ cthd_zone *_zone = zones[i]; ++ ++ // This is only for debug to plot power, so keep ++ if (_zone->get_zone_type() == "rapl_pkg_power") ++ continue; ++ ++ _zone->zone_reset(1); ++ _zone->trip_delete_all(); ++ ++ if (_zone->zone_active_status()) ++ _zone->set_zone_inactive(); ++ } ++ ++ for (int i = 0; i < (int) itmt->itmt_entries.size(); i++) { ++ install_itmt(&itmt->itmt_entries[i]); ++ } ++ ++ thd_log_info("\n\n ZONE DUMP BEGIN\n"); ++ int new_zone_count = 0; ++ for (unsigned int i = 0; i < zones.size(); ++i) { ++ zones[i]->zone_dump(); ++ if (zones[i]->zone_active_status()) ++ ++new_zone_count; ++ } ++ thd_log_info("\n\n ZONE DUMP END\n"); ++ ++ return THD_SUCCESS; ++ ++} ++ + void cthd_engine_adaptive::set_int3400_target(struct adaptive_target target) { +- struct psvt *psvt; ++ ++ if (target.code == "ITMT") { ++ if (set_itmt_target(target) == THD_SUCCESS) ++ return; ++ } + if (target.code == "PSVT") { ++ struct psvt *psvt; ++ + thd_log_info("set_int3400 target %s\n", target.argument.c_str()); + + psvt = find_psvt(target.argument); +Index: thermald-2.4.9/src/thd_engine_adaptive.h +=================================================================== +--- thermald-2.4.9.orig/src/thd_engine_adaptive.h ++++ thermald-2.4.9/src/thd_engine_adaptive.h +@@ -198,7 +198,10 @@ protected: + int parse_gddv_key(char *buf, int size, int *end_offset); + int parse_gddv(char *buf, int size, int *end_offset); + struct psvt* find_psvt(std::string name); ++ struct itmt* find_itmt(std::string name); ++ int set_itmt_target(struct adaptive_target target); + int install_passive(struct psv *psv); ++ int install_itmt(struct itmt_entry *itmt_entry); + void psvt_consolidate(); + void set_trip(std::string device, std::string argument); + void set_int3400_target(struct adaptive_target target); diff -Nru thermald-2.4.9/debian/patches/0006-Use-per-trip-min-max.patch thermald-2.4.9/debian/patches/0006-Use-per-trip-min-max.patch --- thermald-2.4.9/debian/patches/0006-Use-per-trip-min-max.patch 1970-01-01 08:00:00.000000000 +0800 +++ thermald-2.4.9/debian/patches/0006-Use-per-trip-min-max.patch 2023-03-20 09:23:04.000000000 +0800 @@ -0,0 +1,376 @@ +From 1bc1105ddadb24b26b971abd3cfd22a1b245b525 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Mon, 27 Jun 2022 15:51:09 -0700 +Subject: [PATCH 5/5] Use per trip min max + +When throttling action takes place, use the trip specfic min +max if valid. But it will require some conflicts when two +trips in different zones calls for different min and max while +they are active. Use the most constrained one in this case. + +Refer to code comments for changes. +--- + src/thd_cdev.cpp | 155 ++++++++++++++++++++++++++++++++--------- + src/thd_cdev.h | 17 +++-- + src/thd_trip_point.cpp | 14 ++-- + 3 files changed, 140 insertions(+), 46 deletions(-) + +diff --git a/src/thd_cdev.cpp b/src/thd_cdev.cpp +index 5c0bbd2..824fb9e 100644 +--- a/src/thd_cdev.cpp ++++ b/src/thd_cdev.cpp +@@ -39,50 +39,78 @@ + #include "thd_cdev.h" + #include "thd_engine.h" + +-int cthd_cdev::thd_clamp_state_min(int _state) ++// Clamp to cdev min state or trip specific min if valid ++int cthd_cdev::thd_clamp_state_min(int _state, int temp_min_state) + { +- if ((min_state < max_state && _state < min_state) +- || (min_state > max_state && _state > min_state)) +- return min_state; ++ int _min_state = min_state; ++ ++ if (_min_state > max_state) { ++ if (temp_min_state && temp_min_state < _min_state) ++ _min_state = temp_min_state; ++ } else { ++ if (temp_min_state && temp_min_state > _min_state) ++ _min_state = temp_min_state; ++ } ++ ++ thd_log_debug("def_min_state:%d curr_min_state:%d\n", min_state, ++ _min_state); ++ ++ if ((_min_state < max_state && _state < _min_state) ++ || (_min_state > max_state && _state > _min_state)) ++ return _min_state; + else + return _state; + } + +-int cthd_cdev::thd_clamp_state_max(int _state) ++// Clamp to cdev max state or trip specific max if valid ++int cthd_cdev::thd_clamp_state_max(int _state, int temp_max_state) + { +- if ((min_state < max_state && _state > max_state) +- || (min_state > max_state && _state < max_state)) +- return max_state; ++ int _max_state = max_state; ++ ++ if (min_state > _max_state) { ++ if (temp_max_state && temp_max_state > _max_state) ++ _max_state = temp_max_state; ++ } else { ++ if (temp_max_state && temp_max_state < _max_state) ++ _max_state = temp_max_state; ++ } ++ ++ thd_log_debug("def_max_state:%d temp_max_state:%d curr_max_state:%d\n", ++ max_state, temp_max_state, _max_state); ++ ++ if ((min_state < _max_state && _state > _max_state) ++ || (min_state > _max_state && _state < _max_state)) ++ return _max_state; + else + return _state; + } + + int cthd_cdev::thd_cdev_exponential_controller(int set_point, int target_temp, +- int temperature, int state, int zone_id) { ++ int temperature, int state, int zone_id, int temp_min_state, int temp_max_state) { + + int control = state; +- int curr_state, max_state, _state; ++ int _curr_state, _max_state, _state; + +- max_state = get_max_state(); ++ _max_state = get_max_state(); + + if (state) { + // Get the latest state, which for some devices read the state from the hardware +- curr_state = get_curr_state(true); ++ _curr_state = get_curr_state(true); + // Clamp the current state to min_state, as we start from min to max for + // activation of a cooling device +- curr_state = thd_clamp_state_min(curr_state); ++ _curr_state = thd_clamp_state_min(_curr_state, temp_min_state); + thd_log_debug("thd_cdev_set_%d:curr state %d max state %d\n", index, +- curr_state, max_state); ++ _curr_state, _max_state); + + if (inc_val) +- _state = curr_state + inc_val; ++ _state = _curr_state + inc_val; + else +- _state = curr_state + inc_dec_val; ++ _state = _curr_state + inc_dec_val; + + if (trend_increase) { + // This means this is a repeat call for activation + if (curr_pow == 0) +- base_pow_state = curr_state; ++ base_pow_state = _curr_state; + ++curr_pow; + + if (inc_val) +@@ -90,25 +118,32 @@ int cthd_cdev::thd_cdev_exponential_controller(int set_point, int target_temp, + else + _state = base_pow_state + int_2_pow(curr_pow) * inc_dec_val; + ++ // Check for the overflow exhaust the valid range ++ if (((inc_val < 0) && (base_pow_state < _state)) ++ || ((inc_val > 0) && (base_pow_state > _state))) ++ _state = max_state; ++ + thd_log_info( +- "cdev index:%d consecutive call, increment exponentially state %d (min %d max %d)\n", +- index, _state, min_state, max_state); ++ "cdev index:%d consecutive call, increment exponentially state %d (min %d max %d) (%d:%d)\n", ++ index, _state, min_state, _max_state, base_pow_state, curr_pow); + +- // Make sure that the state is not beyond max_state +- _state = thd_clamp_state_max(_state); + } else { + curr_pow = 0; + } ++ ++ // Make sure that the state is not beyond max_state ++ _state = thd_clamp_state_max(_state, temp_max_state); ++ + trend_increase = true; + thd_log_debug("op->device:%s %d\n", type_str.c_str(), _state); + set_curr_state(_state, control); + } else { + // Get the latest state, which is not the latest from the hardware but last set state to the device +- curr_state = get_curr_state(); +- curr_state = thd_clamp_state_max(curr_state); ++ _curr_state = get_curr_state(); ++ _curr_state = thd_clamp_state_max(curr_state); + + thd_log_debug("thd_cdev_set_%d:curr state %d max state %d\n", index, +- curr_state, max_state); ++ curr_state, _max_state); + + curr_pow = 0; + trend_increase = false; +@@ -116,9 +151,9 @@ int cthd_cdev::thd_cdev_exponential_controller(int set_point, int target_temp, + if (auto_down_adjust == false) { + + if (dec_val) +- _state = curr_state - dec_val; ++ _state = _curr_state - dec_val; + else +- _state = curr_state - inc_dec_val; ++ _state = _curr_state - inc_dec_val; + + // Make sure that it is not beyond min_state + _state = thd_clamp_state_min(_state); +@@ -151,6 +186,16 @@ static bool sort_clamp_values_dec(zone_trip_limits_t limit_1, + return (limit_1.target_value > limit_2.target_value); + } + ++static bool sort_min_max_values_asc(zone_trip_limits_t limit_1, ++ zone_trip_limits_t limit_2) { ++ return (limit_1._min_state < limit_2._min_state); ++} ++ ++static bool sort_min_max_values_dec(zone_trip_limits_t limit_1, ++ zone_trip_limits_t limit_2) { ++ return (limit_1._max_state > limit_2._max_state); ++} ++ + /* + * How the state is set? + * If the state set is called before debounce interval, then simply return +@@ -183,8 +228,9 @@ static bool sort_clamp_values_dec(zone_trip_limits_t limit_1, + + int cthd_cdev::thd_cdev_set_state(int set_point, int target_temp, + int temperature, int hard_target, int state, int zone_id, int trip_id, +- int target_state_valid, int target_value, +- pid_param_t *pid_param, cthd_pid& pid, bool force) { ++ int target_state_valid, int target_value, pid_param_t *pid_param, ++ cthd_pid &pid, bool force, int min_max_valid, int _min_state, ++ int _max_state) { + + time_t tm; + int ret; +@@ -199,9 +245,9 @@ int cthd_cdev::thd_cdev_set_state(int set_point, int target_temp, + time(&tm); + + thd_log_debug( +- ">>thd_cdev_set_state temperature %d:%d index:%d state:%d :zone:%d trip_id:%d target_state_valid:%d target_value :%d force:%d\n", ++ ">>thd_cdev_set_state temperature %d:%d index:%d state:%d :zone:%d trip_id:%d target_state_valid:%d target_value :%d force:%d min_state:%d max_state:%d\n", + target_temp, temperature, index, state, zone_id, trip_id, +- target_state_valid, target_value, force); ++ target_state_valid, target_value, force, _min_state, _max_state); + + if (state) { + bool found = false; +@@ -226,9 +272,29 @@ int cthd_cdev::thd_cdev_set_state(int set_point, int target_temp, + limit.trip = trip_id; + limit.target_state_valid = target_state_valid; + limit.target_value = target_value; +- thd_log_info("Added zone %d trip %d clamp_valid %d clamp %d\n", ++ ++ // Cap the trip min max limits to actual cooling device trips ++ // Here min_state and max_state are for cooling device and ++ // _min_state and _max_state are defined for per trip ++ // in thermal table ++ if (min_max_valid) { ++ if (_min_state == TRIP_PT_INVALID_TARGET_STATE || !_min_state) ++ _min_state = min_state; ++ ++ if (_max_state == TRIP_PT_INVALID_TARGET_STATE || !_max_state) ++ _max_state = max_state; ++ } else { ++ _max_state = 0; ++ _min_state = 0; ++ } ++ ++ limit._max_state = _max_state; ++ limit._min_state = _min_state; ++ limit._min_max_valid = min_max_valid; ++ ++ thd_log_info("Added zone %d trip %d clamp_valid %d clamp %d _min:%d _max:%d\n", + limit.zone, limit.trip, limit.target_state_valid, +- limit.target_value); ++ limit.target_value, limit._min_state, limit._max_state); + zone_trip_limits.push_back(limit); + + if (target_state_valid) { +@@ -240,6 +306,21 @@ int cthd_cdev::thd_cdev_set_state(int set_point, int target_temp, + sort_clamp_values_dec); + } + } ++ ++ // Target state and min_max_valid or mutually exclusive ++ // in thermal tables. So no need to consolidate min/max with ++ // target ++ // The table will be ordered so that most restrictive is the ++ // first entry ++ if (min_max_valid) { ++ if (min_state < max_state) { ++ std::sort(zone_trip_limits.begin(), zone_trip_limits.end(), ++ sort_min_max_values_dec); ++ } else { ++ std::sort(zone_trip_limits.begin(), zone_trip_limits.end(), ++ sort_min_max_values_asc); ++ } ++ } + } + + zone_trip_limits_t limit; +@@ -247,6 +328,12 @@ int cthd_cdev::thd_cdev_set_state(int set_point, int target_temp, + limit = zone_trip_limits[zone_trip_limits.size() - 1]; + target_value = limit.target_value; + target_state_valid = limit.target_state_valid; ++ ++ target_value = limit.target_value; ++ min_max_valid = limit._min_max_valid; ++ _max_state = limit._max_state; ++ _min_state = limit._min_state; ++ + if (!first_entry && target_state_valid + && cmp_current_state( + map_target_state(target_state_valid, target_value)) +@@ -394,7 +481,7 @@ int cthd_cdev::thd_cdev_set_state(int set_point, int target_temp, + ret = THD_SUCCESS; + } else { + ret = thd_cdev_exponential_controller(set_point, target_temp, +- temperature, state, zone_id); ++ temperature, state, zone_id, _min_state, _max_state); + } + if (curr_state == get_max_state()) { + control_end(); +@@ -407,7 +494,7 @@ int cthd_cdev::thd_cdev_set_min_state(int zone_id, int trip_id) { + trend_increase = false; + cthd_pid unused; + thd_cdev_set_state(0, 0, 0, 0, 0, zone_id, trip_id, 1, min_state, NULL, +- unused, true); ++ unused, true, 0, 0, 0); + + return THD_SUCCESS; + } +diff --git a/src/thd_cdev.h b/src/thd_cdev.h +index f544d1a..ca3e542 100644 +--- a/src/thd_cdev.h ++++ b/src/thd_cdev.h +@@ -38,6 +38,9 @@ typedef struct { + int trip; + int target_state_valid; + int target_value; ++ int _min_state; ++ int _max_state; ++ int _min_max_valid; + } zone_trip_limits_t; + + #define ZONE_TRIP_LIMIT_COUNT 12 +@@ -79,9 +82,10 @@ private: + return _pow; + } + int thd_cdev_exponential_controller(int set_point, int target_temp, +- int temperature, int state, int arg); +- int thd_clamp_state_min(int _state); +- int thd_clamp_state_max(int _state); ++ int temperature, int state, int arg, int temp_min_state = 0, ++ int temp_max_state = 0); ++ int thd_clamp_state_min(int _state, int temp_min_state = 0); ++ int thd_clamp_state_max(int _state, int temp_max_state = 0); + public: + static const int default_debounce_interval = 2; // In seconds + cthd_cdev(unsigned int _index, std::string control_path) : +@@ -96,9 +100,10 @@ public: + virtual ~cthd_cdev() { + } + virtual int thd_cdev_set_state(int set_point, int target_temp, +- int temperature, int hard_target, int state, +- int zone_id, int trip_id, int target_state_valid, int target_value, +- pid_param_t *pid_param, cthd_pid& pid, bool force); ++ int temperature, int hard_target, int state, int zone_id, ++ int trip_id, int target_state_valid, int target_value, ++ pid_param_t *pid_param, cthd_pid &pid, bool force, ++ int min_max_valid, int _min_state, int _max_state); + + virtual int thd_cdev_set_min_state(int zone_id, int trip_id); + +diff --git a/src/thd_trip_point.cpp b/src/thd_trip_point.cpp +index d1d33a3..1dcb2cb 100644 +--- a/src/thd_trip_point.cpp ++++ b/src/thd_trip_point.cpp +@@ -281,11 +281,12 @@ bool cthd_trip_point::thd_trip_point_check(int id, unsigned int read_temp, + if (cdevs[i].target_state == TRIP_PT_INVALID_TARGET_STATE) + cdevs[i].target_state = cdev->get_min_state(); + +- ret = cdev->thd_cdev_set_state(temp, temp, read_temp, (type == MAX), 1, zone_id, +- index, cdevs[i].target_state_valid, ++ ret = cdev->thd_cdev_set_state(temp, temp, read_temp, (type == MAX), ++ 1, zone_id, index, cdevs[i].target_state_valid, + cdev->map_target_state(cdevs[i].target_state_valid, + cdevs[i].target_state), &cdevs[i].pid_param, +- cdevs[i].pid, false); ++ cdevs[i].pid, false, cdevs[i].min_max_valid, ++ cdevs[i].min_state, cdevs[i].max_state); + if (control_type == SEQUENTIAL && ret == THD_SUCCESS) { + // Only one cdev activation + break; +@@ -310,11 +311,12 @@ bool cthd_trip_point::thd_trip_point_check(int id, unsigned int read_temp, + if (cdevs[i].target_state == TRIP_PT_INVALID_TARGET_STATE) + cdevs[i].target_state = cdev->get_min_state(); + +- cdev->thd_cdev_set_state(temp, temp, read_temp, (type == MAX), 0, zone_id, index, +- cdevs[i].target_state_valid, ++ cdev->thd_cdev_set_state(temp, temp, read_temp, (type == MAX), 0, ++ zone_id, index, cdevs[i].target_state_valid, + cdev->map_target_state(cdevs[i].target_state_valid, + cdevs[i].target_state), &cdevs[i].pid_param, +- cdevs[i].pid, false); ++ cdevs[i].pid, false, cdevs[i].min_max_valid, ++ cdevs[i].min_state, cdevs[i].max_state); + + if (control_type == SEQUENTIAL) { + // Only one cdev activation +-- +2.34.1 + diff -Nru thermald-2.4.9/debian/patches/0007-Add-INT3400-base-path-for-Raptor-Lake.patch thermald-2.4.9/debian/patches/0007-Add-INT3400-base-path-for-Raptor-Lake.patch --- thermald-2.4.9/debian/patches/0007-Add-INT3400-base-path-for-Raptor-Lake.patch 1970-01-01 08:00:00.000000000 +0800 +++ thermald-2.4.9/debian/patches/0007-Add-INT3400-base-path-for-Raptor-Lake.patch 2023-03-20 09:23:04.000000000 +0800 @@ -0,0 +1,41 @@ +From 57c1fe95fef707051d7dd340544f290eae2184c1 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Wed, 29 Jun 2022 17:22:18 -0700 +Subject: [PATCH 06/18] Add INT3400 base path for Raptor Lake + +Update the sysfs path for INT3400 sysfs to be able to run adaptive +mode. +--- + src/thd_engine_adaptive.cpp | 2 ++ + src/thd_int3400.cpp | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/src/thd_engine_adaptive.cpp b/src/thd_engine_adaptive.cpp +index 3ecf61c..71fb550 100644 +--- a/src/thd_engine_adaptive.cpp ++++ b/src/thd_engine_adaptive.cpp +@@ -1866,6 +1866,8 @@ int cthd_engine_adaptive::thd_engine_init(bool ignore_cpuid_check, bool adaptive + int3400_base_path = "/sys/bus/platform/devices/INTC1040:00/"; + } else if (sysfs.exists("/sys/bus/platform/devices/INTC1041:00")) { + int3400_base_path = "/sys/bus/platform/devices/INTC1041:00/"; ++ } else if (sysfs.exists("/sys/bus/platform/devices/INTC10A0:00")) { ++ int3400_base_path = "/sys/bus/platform/devices/INTC10A0:00/"; + } else { + return THD_ERROR; + } +diff --git a/src/thd_int3400.cpp b/src/thd_int3400.cpp +index 3572997..da86760 100644 +--- a/src/thd_int3400.cpp ++++ b/src/thd_int3400.cpp +@@ -38,6 +38,8 @@ cthd_INT3400::cthd_INT3400(std::string _uuid) : uuid(_uuid), base_path("") { + base_path = "/sys/bus/acpi/devices/INTC1040:00/physical_node/uuids/"; + } else if (cdev_sysfs.exists("/sys/bus/acpi/devices/INTC1041:00/physical_node/uuids")) { + base_path = "/sys/bus/acpi/devices/INTC1041:00/physical_node/uuids/"; ++ } else if (cdev_sysfs.exists("/sys/bus/acpi/devices/INTC10A0:00/physical_node/uuids")) { ++ base_path = "/sys/bus/acpi/devices/INTC10A0:00/physical_node/uuids/"; + } + thd_log_info("INT3400 Base path is %s\n", base_path.c_str()); + } +-- +2.34.1 + diff -Nru thermald-2.4.9/debian/patches/0008-Install-passive-default.patch thermald-2.4.9/debian/patches/0008-Install-passive-default.patch --- thermald-2.4.9/debian/patches/0008-Install-passive-default.patch 1970-01-01 08:00:00.000000000 +0800 +++ thermald-2.4.9/debian/patches/0008-Install-passive-default.patch 2023-03-20 19:48:09.000000000 +0800 @@ -0,0 +1,122 @@ +From 82609c7e017a0461eb20d66935979e399f024e0e Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Thu, 30 Jun 2022 16:31:23 -0700 +Subject: [PATCH] Separate Adaptive engine and GDDV + +To better organize code, separate into two classes. One just +implement GDDV parsing and other actually doing adaptive processing. + +No functional changes are expected. + +(koba: Ignore the refactoring codes and leave the install_passive_policy().) +(backported from intel/thermald_daemon) + +Index: thermald-2.4.9/src/thd_engine_adaptive.h +=================================================================== +--- thermald-2.4.9.orig/src/thd_engine_adaptive.h ++++ thermald-2.4.9/src/thd_engine_adaptive.h +@@ -166,7 +166,6 @@ protected: + std::vector targets; + std::vector psvts; + std::vector itmts; +- std::string int3400_path; + UpClient *upower_client; + GDBusProxy *power_profiles_daemon; + struct libevdev *tablet_dev; +@@ -174,6 +173,7 @@ protected: + int current_condition_set; + int policy_active; + int fallback_id; ++ std::string int3400_path; + std::string int3400_base_path; + int passive_def_only; + int passive_def_processed; +@@ -229,12 +229,13 @@ protected: + void dump_psvt(); + void dump_itmt(); + struct psvt *find_def_psvt(); ++ void install_passive_default(); + + public: + cthd_engine_adaptive() : + cthd_engine_default("63BE270F-1C11-48FD-A6F7-3AF253FF3E2D"), upower_client( + NULL), tablet_dev(NULL), current_condition_set(0xffff), policy_active( +- 0), fallback_id(-1), int3400_base_path(""), passive_def_only( ++ 0), fallback_id(-1), int3400_path(""), int3400_base_path(""), passive_def_only( + 0), passive_def_processed(0), passive_installed(0), power_slider(75) { + } + +Index: thermald-2.4.9/src/thd_engine_adaptive.cpp +=================================================================== +--- thermald-2.4.9.orig/src/thd_engine_adaptive.cpp ++++ thermald-2.4.9/src/thd_engine_adaptive.cpp +@@ -1624,6 +1624,41 @@ void cthd_engine_adaptive::set_int3400_t + } + } + ++void cthd_engine_adaptive::install_passive_default() { ++ if (passive_installed) ++ return; ++ ++ thd_log_info("IETM_D0 processed\n"); ++ ++ for (unsigned int i = 0; i < zones.size(); ++i) { ++ cthd_zone *_zone = zones[i]; ++ _zone->zone_reset(1); ++ _zone->trip_delete_all(); ++ ++ if (_zone->zone_active_status()) ++ _zone->set_zone_inactive(); ++ } ++ ++ struct psvt *psvt = find_def_psvt(); ++ if (!psvt) ++ return; ++ ++ std::vector psvs = psvt->psvs; ++ ++ thd_log_info("Name :%s\n", psvt->name.c_str()); ++ for (unsigned int j = 0; j < psvs.size(); ++j) { ++ install_passive(&psvs[j]); ++ } ++ ++ psvt_consolidate(); ++ thd_log_info("\n\n ZONE DUMP BEGIN\n"); ++ for (unsigned int i = 0; i < zones.size(); ++i) { ++ zones[i]->zone_dump(); ++ } ++ thd_log_info("\n\n ZONE DUMP END\n"); ++ passive_installed = 1; ++} ++ + void cthd_engine_adaptive::execute_target(struct adaptive_target target) { + cthd_cdev *cdev; + std::string name; +@@ -1943,8 +1978,10 @@ int cthd_engine_adaptive::thd_engine_ini + int cthd_engine_adaptive::thd_engine_start() { + g_autoptr(GDBusConnection) bus = NULL; + +- if (passive_def_only) ++ if (passive_def_only) { ++ install_passive_default(); + return cthd_engine::thd_engine_start(); ++ } + + setup_input_devices(); + +@@ -1968,7 +2005,14 @@ int cthd_engine_adaptive::thd_engine_sta + thd_log_info("fallback id:%d\n", i); + fallback_id = i; + } else { +- return THD_ERROR; ++ struct psvt *psvt = find_def_psvt(); ++ ++ if (psvt) { ++ thd_log_info("IETM.D0 found\n"); ++ install_passive_default(); ++ } else { ++ return THD_ERROR; ++ } + } + } + } diff -Nru thermald-2.4.9/debian/patches/0009-Parse-idsp-and-trips.patch thermald-2.4.9/debian/patches/0009-Parse-idsp-and-trips.patch --- thermald-2.4.9/debian/patches/0009-Parse-idsp-and-trips.patch 1970-01-01 08:00:00.000000000 +0800 +++ thermald-2.4.9/debian/patches/0009-Parse-idsp-and-trips.patch 2023-03-20 19:48:09.000000000 +0800 @@ -0,0 +1,222 @@ +From cbdd92b49574ceb2d05e500e042cc792cc21b313 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Fri, 1 Jul 2022 14:04:23 -0700 +Subject: [PATCH] Parse idsp and trips + +Read idsp and trip from data vault as the existing sysfs read values +may not be present or wrong. + +(backported cbdd92b49574 from intel/thermal_daemon) + +Index: thermald-2.4.9/src/thd_engine_adaptive.cpp +=================================================================== +--- thermald-2.4.9.orig/src/thd_engine_adaptive.cpp ++++ thermald-2.4.9/src/thd_engine_adaptive.cpp +@@ -668,6 +668,114 @@ void cthd_engine_adaptive::dump_itmt() { + thd_log_info("itmt dump end\n"); + } + ++void cthd_engine_adaptive::parse_idsp(char *name, char *start, int length) { ++ int len, i = 0; ++ unsigned char *str = (unsigned char*) start; ++ ++ while (i < length) { ++ char idsp[64]; ++ std::string idsp_str; ++ ++ // The minimum length for a IDSP should be atleast 28 ++ // including headers and values ++ if ((length - i) < 28) ++ return; ++ ++ if (*str != 7) ++ break; ++ ++ str += 4; // Get to Length field ++ i += 4; ++ ++ len = *(int*) str; ++ str += 8; // Get to actual contents ++ i += 8; ++ ++ snprintf(idsp, sizeof(idsp), ++ "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", ++ str[3], str[2], str[1], str[0], str[5], str[4], str[7], str[6], ++ str[8], str[9], str[10], str[11], str[12], str[13], str[14], ++ str[15]); ++ ++ idsp_str = idsp; ++ std::transform(idsp_str.begin(), idsp_str.end(), idsp_str.begin(), ++ ::toupper); ++ idsps.push_back(idsp_str); ++ ++ str += len; ++ i += len; ++ } ++} ++ ++void cthd_engine_adaptive::dump_idsps() { ++ thd_log_info("..idsp dump begin.. \n"); ++ for (unsigned int i = 0; i < idsps.size(); ++i) { ++ thd_log_info("idsp :%s\n", idsps[i].c_str()); ++ } ++ thd_log_info("idsp dump end\n"); ++} ++ ++int cthd_engine_adaptive::search_idsp(std::string name) ++{ ++ for (unsigned int i = 0; i < idsps.size(); ++i) { ++ if (!idsps[i].compare(0, 36, name)) ++ return THD_SUCCESS; ++ } ++ ++ return THD_ERROR; ++} ++ ++void cthd_engine_adaptive::parse_trip_point(char *name, char *type, char *val, int len) ++{ ++ struct trippoint trip; ++ ++ trip.name = name; ++ trip.type_str = type; ++ if (!trip.type_str.compare(0, 2, "_c")) ++ trip.type = CRITICAL; ++ else if (!trip.type_str.compare(0, 2, "_p")) ++ trip.type = PASSIVE; ++ else if (!trip.type_str.compare(0, 2, "_h")) ++ trip.type = HOT; ++ else if (!trip.type_str.compare(0, 2, "_a")) ++ trip.type = ACTIVE; ++ else ++ trip.type = INVALID_TRIP_TYPE; ++ trip.temp = DECI_KELVIN_TO_CELSIUS(*(int *)val); ++ trippoints.push_back(trip); ++} ++ ++void cthd_engine_adaptive::dump_trips() { ++ thd_log_info("..trippoint dump begin.. \n"); ++ for (unsigned int i = 0; i < trippoints.size(); ++i) { ++ thd_log_info("name:%s type_str:%s type:%d temp:%d\n", ++ trippoints[i].name.c_str(), trippoints[i].type_str.c_str(), ++ trippoints[i].type, trippoints[i].temp); ++ } ++ thd_log_info("trippoint dump end\n"); ++} ++ ++int cthd_engine_adaptive::get_trip_temp(std::string name, trip_point_type_t type) { ++ std::string search_name = name + ".D0"; ++ for (unsigned int i = 0; i < trippoints.size(); ++i) { ++ if (!trippoints[i].name.compare(search_name) ++ && trippoints[i].type == type) ++ return trippoints[i].temp; ++ } ++ ++ return THD_ERROR; ++} ++ ++int cthd_engine_adaptive::parse_trt(char *trt, int len) ++{ ++ int offset = 0; ++ ++ while (offset < len) { ++ } ++ ++ return THD_SUCCESS; ++} ++ + // From Common/esif_sdk_iface_esif.h: + #define ESIF_SERVICE_CONFIG_COMPRESSED 0x40000000/* Payload is Compressed */ + // From Common/esif_sdk.h +@@ -810,6 +918,18 @@ int cthd_engine_adaptive::parse_gddv_key + parse_itmt(point, val, vallength); + } + ++ if (name && type && strcmp(type, "idsp") == 0) { ++ parse_idsp(name, val, vallength); ++ } ++ ++ if (name && type && point && strcmp(type, "trippoint") == 0) { ++ parse_trip_point(name, point, val, vallength); ++ } ++ ++ if (type && strcmp(type, "trt") == 0) { ++ parse_trt(val, vallength); ++ } ++ + delete[] (key); + delete[] (val); + +@@ -1952,6 +2072,8 @@ int cthd_engine_adaptive::thd_engine_ini + dump_itmt(); + dump_apat(); + dump_apct(); ++ dump_idsps(); ++ dump_trips(); + + delete [] buf; + } catch (std::exception &e) { +Index: thermald-2.4.9/src/thd_engine_adaptive.h +=================================================================== +--- thermald-2.4.9.orig/src/thd_engine_adaptive.h ++++ thermald-2.4.9/src/thd_engine_adaptive.h +@@ -32,6 +32,7 @@ + #include "thd_engine_default.h" + #include "thd_cpu_default_binding.h" + #include "thd_adaptive_types.h" ++#include "thd_trt_art_reader.h" + + enum adaptive_condition { + Default = 0x01, +@@ -158,14 +159,24 @@ struct itmt { + std::vector itmt_entries; + }; + ++struct trippoint { ++ std::string name; ++ std::string type_str; ++ trip_point_type_t type; ++ int temp; ++}; ++ + class cthd_engine_adaptive: public cthd_engine_default { + protected: + std::vector ppccs; + std::vector> conditions; + std::vector custom_conditions; + std::vector targets; ++ std::vector rel_list; + std::vector psvts; + std::vector itmts; ++ std::vector idsps; ++ std::vector trippoints; + UpClient *upower_client; + GDBusProxy *power_profiles_daemon; + struct libevdev *tablet_dev; +@@ -194,11 +205,15 @@ protected: + int parse_ppcc(char *name, char *ppcc, int len); + int parse_psvt(char *name, char *psvt, int len); + int parse_itmt(char *name, char *itmt, int len); ++ int parse_trt(char *trt, int len); ++ void parse_idsp(char *name, char *idsp, int len); ++ void parse_trip_point(char *name, char *type, char *val, int len); + int handle_compressed_gddv(char *buf, int size); + int parse_gddv_key(char *buf, int size, int *end_offset); + int parse_gddv(char *buf, int size, int *end_offset); + struct psvt* find_psvt(std::string name); + struct itmt* find_itmt(std::string name); ++ int search_idsp(std::string name); + int set_itmt_target(struct adaptive_target target); + int install_passive(struct psv *psv); + int install_itmt(struct itmt_entry *itmt_entry); +@@ -228,8 +243,11 @@ protected: + void dump_ppcc(); + void dump_psvt(); + void dump_itmt(); ++ void dump_idsps(); ++ void dump_trips(); + struct psvt *find_def_psvt(); + void install_passive_default(); ++ int get_trip_temp(std::string name, trip_point_type_t type); + + public: + cthd_engine_adaptive() : diff -Nru thermald-2.4.9/debian/patches/0010-Use-PL1-max-min-from-PPCC-when-policies-match.patch thermald-2.4.9/debian/patches/0010-Use-PL1-max-min-from-PPCC-when-policies-match.patch --- thermald-2.4.9/debian/patches/0010-Use-PL1-max-min-from-PPCC-when-policies-match.patch 1970-01-01 08:00:00.000000000 +0800 +++ thermald-2.4.9/debian/patches/0010-Use-PL1-max-min-from-PPCC-when-policies-match.patch 2023-03-20 19:48:09.000000000 +0800 @@ -0,0 +1,52 @@ +From d385f20764e1e5477450405be71ec719adc973be Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Tue, 5 Jul 2022 16:41:46 -0700 +Subject: [PATCH 11/18] Use PL1 max/min from PPCC when policies match + +When Adaptive or Passive 2 policy are present in the idsp, use +RAPL PL1 max/min from PPCC table in data vault without checking +if that is lower than what system is booted with. +--- + src/thd_cdev_rapl.cpp | 12 ++++++++++++ + src/thd_engine.h | 3 +++ + src/thd_engine_adaptive.h | 6 ++++++ + src/thd_gddv.cpp | 3 +++ + 4 files changed, 24 insertions(+) + +Index: thermald-2.4.9/src/thd_cdev_rapl.cpp +=================================================================== +--- thermald-2.4.9.orig/src/thd_cdev_rapl.cpp ++++ thermald-2.4.9/src/thd_cdev_rapl.cpp +@@ -504,6 +504,18 @@ bool cthd_sysfs_cdev_rapl::read_ppcc_pow + + thd_log_info("ppcc limits max:%u min:%u min_win:%u step:%u\n", + pl0_max_pwr, pl0_min_pwr, pl0_min_window, pl0_step_pwr); ++ ++ int policy_matched; ++ ++ policy_matched = thd_engine->search_idsp("63BE270F-1C11-48FD-A6F7-3AF253FF3E2D"); ++ if (policy_matched != THD_SUCCESS) ++ policy_matched = thd_engine->search_idsp("9E04115A-AE87-4D1C-9500-0F3E340BFE75"); ++ ++ if (policy_matched == THD_SUCCESS) { ++ thd_log_info("IDSP policy matched, so trusting PPCC limits\n"); ++ return true; ++ } ++ + def_max_power = rapl_read_pl1_max(); + if (def_max_power > pl0_max_pwr) + thd_log_warn("ppcc limits is less than def PL1 max power :%d check thermal-conf.xml.auto\n", def_max_power); +Index: thermald-2.4.9/src/thd_engine.h +=================================================================== +--- thermald-2.4.9.orig/src/thd_engine.h ++++ thermald-2.4.9/src/thd_engine.h +@@ -234,6 +234,9 @@ public: + return config_file; + } + virtual ppcc_t *get_ppcc_param(std::string name); ++ virtual int search_idsp(std::string name) { ++ return THD_ERROR; ++ } + cthd_zone *search_zone(std::string name); + cthd_cdev *search_cdev(std::string name); + cthd_sensor *search_sensor(std::string name); diff -Nru thermald-2.4.9/debian/patches/0011-Parse-GDDV-before-thd_engine-init.patch thermald-2.4.9/debian/patches/0011-Parse-GDDV-before-thd_engine-init.patch --- thermald-2.4.9/debian/patches/0011-Parse-GDDV-before-thd_engine-init.patch 1970-01-01 08:00:00.000000000 +0800 +++ thermald-2.4.9/debian/patches/0011-Parse-GDDV-before-thd_engine-init.patch 2023-03-20 19:48:09.000000000 +0800 @@ -0,0 +1,42 @@ +From 611ae0cae6b0c5e7e28c9a0d064a8343cf8aff88 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Tue, 5 Jul 2022 16:58:24 -0700 +Subject: [PATCH 13/18] Parse GDDV before thd_engine init + +Parse GDDV tables so that IDSP and PPCC information is available +for RAPL cdev. This is just parsing GDDV not evaluating any +conditions. Evaulating conditions will require all sensors +and zone intialized, so that is done during thd_engine_start(). +--- + src/thd_engine_adaptive.cpp | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +Index: thermald-2.4.9/src/thd_engine_adaptive.cpp +=================================================================== +--- thermald-2.4.9.orig/src/thd_engine_adaptive.cpp ++++ thermald-2.4.9/src/thd_engine_adaptive.cpp +@@ -2027,12 +2027,6 @@ int cthd_engine_adaptive::thd_engine_ini + return THD_ERROR; + } + +- /* Read the sensors/zones */ +- res = cthd_engine::thd_engine_init(ignore_cpuid_check, adaptive); +- if (res != THD_SUCCESS) +- return res; +- +- + if (sysfs.read(int3400_base_path + "firmware_node/path", + int3400_path) < 0) { + thd_log_debug("Unable to locate INT3400 firmware path\n"); +@@ -2094,6 +2088,11 @@ int cthd_engine_adaptive::thd_engine_ini + return THD_SUCCESS; + } + ++ /* Read the sensors/zones */ ++ res = cthd_engine::thd_engine_init(ignore_cpuid_check, adaptive); ++ if (res != THD_SUCCESS) ++ return res; ++ + return THD_SUCCESS; + } + diff -Nru thermald-2.4.9/debian/patches/0012-Always-match-motion-0.patch thermald-2.4.9/debian/patches/0012-Always-match-motion-0.patch --- thermald-2.4.9/debian/patches/0012-Always-match-motion-0.patch 1970-01-01 08:00:00.000000000 +0800 +++ thermald-2.4.9/debian/patches/0012-Always-match-motion-0.patch 2023-03-20 19:48:09.000000000 +0800 @@ -0,0 +1,26 @@ +From 4339234275b87b3973487cade283addd14fc9818 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Wed, 13 Jul 2022 11:05:31 -0700 +Subject: [PATCH 17/17] Always match motion = 0 + +--- + src/thd_gddv.cpp | 6 ++++++ + 1 file changed, 6 insertions(+) + +Index: thermald-2.4.9/src/thd_engine_adaptive.cpp +=================================================================== +--- thermald-2.4.9.orig/src/thd_engine_adaptive.cpp ++++ thermald-2.4.9/src/thd_engine_adaptive.cpp +@@ -1293,6 +1293,12 @@ int cthd_engine_adaptive::evaluate_condi + ret = evaluate_power_slider_condition(condition); + } + ++ if (condition.condition == Motion) { ++ thd_log_debug("Match motion == 0 :%d\n", condition.argument); ++ if (condition.argument == 0) ++ ret = THD_SUCCESS; ++ } ++ + if (ret) { + if (condition.time && condition.state_entry_time == 0) { + condition.state_entry_time = time(NULL); diff -Nru thermald-2.4.9/debian/patches/0013-Add-AlderLake-N.patch thermald-2.4.9/debian/patches/0013-Add-AlderLake-N.patch --- thermald-2.4.9/debian/patches/0013-Add-AlderLake-N.patch 1970-01-01 08:00:00.000000000 +0800 +++ thermald-2.4.9/debian/patches/0013-Add-AlderLake-N.patch 2023-03-20 14:36:25.000000000 +0800 @@ -0,0 +1,25 @@ +From a4f5a5fa0fe8e6b607b60752f4c6d2d1d8c8749f Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Tue, 6 Dec 2022 16:29:27 -0800 +Subject: [PATCH] Add AlderLake N + +Add Alderlake N in the supported CPU model list. +--- + src/thd_engine.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/thd_engine.cpp b/src/thd_engine.cpp +index 801fbb5..e37ce9b 100644 +--- a/src/thd_engine.cpp ++++ b/src/thd_engine.cpp +@@ -713,6 +713,7 @@ static supported_ids_t id_table[] = { + { 6, 0x9a }, // Alderlake + { 6, 0xb7 }, // Raptorlake + { 6, 0xba }, // Raptorlake ++ { 6, 0xbe }, // Alderlake N + { 6, 0xbf }, // Raptorlake S + { 0, 0 } // Last Invalid entry + }; +-- +2.34.1 + diff -Nru thermald-2.4.9/debian/patches/0014-Process-ITMT-v2.patch thermald-2.4.9/debian/patches/0014-Process-ITMT-v2.patch --- thermald-2.4.9/debian/patches/0014-Process-ITMT-v2.patch 1970-01-01 08:00:00.000000000 +0800 +++ thermald-2.4.9/debian/patches/0014-Process-ITMT-v2.patch 2023-03-20 19:48:09.000000000 +0800 @@ -0,0 +1,48 @@ +From 90d56bc06cdcf78e7398ea7da389401516591774 Mon Sep 17 00:00:00 2001 +From: Srinivas Pandruvada +Date: Mon, 30 Jan 2023 14:07:34 -0800 +Subject: [PATCH] Process ITMT v2 + +Parsing ITMT v2 structure. Skip fields, which are not known. +--- + src/thd_gddv.cpp | 20 +++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +Index: thermald-2.4.9/src/thd_engine_adaptive.cpp +=================================================================== +--- thermald-2.4.9.orig/src/thd_engine_adaptive.cpp ++++ thermald-2.4.9/src/thd_engine_adaptive.cpp +@@ -629,6 +629,11 @@ int cthd_engine_adaptive::parse_itmt(cha + + thd_log_debug(" ITMT version %d %s\n", (int) version, name); + ++ if (version > 2) { ++ thd_log_info("Unsupported ITMT version\n"); ++ return THD_ERROR; ++ } ++ + if (name == NULL) + itmt.name = "Default"; + else +@@ -642,7 +647,20 @@ int cthd_engine_adaptive::parse_itmt(cha + itmt_entry.pl1_min = get_string(buf, &offset); + itmt_entry.pl1_max = get_string(buf, &offset); + itmt_entry.unused = get_string(buf, &offset); +- offset += 12; ++ if (version == 2) { ++ // Ref DPTF/Sources/Manager/DataManager.cpp DataManager::loadItmtTableObject() ++ std::string dummy_str; ++ unsigned long long dummy1,dummy2, dummy3; ++ ++ // There are three additional fields ++ dummy1 = get_uint64(buf, &offset); ++ dummy_str = get_string(buf, &offset); ++ dummy2 = get_uint64(buf, &offset); ++ dummy3 = get_uint64(buf, &offset); ++ thd_log_debug("ignore dummy_str:%s %llu %llu %llu\n", dummy_str.c_str(), dummy1, dummy2, dummy3); ++ } else { ++ offset += 12; ++ } + + itmt.itmt_entries.push_back(itmt_entry); + } diff -Nru thermald-2.4.9/debian/patches/series thermald-2.4.9/debian/patches/series --- thermald-2.4.9/debian/patches/series 2023-03-08 19:27:17.000000000 +0800 +++ thermald-2.4.9/debian/patches/series 2023-03-20 19:48:09.000000000 +0800 @@ -1,2 +1,14 @@ 0001-Add-RaptorLake-CPU-models.patch 0002-Add-RaptorLake-S-CPU-models.patch +0003-Parse-ITMT-Table.patch +0004-Add-capability-for-min-max-per-trip.patch +0005-Install-ITMT-target.patch +0006-Use-per-trip-min-max.patch +0007-Add-INT3400-base-path-for-Raptor-Lake.patch +0008-Install-passive-default.patch +0009-Parse-idsp-and-trips.patch +0010-Use-PL1-max-min-from-PPCC-when-policies-match.patch +0011-Parse-GDDV-before-thd_engine-init.patch +0012-Always-match-motion-0.patch +0013-Add-AlderLake-N.patch +0014-Process-ITMT-v2.patch