diff --git a/tuned/plugins/plugin_uncore.py b/tuned/plugins/plugin_uncore.py index fe1876223..d420c0d09 100644 --- a/tuned/plugins/plugin_uncore.py +++ b/tuned/plugins/plugin_uncore.py @@ -38,6 +38,17 @@ class UncorePlugin(hotplug.Plugin): on the Intel system to 90% of the allowable range. Except uncore10 which maximum frequency limit will be set to 4 GHz. ==== + + The Efficiency Latency Control (ELC) Interface + + Options [option]`elc_floor_freq_khz`, [option]`elc_low_threshold_percent` + [option]`elc_high_threshold_percent` and [option]`elc_high_threshold_enable` + correspond to `sysfs` files exposed by Intel uncore frequency driver. + The scope of control is same as max_freq_khz and max_freq_khz settings as described + above. + Refer to https://docs.kernel.org/admin-guide/pm/intel_uncore_frequency_scaling.html + for detail. + """ def _init_devices(self): @@ -88,16 +99,27 @@ def _get_all(self, device): initial_min_freq_khz = self._get(device, "initial_min_freq_khz") max_freq_khz = self._get(device, "max_freq_khz") min_freq_khz = self._get(device, "min_freq_khz") + elc_floor_freq_khz = self._get(device, "elc_floor_freq_khz") + elc_high_threshold_enable = self._get(device, "elc_high_threshold_enable") + elc_high_threshold_percent = self._get(device, "elc_high_threshold_percent") + elc_low_threshold_percent = self._get(device, "elc_low_threshold_percent") + except (OSError, IOError): log.error("fail to read uncore frequency values") return None - return (initial_max_freq_khz, initial_min_freq_khz, max_freq_khz, min_freq_khz) + return (initial_max_freq_khz, initial_min_freq_khz, max_freq_khz, min_freq_khz, + elc_floor_freq_khz, elc_high_threshold_enable, elc_high_threshold_percent, + elc_low_threshold_percent) @classmethod def _get_config_options(cls): return { "max_freq_khz": None, "min_freq_khz": None, + "elc_floor_freq_khz": None, + "elc_high_threshold_enable": None, + "elc_high_threshold_percent": None, + "elc_low_threshold_percent": None, } def _validate_khz_value(self, device, min_or_max, value): @@ -110,7 +132,10 @@ def _validate_khz_value(self, device, min_or_max, value): values = self._get_all(device) if values is None: return None - (initial_max_freq_khz, initial_min_freq_khz, max_freq_khz, min_freq_khz) = values + + (initial_max_freq_khz, initial_min_freq_khz, max_freq_khz, min_freq_khz, + elc_floor_freq_khz, elc_high_threshold_enable, elc_high_threshold_percent, + elc_low_threshold_percent) = values if min_or_max == IS_MAX: if freq_khz < min_freq_khz: @@ -157,7 +182,7 @@ def _validate_value(self, device, min_or_max, value): values = self._get_all(device) if values is None: return None - (initial_max_freq_khz, initial_min_freq_khz, _, _) = values + (initial_max_freq_khz, initial_min_freq_khz, _, _, _) = values khz = initial_min_freq_khz + int(pct * (initial_max_freq_khz - initial_min_freq_khz) / 100) else: @@ -216,3 +241,113 @@ def _get_min_freq_khz(self, device, ignore_missing=False): log.debug("%s: get min_freq_khz %d" % (device, min_freq_khz)) return min_freq_khz + + @command_get("elc_floor_freq_khz") + def _get_elc_floor_freq_khz(self, device, ignore_missing=False): + if ignore_missing and not os.path.isdir(SYSFS_DIR): + return None + + try: + elc_floor_freq_khz = self._get(device, "elc_floor_freq_khz") + except (OSError, IOError): + log.error("fail to read elc floor uncore frequency values") + return None + + log.debug("%s: get elc_floor_freq_khz %d" % (device, elc_floor_freq_khz)) + return elc_floor_freq_khz + + @command_set("elc_floor_freq_khz", per_device = True) + def _set_elc_floor_freq_khz(self, value, device, sim, remove): + elc_floor_freq_khz = self._validate_value(device, IS_MAX, value) + if elc_floor_freq_khz is None: + return None + + if sim: + return elc_floor_freq_khz + + log.debug("%s: set elc_floor_freq_khz %d" % (device, elc_floor_freq_khz)) + return self._set(device, "elc_floor_freq_khz", elc_floor_freq_khz) + + @command_set("elc_high_threshold_percent", per_device = True) + def _set_elc_high_threshold_percent(self, value, device, sim, remove): + pct = self._validate_percent_value(value.rstrip("%")) + if pct is None: + return None + + if sim: + return pct + + log.debug("%s: set elc_high_threshold_percent %d" % (device, pct)) + return self._set(device, "elc_high_threshold_percent", pct) + + @command_get("elc_high_threshold_percent") + def _get_elc_high_threshold_percent(self, device, ignore_missing=False): + if ignore_missing and not os.path.isdir(SYSFS_DIR): + return None + + try: + elc_high_threshold_percent = self._get(device, "elc_high_threshold_percent") + except (OSError, IOError): + log.error("fail to read uncore elc threshold") + return None + + log.debug("%s: get elc_high_threshold_percent %d" % (device, elc_high_threshold_percent)) + return elc_high_threshold_percent + + @command_set("elc_low_threshold_percent", per_device = True) + def _set_elc_low_threshold_percent(self, value, device, sim, remove): + pct = self._validate_percent_value(value.rstrip("%")) + if pct is None: + return None + + if sim: + return pct + + log.debug("%s: set elc_low_threshold_percent %d" % (device, pct)) + return self._set(device, "elc_low_threshold_percent", pct) + + @command_get("elc_low_threshold_percent") + def _get_elc_low_threshold_percent(self, device, ignore_missing=False): + if ignore_missing and not os.path.isdir(SYSFS_DIR): + return None + + try: + elc_low_threshold_percent = self._get(device, "elc_low_threshold_percent") + except (OSError, IOError): + log.error("fail to read uncore elc threshold") + return None + + log.debug("%s: get elc_low_threshold_percent %d" % (device, elc_low_threshold_percent)) + return elc_low_threshold_percent + + @command_set("elc_high_threshold_enable", per_device = True) + def _set_elc_high_threshold_enable(self, value, device, sim, remove): + try: + enable = int(value) + except ValueError: + log.error("value '%s' is not integer" % value) + return None + + if enable != 0 and enable != 1: + log.error("Invalid Enable value '%s' is not within [0..1] range" % value) + return None + + if sim: + return enable + + log.debug("%s: set elc_high_threshold_enable %d" % (device, enable)) + return self._set(device, "elc_high_threshold_enable", enable) + + @command_get("elc_high_threshold_enable") + def _get_elc_high_threshold_enable(self, device, ignore_missing=False): + if ignore_missing and not os.path.isdir(SYSFS_DIR): + return None + + try: + elc_high_threshold_enable = self._get(device, "elc_high_threshold_enable") + except (OSError, IOError): + log.error("fatuned/plugins/plugin_uncore.pyil to read uncore elc enable") + return None + + log.debug("%s: get elc_low_threshold_percent %d" % (device, elc_high_threshold_enable)) + return elc_high_threshold_enable