@@ -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