2
* cthd_engine_defualt.cpp: Default thermal engine
4
* Copyright (C) 2013 Intel Corporation. All rights reserved.
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License version
8
* 2 or later as published by the Free Software Foundation.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21
* Author Name <Srinivas.Pandruvada@linux.intel.com>
27
#include <sys/types.h>
28
#include "thd_engine_default.h"
29
#include "thd_zone_cpu.h"
30
#include "thd_zone_generic.h"
31
#include "thd_cdev_gen_sysfs.h"
32
#include "thd_cdev_cpufreq.h"
33
#include "thd_cdev_rapl.h"
34
#include "thd_cdev_intel_pstate_driver.h"
35
#include "thd_zone_surface.h"
36
#include "thd_cdev_msr_rapl.h"
38
#define ACTIVATE_SURFACE
40
// Default CPU cooling devices, which are not part of thermal sysfs
41
// Since non trivial initialization is not supported, we init all fields even if they are not needed
42
/* Some security scan handler can't parse, the following block and generate unnecessary errors.
43
* hiding good ones. So init in old style compatible to C++
45
static cooling_dev_t cpu_def_cooling_devices[] = {
47
.mask = CDEV_DEF_BIT_UNIT_VAL | CDEV_DEF_BIT_READ_BACK | CDEV_DEF_BIT_MIN_STATE | CDEV_DEF_BIT_STEP,
48
.index = 0, .unit_val = ABSOULUTE_VALUE, .min_state = 0, .max_state = 0, .inc_dec_step = 5,
49
.read_back = false, .auto_down_control = false,
50
.type_string = "intel_powerclamp", .path_str = "",
51
.debounce_interval = 4, .pid_enable = false,
52
.pid = {0.0, 0.0, 0.0}},
55
static cooling_dev_t cpu_def_cooling_devices[] = { { true, CDEV_DEF_BIT_UNIT_VAL
56
| CDEV_DEF_BIT_READ_BACK | CDEV_DEF_BIT_MIN_STATE | CDEV_DEF_BIT_STEP,
57
0, ABSOULUTE_VALUE, 0, 0, 5, false, false, "intel_powerclamp", "", 4,
58
false, { 0.0, 0.0, 0.0 } } };
60
cthd_engine_default::~cthd_engine_default() {
62
parser.parser_deinit();
65
int cthd_engine_default::parser_init() {
68
if (parser.parser_init() == THD_SUCCESS) {
69
if (parser.start_parse() == THD_SUCCESS) {
70
parser.dump_thermal_conf();
71
parser_init_done = true;
79
void cthd_engine_default::parser_deinit() {
80
if (parser_init_done) {
81
parser.parser_deinit();
82
parser_init_done = false;
86
int cthd_engine_default::read_thermal_sensors() {
90
int sensor_mask = 0x0f;
92
const std::string base_path = "/sys/devices/platform/";
94
thd_read_default_thermal_sensors();
97
sensor = search_sensor("pkg-temp-0");
99
// Force this to support async
100
sensor->set_async_capable(true);
102
// Default CPU temperature zone
103
// Find path to read DTS temperature
104
if ((dir = opendir(base_path.c_str())) != NULL) {
105
while ((entry = readdir(dir)) != NULL) {
106
if (!strncmp(entry->d_name, "coretemp.", strlen("coretemp."))) {
108
unsigned int mask = 0x1;
110
if (sensor_mask & mask) {
111
std::stringstream temp_input_str;
112
std::string path = base_path + entry->d_name + "/";
113
csys_fs dts_sysfs(path.c_str());
114
temp_input_str << "temp" << cnt << "_input";
115
if (dts_sysfs.exists(temp_input_str.str())) {
116
cthd_sensor *sensor = new cthd_sensor(index,
117
base_path + entry->d_name + "/"
118
+ temp_input_str.str(),
119
temp_input_str.str(), SENSOR_TYPE_RAW);
120
if (sensor->sensor_update() != THD_SUCCESS) {
125
sensors.push_back(sensor);
137
if (index == sensor_count) {
138
// No coretemp sysfs exist, try hwmon
139
thd_log_warn("Thermal DTS: No coretemp sysfs, trying hwmon \n");
140
cthd_sensor *sensor = new cthd_sensor(index,
141
"/sys/class/hwmon/hwmon0/temp1_input", "hwmon",
143
if (sensor->sensor_update() != THD_SUCCESS) {
147
sensors.push_back(sensor);
150
if (index == sensor_count) {
151
thd_log_error("Thermal DTS or hwmon: No Zones present: \n");
152
return THD_FATAL_ERROR;
156
// Add from XML sensor config
157
if (!parser_init() && parser.platform_matched()) {
158
for (int i = 0; i < parser.sensor_count(); ++i) {
159
thermal_sensor_t *sensor_config = parser.get_sensor_dev_index(i);
162
cthd_sensor *sensor = search_sensor(sensor_config->name);
164
if (sensor_config->mask & SENSOR_DEF_BIT_PATH)
165
sensor->update_path(sensor_config->path);
166
if (sensor_config->mask & SENSOR_DEF_BIT_ASYNC_CAPABLE)
167
sensor->set_async_capable(sensor_config->async_capable);
169
cthd_sensor *sensor_new = new cthd_sensor(index,
170
sensor_config->path, sensor_config->name,
172
if (sensor_new->sensor_update() != THD_SUCCESS) {
176
sensors.push_back(sensor_new);
180
sensor_count = index;
183
for (unsigned int i = 0; i < sensors.size(); ++i) {
184
sensors[i]->sensor_dump();
190
int cthd_engine_default::read_thermal_zones() {
193
struct dirent *entry;
194
const std::string base_path = "/sys/devices/platform/";
196
thd_read_default_thermal_zones();
199
if (!search_zone("cpu")) {
200
bool cpu_zone_created = false;
201
thd_log_info("zone cpu will be created \n");
202
// Default CPU temperature zone
203
// Find path to read DTS temperature
204
if ((dir = opendir(base_path.c_str())) != NULL) {
205
while ((entry = readdir(dir)) != NULL) {
206
if (!strncmp(entry->d_name, "coretemp.", strlen("coretemp."))) {
207
cthd_zone_cpu *zone = new cthd_zone_cpu(count,
208
base_path + entry->d_name + "/",
209
atoi(entry->d_name + strlen("coretemp.")));
210
if (zone->zone_update() == THD_SUCCESS) {
211
zone->set_zone_active();
212
zones.push_back(zone);
214
cpu_zone_created = true;
222
#ifdef ACTIVATE_SURFACE
223
// Enable when skin sensors are standardized
225
surface = search_zone("Surface");
227
if (!surface || (surface && !surface->zone_active_status())) {
228
cthd_zone_surface *zone = new cthd_zone_surface(count);
229
if (zone->zone_update() == THD_SUCCESS) {
230
zones.push_back(zone);
232
zone->set_zone_active();
236
thd_log_info("TSKN sensor was activated by config \n");
240
if (!cpu_zone_created) {
241
// No coretemp sysfs exist, try hwmon
242
thd_log_warn("Thermal DTS: No coretemp sysfs, trying hwmon \n");
244
cthd_zone_cpu *zone = new cthd_zone_cpu(count,
245
"/sys/class/hwmon/hwmon0/", 0);
246
if (zone->zone_update() == THD_SUCCESS) {
247
zone->set_zone_active();
248
zones.push_back(zone);
250
cpu_zone_created = true;
255
if (!cpu_zone_created) {
256
thd_log_error("Thermal DTS or hwmon: No Zones present: \n");
257
return THD_FATAL_ERROR;
263
// Add from XML thermal zone
264
if (!parser_init() && parser.platform_matched()) {
265
for (int i = 0; i < parser.zone_count(); ++i) {
266
thermal_zone_t *zone_config = parser.get_zone_dev_index(i);
269
cthd_zone *zone = search_zone(zone_config->type);
271
thd_log_info("Zone already present %s \n", zone_config->type.c_str());
272
for (unsigned int k = 0; k < zone_config->trip_pts.size();
274
trip_point_t &trip_pt_config = zone_config->trip_pts[k];
275
cthd_sensor *sensor = search_sensor(
276
trip_pt_config.sensor_type);
278
thd_log_error("XML zone: invalid sensor type \n");
279
// This will update the trip tempearture for the matching
281
if (trip_pt_config.temperature) {
282
cthd_trip_point trip_pt(zone->get_trip_count(),
283
trip_pt_config.trip_pt_type,
284
trip_pt_config.temperature,
285
trip_pt_config.hyst, zone->get_zone_index(),
286
-1, trip_pt_config.control_type);
287
zone->update_trip_temp(trip_pt);
291
zone->bind_sensor(sensor);
292
cthd_trip_point trip_pt(zone->get_trip_count(),
293
trip_pt_config.trip_pt_type,
294
trip_pt_config.temperature, trip_pt_config.hyst,
295
zone->get_zone_index(), sensor->get_index(),
296
trip_pt_config.control_type);
298
for (unsigned int j = 0;
299
j < trip_pt_config.cdev_trips.size(); ++j) {
300
cthd_cdev *cdev = search_cdev(
301
trip_pt_config.cdev_trips[j].type);
303
trip_pt.thd_trip_point_add_cdev(*cdev,
304
trip_pt_config.cdev_trips[j].influence);
307
zone->add_trip(trip_pt);
309
zone->set_zone_active();
311
cthd_zone_generic *zone = new cthd_zone_generic(count, i,
313
if (zone->zone_update() == THD_SUCCESS) {
314
zones.push_back(zone);
316
zone->set_zone_active();
324
for (unsigned int i = 0; i < zones.size(); ++i) {
325
zones[i]->zone_dump();
330
int cthd_engine_default::add_replace_cdev(cooling_dev_t *config) {
332
bool cdev_present = false;
333
int current_cdev_index = cdev_cnt;
334
bool percent_unit = false;
336
// Check if there is existing cdev with this name and path
337
cdev = search_cdev(config->type_string);
340
// Also check for path, some device like FAN has multiple paths for same type_str
341
std::string base_path = cdev->get_base_path();
342
if (config->path_str.size() && config->path_str != base_path) {
343
cdev_present = false;
348
cdev = new cthd_gen_sysfs_cdev(current_cdev_index, config->path_str);
351
cdev->set_cdev_type(config->type_string);
352
if (cdev->update() != THD_SUCCESS) {
356
cdevs.push_back(cdev);
359
if (config->mask & CDEV_DEF_BIT_UNIT_VAL) {
360
if (config->unit_val == RELATIVE_PERCENTAGES)
363
if (config->mask & CDEV_DEF_BIT_AUTO_DOWN)
364
cdev->set_down_adjust_control(config->auto_down_control);
365
if (config->mask & CDEV_DEF_BIT_STEP) {
367
cdev->set_inc_dec_value(
368
cdev->get_curr_state() * config->inc_dec_step / 100);
370
cdev->set_inc_dec_value(config->inc_dec_step);
372
if (config->mask & CDEV_DEF_BIT_MIN_STATE) {
374
cdev->thd_cdev_set_min_state_param(
375
cdev->get_curr_state() * config->min_state / 100);
377
cdev->thd_cdev_set_min_state_param(config->min_state);
379
if (config->mask & CDEV_DEF_BIT_MAX_STATE) {
381
cdev->thd_cdev_set_max_state_param(
382
cdev->get_curr_state() * config->max_state / 100);
384
cdev->thd_cdev_set_max_state_param(config->max_state);
386
if (config->mask & CDEV_DEF_BIT_READ_BACK)
387
cdev->thd_cdev_set_read_back_param(config->read_back);
389
if (config->mask & CDEV_DEF_BIT_DEBOUNCE_VAL)
390
cdev->set_debounce_interval(config->debounce_interval);
392
if (config->mask & CDEV_DEF_BIT_PID_PARAMS) {
394
cdev->set_pid_param(config->pid.Kp, config->pid.Ki, config->pid.Kd);
398
current_cdev_index++;
404
int cthd_engine_default::read_cooling_devices() {
408
// Read first all the default cooling devices added by kernel
409
thd_read_default_cooling_devices();
410
int current_cdev_index = cdev_cnt;
412
// Add RAPL cooling device
413
cthd_sysfs_cdev_rapl *rapl_dev = new cthd_sysfs_cdev_rapl(cdev_cnt, 0);
414
rapl_dev->set_cdev_type("rapl_controller");
415
if (rapl_dev->update() == THD_SUCCESS) {
416
cdevs.push_back(rapl_dev);
420
if (processor_id_match()) {
421
// RAPL control via MSR
422
cthd_cdev_rapl_msr *rapl_msr_dev = new cthd_cdev_rapl_msr(cdev_cnt,
424
rapl_msr_dev->set_cdev_type("rapl_controller");
425
if (rapl_msr_dev->update() == THD_SUCCESS) {
426
cdevs.push_back(rapl_msr_dev);
432
// Add Intel P state driver as cdev
433
cthd_intel_p_state_cdev *pstate_dev = new cthd_intel_p_state_cdev(cdev_cnt);
434
pstate_dev->set_cdev_type("intel_pstate");
435
if (pstate_dev->update() == THD_SUCCESS) {
436
cdevs.push_back(pstate_dev);
441
// Add statically defined cooling devices
442
size = sizeof(cpu_def_cooling_devices) / sizeof(cooling_dev_t);
443
for (i = 0; i < size; ++i) {
444
if (add_replace_cdev(&cpu_def_cooling_devices[i]) == THD_SUCCESS)
445
current_cdev_index++;
446
cdev_cnt = current_cdev_index;
449
// Add from XML cooling device config
450
if (!parser_init() && parser.platform_matched()) {
451
for (int i = 0; i < parser.cdev_count(); ++i) {
452
cooling_dev_t *cdev_config = parser.get_cool_dev_index(i);
456
if (add_replace_cdev(cdev_config) == THD_SUCCESS) {
457
current_cdev_index++;
460
cdev_cnt = current_cdev_index;
463
cthd_cdev_cpufreq *cpu_freq_dev = new cthd_cdev_cpufreq(cdev_cnt, -1);
464
cpu_freq_dev->set_cdev_type("cpufreq");
465
if (cpu_freq_dev->update() == THD_SUCCESS) {
466
cdevs.push_back(cpu_freq_dev);
471
// Dump all cooling devices
472
for (unsigned i = 0; i < cdevs.size(); ++i) {
473
cdevs[i]->cdev_dump();