2
* cthd_cdev_rapl.cpp: thermal cooling class implementation
4
* Copyright (C) 2012 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>
24
#include "thd_cdev_rapl.h"
25
#include "thd_engine.h"
27
/* This uses Intel RAPL driver to cool the system. RAPL driver show
28
* mas thermal spec power in max_state. Each state can compensate
29
* rapl_power_dec_percent, from the max state.
32
void cthd_sysfs_cdev_rapl::set_curr_state(int state, int arg) {
34
std::stringstream tc_state_dev;
36
std::stringstream state_str;
39
if (state < inc_dec_val) {
42
cdev_sysfs.write("enabled", "0");
45
if (dynamic_phy_max_enable) {
46
if (!calculate_phy_max()) {
51
new_state = phy_max - state;
53
cdev_sysfs.write("enabled", "1");
55
state_str << new_state;
56
thd_log_info("set cdev state index %d state %d wr:%d\n", index, state,
58
tc_state_dev << "constraint_" << constraint_index << "_power_limit_uw";
59
if (cdev_sysfs.write(tc_state_dev.str(), state_str.str()) < 0)
60
curr_state = (state == 0) ? 0 : max_state;
64
void cthd_sysfs_cdev_rapl::set_curr_state_raw(int state, int arg) {
65
std::stringstream state_str;
66
std::stringstream tc_state_dev;
69
if (state <= min_state)
72
if (dynamic_phy_max_enable) {
73
if (!calculate_phy_max()) {
78
new_state = phy_max - state;
81
state_str << new_state;
83
tc_state_dev << "constraint_" << constraint_index << "_power_limit_uw";
84
if (cdev_sysfs.write(tc_state_dev.str(), state_str.str()) < 0)
85
curr_state = (state == 0) ? 0 : max_state;
87
thd_log_info("set cdev state raw index %d state %d wr:%d\n", index, state,
92
bool cthd_sysfs_cdev_rapl::calculate_phy_max() {
93
if (dynamic_phy_max_enable) {
94
unsigned int curr_max_phy;
95
curr_max_phy = thd_engine->rapl_power_meter.rapl_action_get_power(
97
thd_log_info("curr_phy_max = %u \n", curr_max_phy);
98
if (curr_max_phy < rapl_min_default_step)
100
if (phy_max < curr_max_phy) {
101
phy_max = curr_max_phy;
102
set_inc_dec_value(phy_max * (float) rapl_power_dec_percent / 100);
104
max_state -= (float) max_state * rapl_low_limit_percent / 100;
105
thd_log_info("PHY_MAX %lu, step %d, max_state %d\n", phy_max,
106
inc_dec_val, max_state);
113
int cthd_sysfs_cdev_rapl::get_curr_state() {
117
int cthd_sysfs_cdev_rapl::get_max_state() {
122
int cthd_sysfs_cdev_rapl::update() {
124
std::stringstream temp_str;
126
unsigned long constraint_phy_max;
128
std::string domain_name;
130
for (i = 0; i < rapl_no_time_windows; ++i) {
131
temp_str << "constraint_" << i << "_name";
132
if (cdev_sysfs.exists(temp_str.str())) {
133
std::string type_str;
134
cdev_sysfs.read(temp_str.str(), type_str);
135
if (type_str == "long_term") {
142
thd_log_info("powercap RAPL no long term time window\n");
146
cdev_sysfs.read("name", domain_name);
147
if (domain_name == "package-0")
148
ppcc = read_ppcc_power_limits();
151
phy_max = pl0_max_pwr;
152
set_inc_dec_value(pl0_step_pwr);
153
max_state = pl0_max_pwr - pl0_min_pwr;
155
temp_str.str(std::string());
156
temp_str << "constraint_" << _index << "_max_power_uw";
157
if (!cdev_sysfs.exists(temp_str.str())) {
158
thd_log_info("powercap RAPL no max power limit range %s \n",
159
temp_str.str().c_str());
162
if (cdev_sysfs.read(temp_str.str(), &phy_max) < 0) {
163
thd_log_info("powercap RAPL invalid max power limit range \n");
164
thd_log_info("Calculate dynamically phy_max \n");
166
thd_engine->rapl_power_meter.rapl_start_measure_power();
167
max_state = rapl_min_default_step;
168
set_inc_dec_value(rapl_min_default_step);
169
dynamic_phy_max_enable = true;
173
std::stringstream temp_power_str;
174
temp_power_str.str(std::string());
175
temp_power_str << "constraint_" << _index << "_power_limit_uw";
176
if (!cdev_sysfs.exists(temp_power_str.str())) {
177
thd_log_info("powercap RAPL no power limit uw %s \n",
178
temp_str.str().c_str());
181
if (cdev_sysfs.read(temp_power_str.str(), &constraint_phy_max) <= 0) {
182
thd_log_info("powercap RAPL invalid max power limit range \n");
183
constraint_phy_max = 0;
185
if (constraint_phy_max > phy_max) {
187
"Default constraint power limit is more than max power %lu:%lu\n",
188
constraint_phy_max, phy_max);
189
phy_max = constraint_phy_max;
191
thd_log_info("powercap RAPL max power limit range %lu \n", phy_max);
193
set_inc_dec_value(phy_max * (float) rapl_power_dec_percent / 100);
195
max_state -= (float) max_state * rapl_low_limit_percent / 100;
197
std::stringstream time_window;
198
temp_str.str(std::string());
199
temp_str << "constraint_" << _index << "_time_window_us";
200
if (!cdev_sysfs.exists(temp_str.str())) {
201
thd_log_info("powercap RAPL no time_window_us %s \n",
202
temp_str.str().c_str());
206
time_window << pl0_min_window;
208
time_window << def_rapl_time_window;
209
cdev_sysfs.write(temp_str.str(), time_window.str());
211
std::stringstream enable;
212
temp_str.str(std::string());
213
temp_str << "enabled";
214
if (!cdev_sysfs.exists(temp_str.str())) {
215
thd_log_info("powercap RAPL no enabled %s \n", temp_str.str().c_str());
218
cdev_sysfs.write(temp_str.str(), "0");
220
thd_log_debug("RAPL max limit %d increment: %d\n", max_state, inc_dec_val);
221
constraint_index = _index;
222
set_pid_param(1000, 100, 10);
227
bool cthd_sysfs_cdev_rapl::read_ppcc_power_limits() {
230
if (sys_fs.exists("/sys/bus/pci/devices/0000:00:04.0/power_limits/"))
231
sys_fs.update_path("/sys/bus/pci/devices/0000:00:04.0/power_limits/");
232
else if (sys_fs.exists("/sys/bus/pci/devices/0000:00:0b.0/power_limits/"))
233
sys_fs.update_path("/sys/bus/pci/devices/0000:00:0b.0/power_limits/");
234
else if (sys_fs.exists(
235
"/sys/bus/platform/devices/INT3401:00/power_limits/"))
237
"/sys/bus/platform/devices/INT3401:00/power_limits/");
241
if (sys_fs.exists("power_limit_0_max_uw")) {
242
if (sys_fs.read("power_limit_0_max_uw", &pl0_max_pwr) <= 0)
246
if (sys_fs.exists("power_limit_0_min_uw")) {
247
if (sys_fs.read("power_limit_0_min_uw", &pl0_min_pwr) <= 0)
251
if (sys_fs.exists("power_limit_0_tmin_us")) {
252
if (sys_fs.read("power_limit_0_tmin_us", &pl0_min_window) <= 0)
256
if (sys_fs.exists("power_limit_0_step_uw")) {
257
if (sys_fs.read("power_limit_0_step_uw", &pl0_step_pwr) <= 0)
261
if (pl0_max_pwr && pl0_min_pwr && pl0_min_window && pl0_step_pwr) {
262
thd_log_info("ppcc limits max:%u min:%u min_win:%u step:%u\n",
263
pl0_max_pwr, pl0_min_pwr, pl0_min_window, pl0_step_pwr);