[Skiboot] [PATCH V8 3/8] psr: occ: Add support to change power-shifting-ratio
Stewart Smith
stewart at linux.vnet.ibm.com
Thu Jul 27 18:47:16 AEST 2017
Shilpasri G Bhat <shilpa.bhat at linux.vnet.ibm.com> writes:
> 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 at linux.vnet.ibm.com>
> ---
> core/Makefile.inc | 2 +-
> core/psr.c | 40 +++++++++++++
> doc/device-tree/ibm,opal/power-mgt/psr.rst | 41 +++++++++++++
> doc/opal-api/opal-psr.rst | 74 ++++++++++++++++++++++++
> hw/occ.c | 92 ++++++++++++++++++++++++++++++
> include/opal-api.h | 4 +-
> include/psr.h | 46 +++++++++++++++
> 7 files changed, 297 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-psr.rst
> create mode 100644 include/psr.h
>
> 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..5a24d89
> --- /dev/null
> +++ b/core/psr.c
> @@ -0,0 +1,40 @@
> +/* 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_psr(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_PSR, opal_get_psr, 3);
> +
> +static int opal_set_psr(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_PSR, opal_set_psr, 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..aaf6fa3
> --- /dev/null
> +++ b/doc/device-tree/ibm,opal/power-mgt/psr.rst
> @@ -0,0 +1,41 @@
> +power-mgt/psr
> +------------------
Add "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."
> +The power-shifting-ratio sensors are populated in this node.
> +Each child node in the "psr" node represents a configurable psr
> +sensor.
Use a compatible property to define power-shifting-ratio 'devices'.
> +For example : ::
> + cpu-to-gpu at 1
> +
> +Each child node has below properties:
> +
> +`handle`
> + Handle to indicate the type of psr
> +
> +`label`
> + Name of the psr sensor
> +
Add "The format of the handle is internal, and *not* ABI, although
currentyl it uses the following encoding"
> +PSR handle uses the following encoding: ::
> +
> + | Class |Reserved| RID | Type |
> + |-------|--------|------|------|
> +
> +.. code-block:: dts
> +
> + power-mgt {
> + psr {
> +
> + cpu-to-gpu at 0 {
> + name = "cpu-to-gpu"
> + handle = <0x00000000>
> + label = "cpu_to_gpu_0"
> + };
> +
> + cpu-to-gpu at 1 {
> + name = "cpu-to-gpu"
> + handle = <0x00000100>
> + label = "cpu_to_gpu_1"
> + };
> + };
> + };
> diff --git a/doc/opal-api/opal-psr.rst b/doc/opal-api/opal-psr.rst
> new file mode 100644
> index 0000000..65a2ae3
> --- /dev/null
> +++ b/doc/opal-api/opal-psr.rst
> @@ -0,0 +1,74 @@
> +.. _opal-psr:
> +
> +OPAL_GET_PSR
> +==============================
> +OPAL call to read the power-shifting-ratio using a handle to identify
> +the type (CPU-GPU, CPU-MEM) which is exported via DT.
I think we should have "(e.g CPU vs. GPU, CPU vs. MEM)".
> +
> +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_SET_PSR
> +============================
> +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 c0a1158..162b453 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 */
> @@ -1363,6 +1368,93 @@ 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, *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_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..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
I think I'd prefer to call these OPAL_GET_POWER_SHIFT_RATIO and
OPAL_SET_POWER_SHIFT_RATIO, just so we have one fewer three letter
acronyms to get confused about :)
> diff --git a/include/psr.h b/include/psr.h
> new file mode 100644
> index 0000000..37e1d20
> --- /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 */
> +extern int occ_get_psr(u32 handle, u32 *ratio);
> +extern int occ_set_psr(u32 handle, int token, u32 ratio);
> +
> +#endif /* __PSR_H */
> --
> 1.8.3.1
>
--
Stewart Smith
OPAL Architect, IBM.
More information about the Skiboot
mailing list