diff mbox

[V7,3/8] occ: Add support to change power-shifting-ratio

Message ID 1500488561-22489-4-git-send-email-shilpa.bhat@linux.vnet.ibm.com
State Superseded
Headers show

Commit Message

Shilpasri G Bhat July 19, 2017, 6:22 p.m. UTC
Add support to set the CPU-GPU power shifting ratio which is used by
the OCC power capping algorithm. PSR value of 100 takes all power away
from CPU first and a PSR value of 0 caps GPU first.

Signed-off-by: Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com>
---
 hw/occ.c           | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/opal-api.h |  4 ++-
 2 files changed, 99 insertions(+), 1 deletion(-)
diff mbox

Patch

diff --git a/hw/occ.c b/hw/occ.c
index d166fe5..907cf6e 100644
--- a/hw/occ.c
+++ b/hw/occ.c
@@ -1217,6 +1217,7 @@  exit:
 }
 
 static void occ_add_powercap_sensors(struct dt_node *power_mgt);
+static void occ_add_psr_sensors(struct dt_node *power_mgt);
 
 static void occ_cmd_interface_init(void)
 {
@@ -1262,6 +1263,9 @@  static void occ_cmd_interface_init(void)
 
 	/* Add powercap sensors to DT */
 	occ_add_powercap_sensors(power_mgt);
+
+	/* Add power-shifting-ratio CPU-GPU sensors to DT */
+	occ_add_psr_sensors(power_mgt);
 }
 
 /* Powercap interface */
@@ -1362,6 +1366,98 @@  int occ_set_powercap(int token, u32 pcap)
 	return opal_occ_command(&chips[i], token, &pcap_data);
 };
 
+/* Power-Shifting Ratio */
+enum psr_type {
+	PSR_TYPE_CPU_TO_GPU, /* 0% Cap GPU first, 100% Cap CPU first */
+};
+
+static int opal_get_power_shifting_ratio(u32 handle, int token __unused,
+					 int *ratio)
+{
+	struct occ_dynamic_data *ddata;
+	struct proc_chip *chip;
+	int type = (handle >> 24) & 0xF;
+	int i = handle & 0xF;
+
+	if (type != PSR_TYPE_CPU_TO_GPU)
+		return OPAL_UNSUPPORTED;
+
+	if (i > nr_occs || i < 0)
+		return OPAL_PARAMETER;
+
+	if (!(*chips[i].valid))
+		return OPAL_WRONG_STATE;
+
+	chip = get_chip(chips[i].chip_id);
+	ddata = get_occ_dynamic_data(chip);
+	*ratio = ddata->pwr_shifting_ratio;
+	return OPAL_SUCCESS;
+}
+
+static u8 psr_cdata;
+static struct opal_occ_cmd_data psr_data = {
+	.data		= &psr_cdata,
+	.cmd		= OCC_CMD_SET_POWER_SHIFTING_RATIO,
+};
+
+static int opal_set_power_shifting_ratio(u32 handle, int token, int ratio)
+{
+	struct occ_dynamic_data *ddata;
+	struct proc_chip *chip;
+	int type = (handle >> 24) & 0xF;
+	int i = handle & 0xF;
+
+	if (type != PSR_TYPE_CPU_TO_GPU)
+		return OPAL_UNSUPPORTED;
+
+	if (ratio < 0 || ratio > 100)
+		return OPAL_PARAMETER;
+
+	if (i > nr_occs || i < 0)
+		return OPAL_PARAMETER;
+
+	if (!(*chips[i].valid))
+		return OPAL_WRONG_STATE;
+
+	chip = get_chip(chips[i].chip_id);
+	ddata = get_occ_dynamic_data(chip);
+	if (ratio == ddata->pwr_shifting_ratio)
+		return OPAL_SUCCESS;
+
+	psr_cdata = ratio;
+	return opal_occ_command(&chips[i], token, &psr_data);
+}
+
+static void occ_add_psr_sensors(struct dt_node *power_mgt)
+{
+	struct dt_node *node, *cnode;
+	int i;
+
+	node = dt_new(power_mgt, "psr");
+	if (!node) {
+		prerror("OCC: Failed to create power-shifting-ratio node\n");
+		return;
+	}
+
+	for (i = 0; i < nr_occs; i++) {
+		char name[20];
+		u32 handle = (PSR_TYPE_CPU_TO_GPU << 24) | i;
+
+		cnode = dt_new_addr(node, "cpu-to-gpu", handle);
+		if (!cnode) {
+			prerror("OCC: Failed to create power-shifting-ratio node\n");
+			return;
+		}
+
+		snprintf(name, 20, "cpu_to_gpu_%d", chips[i].chip_id);
+		dt_add_property_string(cnode, "label", name);
+		dt_add_property_cells(cnode, "handle", handle);
+	}
+
+	opal_register(OPAL_GET_PSR, opal_get_power_shifting_ratio, 3);
+	opal_register(OPAL_SET_PSR, opal_set_power_shifting_ratio, 3);
+}
+
 /* CPU-OCC PState init */
 /* Called after OCC init on P8 and P9 */
 void occ_pstates_init(void)
diff --git a/include/opal-api.h b/include/opal-api.h
index 3ad4898..2717a0d 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -210,7 +210,9 @@ 
 #define OPAL_IMC_COUNTERS_STOP			151
 #define OPAL_GET_POWERCAP			152
 #define OPAL_SET_POWERCAP			153
-#define OPAL_LAST				153
+#define OPAL_GET_PSR				154
+#define OPAL_SET_PSR				155
+#define OPAL_LAST				155
 
 /* Device tree flags */