Blame SOURCES/tuned-2.12-latency-as-cstate.patch

f916fa
diff --git a/profiles/latency-performance/tuned.conf b/profiles/latency-performance/tuned.conf
f916fa
index 054c554..4cd69a1 100644
f916fa
--- a/profiles/latency-performance/tuned.conf
f916fa
+++ b/profiles/latency-performance/tuned.conf
f916fa
@@ -6,7 +6,7 @@
f916fa
 summary=Optimize for deterministic performance at the cost of increased power consumption
f916fa
 
f916fa
 [cpu]
f916fa
-force_latency=1
f916fa
+force_latency=cstate.id:1|1
f916fa
 governor=performance
f916fa
 energy_perf_bias=performance
f916fa
 min_perf_pct=100
f916fa
diff --git a/profiles/sap-hana/tuned.conf b/profiles/sap-hana/tuned.conf
f916fa
index 9afac82..d74250b 100644
f916fa
--- a/profiles/sap-hana/tuned.conf
f916fa
+++ b/profiles/sap-hana/tuned.conf
f916fa
@@ -7,7 +7,7 @@ summary=Optimize for SAP HANA
f916fa
 include=throughput-performance
f916fa
 
f916fa
 [cpu]
f916fa
-force_latency=70
f916fa
+force_latency=cstate.id:3|70
f916fa
 
f916fa
 [vm]
f916fa
 transparent_hugepages=never
f916fa
diff --git a/profiles/virtual-host/tuned.conf b/profiles/virtual-host/tuned.conf
f916fa
index ca493d6..8acb92d 100644
f916fa
--- a/profiles/virtual-host/tuned.conf
f916fa
+++ b/profiles/virtual-host/tuned.conf
f916fa
@@ -18,4 +18,4 @@ kernel.sched_migration_cost_ns = 5000000
f916fa
 
f916fa
 [cpu]
f916fa
 # Setting C3 state sleep mode/power savings
f916fa
-force_latency=70
f916fa
+force_latency=cstate.id:3|70
f916fa
diff --git a/tuned/plugins/plugin_cpu.py b/tuned/plugins/plugin_cpu.py
f916fa
index 77e9448..04c7b19 100644
f916fa
--- a/tuned/plugins/plugin_cpu.py
f916fa
+++ b/tuned/plugins/plugin_cpu.py
f916fa
@@ -12,8 +12,7 @@ import procfs
f916fa
 
f916fa
 log = tuned.logs.get()
f916fa
 
f916fa
-# TODO: force_latency -> command
f916fa
-#       intel_pstate
f916fa
+cpuidle_states_path = "/sys/devices/system/cpu/cpu0/cpuidle"
f916fa
 
f916fa
 class CPULatencyPlugin(base.Plugin):
f916fa
 	"""
f916fa
@@ -210,13 +209,74 @@ class CPULatencyPlugin(base.Plugin):
f916fa
 	def _instance_unapply_dynamic(self, instance, device):
f916fa
 		pass
f916fa
 
f916fa
+	def _str2int(self, s):
f916fa
+		try:
f916fa
+			return int(s)
f916fa
+		except (ValueError, TypeError):
f916fa
+			return None
f916fa
+
f916fa
+	def _read_cstates_latency(self):
f916fa
+		self.cstates_latency = {}
f916fa
+		for d in os.listdir(cpuidle_states_path):
f916fa
+			cstate_path = cpuidle_states_path + "/%s/" % d
f916fa
+			name = self._cmd.read_file(cstate_path + "name", err_ret = None, no_error = True)
f916fa
+			latency = self._cmd.read_file(cstate_path + "latency", err_ret = None, no_error = True)
f916fa
+			if name is not None and latency is not None:
f916fa
+				latency = self._str2int(latency)
f916fa
+				if latency is not None:
f916fa
+					self.cstates_latency[name.strip()] = latency
f916fa
+
f916fa
+	def _get_latency_by_cstate_name(self, name):
f916fa
+		log.debug("getting latency for cstate with name '%s'" % name)
f916fa
+		if self.cstates_latency is None:
f916fa
+			log.debug("reading cstates latency table")
f916fa
+			self._read_cstates_latency()
f916fa
+		latency = self.cstates_latency.get(name, None)
f916fa
+		log.debug("cstate name mapped to latency: %s" % str(latency))
f916fa
+		return latency
f916fa
+
f916fa
+	def _get_latency_by_cstate_id(self, lid):
f916fa
+		log.debug("getting latency for cstate with ID '%s'" % str(lid))
f916fa
+		lid = self._str2int(lid)
f916fa
+		if lid is None:
f916fa
+			log.debug("cstate ID is invalid")
f916fa
+			return None
f916fa
+		latency_path = cpuidle_states_path + "/%s/latency" % ("state%d" % lid)
f916fa
+		latency = self._str2int(self._cmd.read_file(latency_path, err_ret = None, no_error = True))
f916fa
+		log.debug("cstate ID mapped to latency: %s" % str(latency))
f916fa
+		return latency
f916fa
+
f916fa
+	def _parse_latency(self, latency):
f916fa
+		self.cstates_latency = None
f916fa
+		latencies = str(latency).split("|")
f916fa
+		log.debug("parsing latency")
f916fa
+		for latency in latencies:
f916fa
+			try:
f916fa
+				latency = int(latency)
f916fa
+				log.debug("parsed directly specified latency value: %d" % latency)
f916fa
+			except ValueError:
f916fa
+				if latency[0:10] == "cstate.id:":
f916fa
+					latency = self._get_latency_by_cstate_id(latency[10:])
f916fa
+				elif latency[0:12] == "cstate.name:":
f916fa
+					latency = self._get_latency_by_cstate_name(latency[12:])
f916fa
+				else:
f916fa
+					latency = None
f916fa
+					log.debug("invalid latency specified: '%s'" % str(latency))
f916fa
+			if latency is not None:
f916fa
+				break
f916fa
+		return latency
f916fa
+
f916fa
 	def _set_latency(self, latency):
f916fa
-		latency = int(latency)
f916fa
-		if self._has_pm_qos and self._latency != latency:
f916fa
-			log.info("setting new cpu latency %d" % latency)
f916fa
-			latency_bin = struct.pack("i", latency)
f916fa
-			os.write(self._cpu_latency_fd, latency_bin)
f916fa
-			self._latency = latency
f916fa
+		latency = self._parse_latency(latency)
f916fa
+		if self._has_pm_qos:
f916fa
+			if latency is None:
f916fa
+				log.error("unable to evaluate latency value (probably wrong settings in the 'cpu' section of current profile), disabling PM QoS")
f916fa
+				self._has_pm_qos = False
f916fa
+			elif self._latency != latency:
f916fa
+				log.info("setting new cpu latency %d" % latency)
f916fa
+				latency_bin = struct.pack("i", latency)
f916fa
+				os.write(self._cpu_latency_fd, latency_bin)
f916fa
+				self._latency = latency
f916fa
 
f916fa
 	def _get_available_governors(self, device):
f916fa
 		return self._cmd.read_file("/sys/devices/system/cpu/%s/cpufreq/scaling_available_governors" % device).strip().split()