diff mbox

[V9,4/8] psr: occ: Add support to change power-shifting-ratio

Message ID 1501182933-756-5-git-send-email-shilpa.bhat@linux.vnet.ibm.com
State Accepted
Headers show

Commit Message

Shilpasri G Bhat July 27, 2017, 7:15 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.

Documentation enhanced by Stewart Smith.

Signed-off-by: Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com>
---
Changes from V8:
- Enhanced documentation
- Add compatible property "ibm,opal-power-shift-ratio"
- Replace OPAL_{GET/SET}_PSR with OPAL_{GET/SET}_POWER_SHIFT_RATIO

 core/Makefile.inc                          |  2 +-
 core/psr.c                                 | 42 +++++++++++++
 doc/device-tree/ibm,opal/power-mgt/psr.rst | 53 +++++++++++++++++
 doc/opal-api/opal-power-shift-ratio.rst    | 79 +++++++++++++++++++++++++
 hw/occ.c                                   | 95 ++++++++++++++++++++++++++++++
 include/opal-api.h                         |  4 +-
 include/psr.h                              | 46 +++++++++++++++
 7 files changed, 319 insertions(+), 2 deletions(-)
 create mode 100644 core/psr.c
 create mode 100644 doc/device-tree/ibm,opal/power-mgt/psr.rst
 create mode 100644 doc/opal-api/opal-power-shift-ratio.rst
 create mode 100644 include/psr.h
diff mbox

Patch

diff --git a/core/Makefile.inc b/core/Makefile.inc
index b3c9e91..f2de2f6 100644
--- a/core/Makefile.inc
+++ b/core/Makefile.inc
@@ -8,7 +8,7 @@  CORE_OBJS += pci-opal.o fast-reboot.o device.o exceptions.o trace.o affinity.o
 CORE_OBJS += vpd.o hostservices.o platform.o nvram.o nvram-format.o hmi.o
 CORE_OBJS += console-log.o ipmi.o time-utils.o pel.o pool.o errorlog.o
 CORE_OBJS += timer.o i2c.o rtc.o flash.o sensor.o ipmi-opal.o
-CORE_OBJS += flash-subpartition.o bitmap.o buddy.o pci-quirk.o powercap.o
+CORE_OBJS += flash-subpartition.o bitmap.o buddy.o pci-quirk.o powercap.o psr.o
 
 ifeq ($(SKIBOOT_GCOV),1)
 CORE_OBJS += gcov-profiling.o
diff --git a/core/psr.c b/core/psr.c
new file mode 100644
index 0000000..d3ff6ac
--- /dev/null
+++ b/core/psr.c
@@ -0,0 +1,42 @@ 
+/* Copyright 2017 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *	http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <psr.h>
+
+static int opal_get_power_shift_ratio(u32 handle, int token __unused,
+				      u32 *ratio)
+{
+	if (!ratio || !opal_addr_valid(ratio))
+		return OPAL_PARAMETER;
+
+	if (psr_get_class(handle) == PSR_CLASS_OCC)
+		return occ_get_psr(handle, ratio);
+
+	return OPAL_UNSUPPORTED;
+};
+
+opal_call(OPAL_GET_POWER_SHIFT_RATIO, opal_get_power_shift_ratio, 3);
+
+static int opal_set_power_shift_ratio(u32 handle, int token,
+				      u32 ratio)
+{
+	if (psr_get_class(handle) == PSR_CLASS_OCC)
+		return occ_set_psr(handle, token, ratio);
+
+	return OPAL_UNSUPPORTED;
+};
+
+opal_call(OPAL_SET_POWER_SHIFT_RATIO, opal_set_power_shift_ratio, 3);
diff --git a/doc/device-tree/ibm,opal/power-mgt/psr.rst b/doc/device-tree/ibm,opal/power-mgt/psr.rst
new file mode 100644
index 0000000..edae8da
--- /dev/null
+++ b/doc/device-tree/ibm,opal/power-mgt/psr.rst
@@ -0,0 +1,53 @@ 
+power-mgt/psr
+------------------
+
+Some systems allow modification of how power consumption throttling
+is balanced between entities in a system. A typical one may be how the power
+management complex should balance throttling CPU versus the GPU. An OPAL
+call can be used to set these ratios, which are described in the device
+tree.
+
+In the future, there may be more available settings than just CPU
+versus GPU.
+
+Each child node in the "psr" node represents a configurable psr
+sensor.
+
+For example : ::
+        cpu-to-gpu@1
+
+The compatible property is set to "ibm,opal-power-shift-ratio".
+
+Each child node has below properties:
+
+`handle`
+  Handle to indicate the type of psr
+
+`label`
+  Name of the psr sensor
+
+The format of the handle is internal, and ``not`` ABI, although
+currently it uses the following encoding ::
+
+	| Class |Reserved|  RID	| Type |
+	|-------|--------|------|------|
+
+.. code-block:: dts
+
+   power-mgt {
+     psr {
+        compatible = "ibm,opal-power-shift-ratio"
+
+        cpu-to-gpu@0 {
+                name = "cpu-to-gpu"
+                handle = <0x00000000>
+                label = "cpu_to_gpu_0"
+        };
+
+        cpu-to-gpu@1 {
+                name = "cpu-to-gpu"
+                handle = <0x00000100>
+                label = "cpu_to_gpu_1"
+        };
+     };
+    };
diff --git a/doc/opal-api/opal-power-shift-ratio.rst b/doc/opal-api/opal-power-shift-ratio.rst
new file mode 100644
index 0000000..7f1f71f
--- /dev/null
+++ b/doc/opal-api/opal-power-shift-ratio.rst
@@ -0,0 +1,79 @@ 
+.. _opal-psr:
+
+OPAL_GET_POWER_SHIFT_RATIO
+==============================
+OPAL call to read the power-shifting-ratio using a handle to identify
+the type (e.g CPU vs. GPU, CPU vs. MEM) which is exported via
+device-tree.
+
+The call can be asynchronus, where the token parameter is used to wait
+for the completion.
+
+Parameters
+----------
+::
+        u32 handle
+        int token
+        u32 *ratio
+
+Returns
+-------
+OPAL_SUCCESS
+  Success
+
+OPAL_PARAMETER
+  Invalid ratio pointer
+
+OPAL_UNSUPPORTED
+  No support for reading psr
+
+OPAL_HARDWARE
+  Unable to procced due to the current hardware state
+
+OPAL_ASYNC_COMPLETION
+  Request was sent and an async completion message will be sent with
+  token and status of the request.
+
+OPAL_SET_POWER_SHIFT_RATIO
+==============================
+OPAL call to set power-shifting-ratio using a handle to identify
+the type of PSR which is exported in device-tree. This call can be
+asynchronus where the token parameter is used to wait for the
+completion.
+
+Parameters
+----------
+::
+        u32 handle
+        int token
+        u32 ratio
+
+Returns
+-------
+OPAL_SUCCESS
+  Success
+
+OPAL_PARAMETER
+  Invalid ratio requested
+
+OPAL_UNSUPPORTED
+  No support for changing the ratio
+
+OPAL_PERMISSION
+  Hardware cannot take the request
+
+OPAL_ASYNC_COMPLETION
+  Request was sent and an async completion message will be sent with
+  token and status of the request.
+
+OPAL_HARDWARE
+  Unable to procced due to the current hardware state
+
+OPAL_BUSY
+  Previous request in progress
+
+OPAL_INTERNAL_ERROR
+  Error in request response
+
+OPAL_TIMEOUT
+  Timeout in request completion
diff --git a/hw/occ.c b/hw/occ.c
index d286628..8337011 100644
--- a/hw/occ.c
+++ b/hw/occ.c
@@ -29,6 +29,7 @@ 
 #include <timer.h>
 #include <i2c.h>
 #include <powercap.h>
+#include <psr.h>
 
 /* OCC Communication Area for PStates */
 
