[RFC,v2,1/2] SLW: Add new idle device-tree format

Message ID 20181015091531.14126-2-akshay.adiga@linux.vnet.ibm.com
State New
Headers show
Series
  • New device-tree format and Opal based idle save-restore
Related show

Checks

Context Check Description
snowpatch_ozlabs/apply_patch success master/apply_patch Successfully applied

Commit Message

Akshay Adiga Oct. 15, 2018, 9:15 a.m.
Add stop states under ibm,idle-states in addition to the current array
based device tree properties.

Drawback of the array based dt node is that versioning of idle states is
not possible. Future kernels will have capability to handle newer stop
sates, hence versioning will help kenrnel to selectively enable states
based on its capability. The new device tree node is extensible and
has a compatible string for each idle-state.

Linux kernel can now look at the version string and decide if it has the
ability to handle that idle state. Henceforth, if kernel does not know
about a version it checks if it has "opal-supported", in which case it
will use opal-call-based-method to execute stop state. When both
"opal-supported" and  version string  are unknown, it will skip all deeper
states.

"cpuidle" and "cpuoffline" indicates that state should be used for
cpuidle or hotplug.

Final output
       power-mgt {
            ...
         ibm,enabled-stop-levels = <0xec000000>;
         ibm,cpu-idle-state-psscr-mask = <0x0 0x3003ff 0x0 0x3003ff>;
         ibm,cpu-idle-state-latencies-ns = <0x3e8 0x7d0>;
         ibm,cpu-idle-state-psscr = <0x0 0x330 0x0 0x300330>;
         ibm,cpu-idle-state-flags = <0x100000 0x101000>;
         ibm,cpu-idle-state-residency-ns = <0x2710 0x4e20>;
         ibm,idle-states {
                     stop4 {
                         flags = <0x207000>;
                         compatible = "ibm,state-v1",
                                      "opal-supported";
                         type = "cpuidle";
                         psscr-mask = <0x0 0x3003ff>;
                         handle = <0x102>;
                         latency-ns = <0x186a0>;
                         residency-ns = <0x989680>;
                         psscr = <0x0 0x300374>;
                  };
                    ...
                    stop11 {
                     ...
                         compatible = "ibm,state-v1",
                                      "opal-supported";
                         type = "cpuoffline";
                         ...
                  };
             };

Signed-off-by: Akshay Adiga <akshay.adiga@linux.vnet.ibm.com>
---
Changes from v1 :
 - Moved "cpuidle" and "cpuoffline" to a different property
   called "type"
 
 hw/slw.c | 124 +++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 97 insertions(+), 27 deletions(-)

Patch

diff --git a/hw/slw.c b/hw/slw.c
index dfa9189b..c0181534 100644
--- a/hw/slw.c
+++ b/hw/slw.c
@@ -414,8 +414,12 @@  static bool idle_prepare_core(struct proc_chip *chip, struct cpu_thread *c)
 
 /* Define device-tree fields */
 #define MAX_NAME_LEN	16
+#define MAX_VERSION_LEN	25
 struct cpu_idle_states {
 	char name[MAX_NAME_LEN];
+	char version[MAX_VERSION_LEN];
+	char type[MAX_VERSION_LEN];
+	u32 dt_node_type;
 	u32 latency_ns;
 	u32 residency_ns;
 	/*
@@ -504,6 +508,8 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 	{
 		.name = "stop0_lite", /* Enter stop0 with no state loss */
 		.latency_ns = 1000,
+		.dt_node_type = 0,
+		.version = "ibm,state-v1",
 		.residency_ns = 10000,
 		.flags = 0*OPAL_PM_DEC_STOP \
 		       | 0*OPAL_PM_TIMEBASE_STOP  \
@@ -518,6 +524,8 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 	{
 		.name = "stop0",
 		.latency_ns = 2000,
+		.dt_node_type = 0,
+		.version = "ibm,state-v1",
 		.residency_ns = 20000,
 		.flags = 0*OPAL_PM_DEC_STOP \
 		       | 0*OPAL_PM_TIMEBASE_STOP  \
@@ -536,6 +544,9 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 
 	{
 		.name = "stop1",
+		.dt_node_type = 1,
+		.version = "ibm,state-v1",
+		.type = "cpuidle",
 		.latency_ns = 5000,
 		.residency_ns = 50000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -557,6 +568,9 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 
 	{
 		.name = "stop2",
+		.dt_node_type = 1,
+		.version = "ibm,state-v1",
+		.type = "cpuidle",
 		.latency_ns = 10000,
 		.residency_ns = 100000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -573,6 +587,9 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
 	{
 		.name = "stop4",
+		.dt_node_type = 1,
+		.version = "ibm,state-v1",
+		.type = "cpuidle",
 		.latency_ns = 100000,
 		.residency_ns = 10000000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -589,6 +606,9 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 		.pm_ctrl_reg_mask = OPAL_PM_PSSCR_MASK },
 	{
 		.name = "stop5",
+		.dt_node_type = 1,
+		.version = "ibm,state-v1",
+		.type = "cpuidle",
 		.latency_ns = 200000,
 		.residency_ns = 20000000,
 		.flags = 0*OPAL_PM_DEC_STOP \
@@ -606,6 +626,9 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 
 	{
 		.name = "stop8",
+		.dt_node_type = 1,
+		.version = "ibm,state-v1",
+		.type = "cpuoffline",
 		.latency_ns = 2000000,
 		.residency_ns = 20000000,
 		.flags = 1*OPAL_PM_DEC_STOP \
@@ -623,6 +646,9 @@  static struct cpu_idle_states power9_cpu_idle_states[] = {
 
 	{
 		.name = "stop11",
+		.dt_node_type = 1,
+		.version = "ibm,state-v1",
+		.type = "cpuoffline",
 		.latency_ns = 10000000,
 		.residency_ns = 100000000,
 		.flags = 1*OPAL_PM_DEC_STOP \
@@ -1011,34 +1037,78 @@  void add_cpu_idle_state_properties(void)
 				}
 			}
 		}
+		if (states[i].dt_node_type == 0) {
+			prlog(PR_NOTICE, "SLW: Enabling: %s\n", states[i].name);
+
+			/*
+			 * If a state is supported add each of its property
+			 * to its corresponding property buffer.
+			 */
+			strncpy(name_buf, states[i].name, MAX_NAME_LEN);
+			name_buf = name_buf + strlen(states[i].name) + 1;
+
+			*latency_ns_buf = cpu_to_fdt32(states[i].latency_ns);
+			latency_ns_buf++;
+
+			*residency_ns_buf = cpu_to_fdt32(states[i].residency_ns);
+			residency_ns_buf++;
+
+			*flags_buf = cpu_to_fdt32(states[i].flags);
+			flags_buf++;
+
+			*pm_ctrl_reg_val_buf = cpu_to_fdt64(states[i].pm_ctrl_reg_val);
+			pm_ctrl_reg_val_buf++;
+
+			*pm_ctrl_reg_mask_buf = cpu_to_fdt64(states[i].pm_ctrl_reg_mask);
+			pm_ctrl_reg_mask_buf++;
+
+			/* Increment buffer length trackers */
+			name_buf_len += strlen(states[i].name) + 1;
+			num_supported_idle_states++;
+
+		} else if (states[i].dt_node_type == 1) {
+
+			struct dt_node *parent_node, *dt_state_node;
+			char version_buf[MAX_VERSION_LEN];
+			u32 *lat_buf, *res_buf, *flg_buf;
+			u64 *psscr_buf, *psscr_mask_buf;
+
+			lat_buf = malloc(sizeof(u32));
+			res_buf = malloc(sizeof(u32));
+			flg_buf = malloc(sizeof(u32));
+			psscr_buf = malloc(sizeof(u64));
+			psscr_mask_buf = malloc(sizeof(u64));
+			prlog(PR_NOTICE, "SLW: Enabling: %s in new format\n", states[i].name);
+
+			parent_node = dt_new_check(power_mgt,  "ibm,idle-states");
+			if (!parent_node)
+				prlog(PR_ERR, "Error creating ibm,idle-states\n");
+
+			dt_state_node = dt_new_check(parent_node, states[i].name);
+			if (!dt_state_node)
+				prlog(PR_ERR, "Error creating %s\n", states[i].name);
+
+			strncpy(version_buf, states[i].version, strlen(states[i].version)+1);
+			dt_add_property_strings(dt_state_node, "compatible", version_buf);
+			dt_add_property_strings(dt_state_node, "type", states[i].type);
+
+			*lat_buf = cpu_to_fdt32(states[i].latency_ns);
+			dt_add_property(dt_state_node, "latency-ns", lat_buf, sizeof(u32));
+			*res_buf = cpu_to_fdt32(states[i].residency_ns);
+			dt_add_property(dt_state_node, "residency-ns", res_buf, sizeof(u32));
+			*flg_buf = cpu_to_fdt32(states[i].flags);
+			dt_add_property(dt_state_node, "flags", flg_buf, sizeof(u32));
+			*psscr_buf = cpu_to_fdt64(states[i].pm_ctrl_reg_val);
+			dt_add_property(dt_state_node, "psscr", psscr_buf, sizeof(u64));
+			*psscr_mask_buf = cpu_to_fdt64(states[i].pm_ctrl_reg_mask);
+			dt_add_property(dt_state_node, "psscr-mask", psscr_mask_buf, sizeof(u64));
+			free(res_buf);
+			free(lat_buf);
+			free(flg_buf);
+			free(psscr_buf);
+			free(psscr_mask_buf);
 
-		prlog(PR_INFO, "SLW: Enabling: %s\n", states[i].name);
-
-		/*
-		 * If a state is supported add each of its property
-		 * to its corresponding property buffer.
-		 */
-		strncpy(name_buf, states[i].name, MAX_NAME_LEN);
-		name_buf = name_buf + strlen(states[i].name) + 1;
-
-		*latency_ns_buf = cpu_to_fdt32(states[i].latency_ns);
-		latency_ns_buf++;
-
-		*residency_ns_buf = cpu_to_fdt32(states[i].residency_ns);
-		residency_ns_buf++;
-
-		*flags_buf = cpu_to_fdt32(states[i].flags);
-		flags_buf++;
-
-		*pm_ctrl_reg_val_buf = cpu_to_fdt64(states[i].pm_ctrl_reg_val);
-		pm_ctrl_reg_val_buf++;
-
-		*pm_ctrl_reg_mask_buf = cpu_to_fdt64(states[i].pm_ctrl_reg_mask);
-		pm_ctrl_reg_mask_buf++;
-
-		/* Increment buffer length trackers */
-		name_buf_len += strlen(states[i].name) + 1;
-		num_supported_idle_states++;
+		}
 
 	}