Skip to content

Commit 3bbdb8d

Browse files
committed
uncore: Allow to configure uncore ELC control
The Efficiency Latency Control (ELC) feature improves performance per watt. With this feature hardware power management algorithms optimize trade-off between latency and power consumption. Add additional configuration for uncore plugin to include attributes to configure ELC. Refer to Intel White Paper Link: Linux kernel documentation: https://docs.kernel.org/admin-guide/pm/intel_uncore_frequency_scaling.html Example configuration: [uncore_all] type=uncore elc_floor_freq_khz=2400000 elc_high_threshold_enable=1 elc_high_threshold_percent=95 elc_low_threshold_percent=10
1 parent 3554d5b commit 3bbdb8d

File tree

1 file changed

+138
-3
lines changed

1 file changed

+138
-3
lines changed

tuned/plugins/plugin_uncore.py

Lines changed: 138 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,17 @@ class UncorePlugin(hotplug.Plugin):
3838
on the Intel system to 90% of the allowable range. Except uncore10 which
3939
maximum frequency limit will be set to 4 GHz.
4040
====
41+
42+
The Efficiency Latency Control (ELC) Interface
43+
44+
Options [option]`elc_floor_freq_khz`, [option]`elc_low_threshold_percent`
45+
[option]`elc_high_threshold_percent` and [option]`elc_high_threshold_enable`
46+
correspond to `sysfs` files exposed by Intel uncore frequency driver.
47+
The scope of control is same as max_freq_khz and max_freq_khz settings as described
48+
above.
49+
Refer to https://docs.kernel.org/admin-guide/pm/intel_uncore_frequency_scaling.html
50+
for detail.
51+
4152
"""
4253

4354
def _init_devices(self):
@@ -88,16 +99,27 @@ def _get_all(self, device):
8899
initial_min_freq_khz = self._get(device, "initial_min_freq_khz")
89100
max_freq_khz = self._get(device, "max_freq_khz")
90101
min_freq_khz = self._get(device, "min_freq_khz")
102+
elc_floor_freq_khz = self._get(device, "elc_floor_freq_khz")
103+
elc_high_threshold_enable = self._get(device, "elc_high_threshold_enable")
104+
elc_high_threshold_percent = self._get(device, "elc_high_threshold_percent")
105+
elc_low_threshold_percent = self._get(device, "elc_low_threshold_percent")
106+
91107
except (OSError, IOError):
92108
log.error("fail to read uncore frequency values")
93109
return None
94-
return (initial_max_freq_khz, initial_min_freq_khz, max_freq_khz, min_freq_khz)
110+
return (initial_max_freq_khz, initial_min_freq_khz, max_freq_khz, min_freq_khz,
111+
elc_floor_freq_khz, elc_high_threshold_enable, elc_high_threshold_percent,
112+
elc_low_threshold_percent)
95113

96114
@classmethod
97115
def _get_config_options(cls):
98116
return {
99117
"max_freq_khz": None,
100118
"min_freq_khz": None,
119+
"elc_floor_freq_khz": None,
120+
"elc_high_threshold_enable": None,
121+
"elc_high_threshold_percent": None,
122+
"elc_low_threshold_percent": None,
101123
}
102124

103125
def _validate_khz_value(self, device, min_or_max, value):
@@ -110,7 +132,10 @@ def _validate_khz_value(self, device, min_or_max, value):
110132
values = self._get_all(device)
111133
if values is None:
112134
return None
113-
(initial_max_freq_khz, initial_min_freq_khz, max_freq_khz, min_freq_khz) = values
135+
136+
(initial_max_freq_khz, initial_min_freq_khz, max_freq_khz, min_freq_khz,
137+
elc_floor_freq_khz, elc_high_threshold_enable, elc_high_threshold_percent,
138+
elc_low_threshold_percent) = values
114139

115140
if min_or_max == IS_MAX:
116141
if freq_khz < min_freq_khz:
@@ -157,7 +182,7 @@ def _validate_value(self, device, min_or_max, value):
157182
values = self._get_all(device)
158183
if values is None:
159184
return None
160-
(initial_max_freq_khz, initial_min_freq_khz, _, _) = values
185+
(initial_max_freq_khz, initial_min_freq_khz, _, _, _) = values
161186

162187
khz = initial_min_freq_khz + int(pct * (initial_max_freq_khz - initial_min_freq_khz) / 100)
163188
else:
@@ -216,3 +241,113 @@ def _get_min_freq_khz(self, device, instance, ignore_missing=False):
216241

217242
log.debug("%s: get min_freq_khz %d" % (device, min_freq_khz))
218243
return min_freq_khz
244+
245+
@command_get("elc_floor_freq_khz")
246+
def _get_elc_floor_freq_khz(self, device, instance, ignore_missing=False):
247+
if ignore_missing and not os.path.isdir(SYSFS_DIR):
248+
return None
249+
250+
try:
251+
elc_floor_freq_khz = self._get(device, "elc_floor_freq_khz")
252+
except (OSError, IOError):
253+
log.error("fail to read elc floor uncore frequency values")
254+
return None
255+
256+
log.debug("%s: get elc_floor_freq_khz %d" % (device, elc_floor_freq_khz))
257+
return elc_floor_freq_khz
258+
259+
@command_set("elc_floor_freq_khz", per_device = True)
260+
def _set_elc_floor_freq_khz(self, value, device, instance, sim, remove):
261+
elc_floor_freq_khz = self._validate_value(device, IS_MAX, value)
262+
if elc_floor_freq_khz is None:
263+
return None
264+
265+
if sim:
266+
return elc_floor_freq_khz
267+
268+
log.debug("%s: set elc_floor_freq_khz %d" % (device, elc_floor_freq_khz))
269+
return self._set(device, "elc_floor_freq_khz", elc_floor_freq_khz)
270+
271+
@command_set("elc_high_threshold_percent", per_device = True)
272+
def _set_elc_high_threshold_percent(self, value, device, instance, sim, remove):
273+
pct = self._validate_percent_value(value.rstrip("%"))
274+
if pct is None:
275+
return None
276+
277+
if sim:
278+
return pct
279+
280+
log.debug("%s: set elc_high_threshold_percent %d" % (device, pct))
281+
return self._set(device, "elc_high_threshold_percent", pct)
282+
283+
@command_get("elc_high_threshold_percent")
284+
def _get_elc_high_threshold_percent(self, device, instance, ignore_missing=False):
285+
if ignore_missing and not os.path.isdir(SYSFS_DIR):
286+
return None
287+
288+
try:
289+
elc_high_threshold_percent = self._get(device, "elc_high_threshold_percent")
290+
except (OSError, IOError):
291+
log.error("fail to read uncore elc threshold")
292+
return None
293+
294+
log.debug("%s: get elc_high_threshold_percent %d" % (device, elc_high_threshold_percent))
295+
return elc_high_threshold_percent
296+
297+
@command_set("elc_low_threshold_percent", per_device = True)
298+
def _set_elc_low_threshold_percent(self, value, device, instance, sim, remove):
299+
pct = self._validate_percent_value(value.rstrip("%"))
300+
if pct is None:
301+
return None
302+
303+
if sim:
304+
return pct
305+
306+
log.debug("%s: set elc_low_threshold_percent %d" % (device, pct))
307+
return self._set(device, "elc_low_threshold_percent", pct)
308+
309+
@command_get("elc_low_threshold_percent")
310+
def _get_elc_low_threshold_percent(self, device, instance, ignore_missing=False):
311+
if ignore_missing and not os.path.isdir(SYSFS_DIR):
312+
return None
313+
314+
try:
315+
elc_low_threshold_percent = self._get(device, "elc_low_threshold_percent")
316+
except (OSError, IOError):
317+
log.error("fail to read uncore elc threshold")
318+
return None
319+
320+
log.debug("%s: get elc_low_threshold_percent %d" % (device, elc_low_threshold_percent))
321+
return elc_low_threshold_percent
322+
323+
@command_set("elc_high_threshold_enable", per_device = True)
324+
def _set_elc_high_threshold_enable(self, value, device, instance, sim, remove):
325+
try:
326+
enable = int(value)
327+
except ValueError:
328+
log.error("value '%s' is not integer" % value)
329+
return None
330+
331+
if enable != 0 and enable != 1:
332+
log.error("Invalid Enable value '%s' is not within [0..1] range" % value)
333+
return None
334+
335+
if sim:
336+
return enable
337+
338+
log.debug("%s: set elc_high_threshold_enable %d" % (device, enable))
339+
return self._set(device, "elc_high_threshold_enable", enable)
340+
341+
@command_get("elc_high_threshold_enable")
342+
def _get_elc_high_threshold_enable(self, device, instance, ignore_missing=False):
343+
if ignore_missing and not os.path.isdir(SYSFS_DIR):
344+
return None
345+
346+
try:
347+
elc_high_threshold_enable = self._get(device, "elc_high_threshold_enable")
348+
except (OSError, IOError):
349+
log.error("fatuned/plugins/plugin_uncore.pyil to read uncore elc enable")
350+
return None
351+
352+
log.debug("%s: get elc_low_threshold_percent %d" % (device, elc_high_threshold_enable))
353+
return elc_high_threshold_enable

0 commit comments

Comments
 (0)