@@ -1215,6 +1216,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)
 {
@@ -1260,6 +1262,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 */
@@ -1364,6 +1369,96 @@  int occ_set_powercap(u32 handle, 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 */
+};
+
+int occ_get_psr(u32 handle, u32 *ratio)
+{
+	struct occ_dynamic_data *ddata;
+	struct proc_chip *chip;
+	u8 i = psr_get_rid(handle);
+
+	if (psr_get_type(handle) != PSR_TYPE_CPU_TO_GPU)
+		return OPAL_UNSUPPORTED;
+
+	if (i > nr_occs)
+		return OPAL_UNSUPPORTED;
+
+	if (!(*chips[i].valid))
+		return OPAL_HARDWARE;
+
+	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,
+};
+
+int occ_set_psr(u32 handle, int token, u32 ratio)
+{
+	struct occ_dynamic_data *ddata;
+	struct proc_chip *chip;
+	u8 i = psr_get_rid(handle);
+
+	if (psr_get_type(handle) != PSR_TYPE_CPU_TO_GPU)
+		return OPAL_UNSUPPORTED;
+
+	if (ratio > 100)
+		return OPAL_PARAMETER;
+
+	if (i > nr_occs)
+		return OPAL_UNSUPPORTED;
+
+	if (!(*chips[i].valid))
+		return OPAL_HARDWARE;
+
+	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;
+	int i;
+
+	node = dt_new(power_mgt, "psr");
+	if (!node) {
+		prerror("OCC: Failed to create power-shifting-ratio node\n");
+		return;
+	}
+
+	dt_add_property_string(node, "compatible",
+			       "ibm,opal-power-shift-ratio");
+	for (i = 0; i < nr_occs; i++) {
+		struct dt_node *cnode;
+		char name[20];
+		u32 handle = psr_make_handle(PSR_CLASS_OCC, i,
+					     PSR_TYPE_CPU_TO_GPU);
+
+		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);
+	}
+}
+
 /* 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..8d33c08 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_POWER_SHIFT_RATIO		154
+#define OPAL_SET_POWER_SHIFT_RATIO		155
+#define OPAL_LAST				155
 
 /* Device tree flags */
 
diff --git a/include/psr.h b/include/psr.h
new file mode 100644
index 0000000..92c0aa5
--- /dev/null
+++ b/include/psr.h
@@ -0,0 +1,46 @@ 
+/* Copyright 2017 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *	http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __PSR_H
+#define __PSR_H
+
+#include <opal.h>
+
+enum psr_class {
+	PSR_CLASS_OCC,
+};
+
+/*
+ * PSR handle is defined as u32. The first and last bytes are
+ * used to indicate the class and type. RID indiactes psr class
+ * specific data. For PSR_CLASS_OCC psr class RID is the chip index.
+ *
+ *	| Class |Reserved|  RID	| Type |
+ *	|-------|--------|------|------|
+ */
+
+#define psr_make_handle(class, rid, type) (((class & 0xF) << 24) | \
+					   ((rid & 0xF) << 8) | (type & 0xF))
+
+#define psr_get_class(handle)	((handle >> 24) & 0xF)
+#define psr_get_rid(handle)	((handle >> 8) & 0xF)
+#define psr_get_type(handle)	(handle & 0xF)
+
+/* Powercap OCC interface */
+int occ_get_psr(u32 handle, u32 *ratio);
+int occ_set_psr(u32 handle, int token, u32 ratio);
+
+#endif /* __PSR_H */