[Skiboot] [RFC PATCH 2/2] occ : Add opal call to support runtime update
Cédric Le Goater
clg at fr.ibm.com
Mon Feb 15 23:54:02 AEDT 2016
Hello Shilpasri,
On 02/15/2016 05:13 AM, Shilpasri G Bhat wrote:
> This patch adds a generic opal call to retrieve updated information.
> One such data is pstate table. OCC can provide new frequencies
> to the host which needs to be parsed and passed to linux for cpufreq
> to consume it. This call can be extended to support reading sensors,
> frequency throttle stats later in the future.
So you don't plan to use the existing sensor OPAL interface ?
C.
> Signed-off-by: Shilpasri G Bhat <shilpa.bhat at linux.vnet.ibm.com>
> ---
> core/opal.c | 19 ++++++++++++
> hw/occ.c | 87 +++++++++++++++++++++++++++++++++++++++++++-----------
> include/opal-api.h | 10 ++++++-
> 3 files changed, 98 insertions(+), 18 deletions(-)
>
> diff --git a/core/opal.c b/core/opal.c
> index b6411f0..70ad574 100644
> --- a/core/opal.c
> +++ b/core/opal.c
> @@ -403,3 +403,22 @@ static int64_t opal_sync_host_reboot(void)
> return OPAL_BUSY_EVENT;
> }
> opal_call(OPAL_SYNC_HOST_REBOOT, opal_sync_host_reboot, 0);
> +
> +/* Opal call to get runtime updates */
> +static int opal_get_dynamic_update(enum opal_update_type type, void *buffer,
> + uint64_t len)
> +{
> + if (type > OPAL_UPDATE_TYPE_MAX) {
> + prerror("Unsupported dynamic update type %d\n", type);
> + return OPAL_PARAMETER;
> + }
> +
> + switch (type) {
> + case OPAL_UPDATE_TYPE_PSTATES:
> + return opal_get_dynamic_pstate_update(buffer, len);
> + default:
> + prerror("Unsupported dynamic update type %d\n", type);
> + return OPAL_PARAMETER;
> + }
> +}
> +opal_call(OPAL_GET_DYNAMIC_UPDATE, opal_get_dynamic_update, 3);
> diff --git a/hw/occ.c b/hw/occ.c
> index 93dd7ce..301d2e4 100644
> --- a/hw/occ.c
> +++ b/hw/occ.c
> @@ -27,6 +27,7 @@
> #include <opal-api.h>
> #include <opal-msg.h>
> #include <timer.h>
> +#include <libfdt/libfdt.h>
>
> /* OCC Communication Area for PStates */
>
> @@ -140,14 +141,23 @@ static bool wait_for_all_occ_init(void)
> return true;
> }
>
> +/* Return nominal pstate to set in each core */
> +static s8 get_nominal_pstate(void)
> +{
> + struct proc_chip *chip;
> + struct occ_pstate_table *occ_data;
> +
> + chip = next_chip(NULL);
> + occ_data = chip_occ_data(chip);
> + return occ_data->pstate_nom;
> +}
> +
> /* Add device tree properties to describe pstates states */
> -/* Retrun nominal pstate to set in each core */
> -static bool add_cpu_pstate_properties(s8 *pstate_nom)
> +static bool add_cpu_pstate_properties(struct dt_node *power_mgt)
> {
> struct proc_chip *chip;
> uint64_t occ_data_area;
> struct occ_pstate_table *occ_data;
> - struct dt_node *power_mgt;
> u8 nr_pstates, nr_cores = 0;
> s8 pmax;
> /* Arrays for device tree */
> @@ -197,12 +207,6 @@ static bool add_cpu_pstate_properties(s8 *pstate_nom)
> return false;
> }
>
> - power_mgt = dt_find_by_path(dt_root, "/ibm,opal/power-mgt");
> - if (!power_mgt) {
> - prerror("OCC: dt node /ibm,opal/power-mgt not found\n");
> - return false;
> - }
> -
> rc = false;
>
> /* Setup arrays for device-tree */
> @@ -267,9 +271,6 @@ static bool add_cpu_pstate_properties(s8 *pstate_nom)
> free(dt_core_max);
> }
>
> - /* Return pstate to set for each core */
> - *pstate_nom = occ_data->pstate_nom;
> -
> for_each_chip(chip) {
> struct dt_node *occ_node;
>
> @@ -461,6 +462,7 @@ done:
> /* Called after OCC init on P8 */
> void occ_pstates_init(void)
> {
> + struct dt_node *power_mgt;
> struct proc_chip *chip;
> struct cpu_thread *c;
> s8 pstate_nom;
> @@ -484,16 +486,21 @@ void occ_pstates_init(void)
> return;
> }
>
> - /*
> - * Check boundary conditions and add device tree nodes
> - * and return nominal pstate to set for the core
> - */
> - if (!add_cpu_pstate_properties(&pstate_nom)) {
> + power_mgt = dt_find_by_path(dt_root, "/ibm,opal/power-mgt");
> + if (!power_mgt) {
> + prerror("OCC: dt node /ibm,opal/power-mgt not found\n");
> + return;
> + }
> +
> + /* Check boundary conditions and add device tree nodes */
> + if (!add_cpu_pstate_properties(power_mgt)) {
> log_simple_error(&e_info(OPAL_RC_OCC_PSTATE_INIT),
> "Skiping core cpufreq init due to OCC error\n");
> return;
> }
>
> + /* Get nominal pstate to set for the core */
> + pstate_nom = get_nominal_pstate();
> /* Setup host based pstates and set nominal frequency */
> for_each_chip(chip) {
> for_each_available_core_in_chip(c, chip->id) {
> @@ -929,4 +936,50 @@ void occ_fsp_init(void)
> fsp_register_client(&fsp_occ_client, FSP_MCLASS_OCC);
> }
>
> +int opal_get_dynamic_pstate_update(void *buff, uint64_t len)
> +{
> + struct dt_node *new_dt_root, *power_mgt;
> + void *fdt;
> + int ret;
> +
> + if (len > DEVICE_TREE_MAX_SIZE) {
> + prerror("OCC: Invalid DT size %lld\n", len);
> + return OPAL_PARAMETER;
> + }
> +
> + last_phandle = 0;
> + new_dt_root = dt_new_root("");
> + if (!new_dt_root) {
> + prerror("OCC: Cannote create new_dt_root\n");
> + return OPAL_NO_MEM;
> + }
>
> + power_mgt = dt_new(new_dt_root, "power-mgt");
> + if (!power_mgt) {
> + prerror("OCC: Cannot create dt node /power-mgt\n");
> + ret = OPAL_NO_MEM;
> + goto free_dt_root;
> + }
> +
> + if (!add_cpu_pstate_properties(power_mgt)) {
> + prerror("OCC: Pstates reinitialization failed\n");
> + ret = OPAL_INTERNAL_ERROR;
> + goto free_dt_root;
> + }
> +
> + fdt = create_dtb(new_dt_root);
> + if (!fdt) {
> + prerror("OCC: DTB creation failed\n");
> + ret = OPAL_INTERNAL_ERROR;
> + goto free_dt_root;
> + }
> +
> + ret = fdt_open_into(fdt, buff, fdt_totalsize(fdt));
> + if (ret)
> + prerror("fdt_move failed %d\n", ret);
> +
> + free(fdt);
> +free_dt_root:
> + dt_free(new_dt_root);
> + return ret;
> +}
> diff --git a/include/opal-api.h b/include/opal-api.h
> index 369aa93..2727fa6 100644
> --- a/include/opal-api.h
> +++ b/include/opal-api.h
> @@ -163,7 +163,8 @@
> #define OPAL_LEDS_SET_INDICATOR 115
> #define OPAL_CEC_REBOOT2 116
> #define OPAL_CONSOLE_FLUSH 117
> -#define OPAL_LAST 117
> +#define OPAL_GET_DYNAMIC_UPDATE 118
> +#define OPAL_LAST 118
>
> /* Device tree flags */
>
> @@ -980,6 +981,13 @@ enum {
> OPAL_REBOOT_PLATFORM_ERROR,
> };
>
> +enum opal_update_type {
> + OPAL_UPDATE_TYPE_PSTATES,
> + OPAL_UPDATE_TYPE_MAX
> +};
> +
> +extern int opal_get_dynamic_pstate_update(void *buff, uint64_t len);
> +
> #endif /* __ASSEMBLY__ */
>
> #endif /* __OPAL_API_H */
>
More information about the Skiboot
mailing list