Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

uncore: Allow to configure uncore ELC control #731

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 138 additions & 3 deletions tuned/plugins/plugin_uncore.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand All @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
Loading