[Skiboot] [PATCH] opal-prd: Add support for runtime OCC reset in ZZ
Mahesh Jagannath Salgaonkar
mahesh at linux.vnet.ibm.com
Fri Sep 1 17:12:35 AEST 2017
On 08/31/2017 01:56 PM, Shilpasri G Bhat wrote:
> This patch handles OCC_RESET runtime events in host opal-prd and also
> provides support for calling 'hostinterface->wakeup()' which is
> required for doing the reset operation.
>
> Signed-off-by: Shilpasri G Bhat <shilpa.bhat at linux.vnet.ibm.com>
Patch looks good to me.
Reviewed-by: Mahesh Salgaonkar <mahesh at linux.vnet.ibm.com>
Thanks,
-Mahesh.
> ---
> - This is based on top of
> https://urldefense.proofpoint.com/v2/url?u=https-3A__lists.ozlabs.org_pipermail_skiboot_2017-2DAugust_008585.html&d=DwIGaQ&c=jf_iaSHvJObTbx-siA1ZOg&r=Ai3L2JW-0UCviNlQjlx57cFb6BIPotR3Af4uhUMAl18&m=jdbkUAOfWaC23BaUscD1vtdb8M8P3i8ldTb2DFHAsv8&s=J0KYU3rfdqVey-5Gt6HogvWcW2b9MQWtby4yGhOGkAo&e=
> which handles special wakeup in P9.
>
> core/hostservices.c | 28 +++++++++++++++--------
> external/opal-prd/opal-prd.c | 51 +++++++++++++++++++++++++++++++++++++++++-
> external/opal-prd/thunk.S | 2 +-
> hw/occ.c | 53 +++++++++++++++++++++++++++++++++++++++++++-
> hw/prd.c | 8 +++++++
> include/opal-api.h | 10 +++++++++
> include/skiboot.h | 2 ++
> 7 files changed, 142 insertions(+), 12 deletions(-)
>
> diff --git a/core/hostservices.c b/core/hostservices.c
> index 345c8c0..799b483 100644
> --- a/core/hostservices.c
> +++ b/core/hostservices.c
> @@ -721,17 +721,23 @@ static int hservice_wakeup(uint32_t i_core, uint32_t i_mode)
> struct cpu_thread *cpu;
> int rc = OPAL_SUCCESS;
>
> - /*
> - * Mask out the top nibble of i_core since it may contain
> - * 0x4 (which we use for XSCOM targeting)
> - */
> - i_core &= 0x0fffffff;
> + switch (proc_gen) {
> + case proc_gen_p8:
> + i_core &= SPR_PIR_P8_MASK;
> + i_core <<= 3;
> + break;
> + case proc_gen_p9:
> + i_core &= SPR_PIR_P9_MASK;
> + i_core <<= 2;
> + break;
> + default:
> + return OPAL_UNSUPPORTED;
> + }
>
> /* What do we need to do ? */
> switch(i_mode) {
> case 0: /* Assert special wakeup */
> - /* XXX Assume P8 */
> - cpu = find_cpu_by_pir(i_core << 3);
> + cpu = find_cpu_by_pir(i_core);
> if (!cpu)
> return OPAL_PARAMETER;
> prlog(PR_DEBUG, "HBRT: Special wakeup assert for core 0x%x,"
> @@ -742,8 +748,7 @@ static int hservice_wakeup(uint32_t i_core, uint32_t i_mode)
> cpu->hbrt_spec_wakeup++;
> return rc;
> case 1: /* Deassert special wakeup */
> - /* XXX Assume P8 */
> - cpu = find_cpu_by_pir(i_core << 3);
> + cpu = find_cpu_by_pir(i_core);
> if (!cpu)
> return OPAL_PARAMETER;
> prlog(PR_DEBUG, "HBRT: Special wakeup release for core"
> @@ -774,6 +779,11 @@ static int hservice_wakeup(uint32_t i_core, uint32_t i_mode)
> }
> }
>
> +int core_special_wakeup(u32 core, u32 mode)
> +{
> + return hservice_wakeup(core, mode);
> +}
> +
> static struct host_interfaces hinterface = {
> .interface_version = HOSTBOOT_RUNTIME_INTERFACE_VERSION,
> .puts = hservice_puts,
> diff --git a/external/opal-prd/opal-prd.c b/external/opal-prd/opal-prd.c
> index a09a636..614b4b1 100644
> --- a/external/opal-prd/opal-prd.c
> +++ b/external/opal-prd/opal-prd.c
> @@ -506,6 +506,25 @@ int hservice_i2c_write(uint64_t i_master, uint16_t i_devAddr,
> i_offset, i_length, i_data);
> }
>
> +int hservice_wakeup(u32 core, u32 mode)
> +{
> + int rc;
> + struct opal_prd_msg msg;
> +
> + msg.hdr.type = OPAL_PRD_MSG_TYPE_CORE_SPECIAL_WAKEUP;
> + msg.hdr.size = htobe16(sizeof(msg));
> + msg.spl_wakeup.core = htobe32(core);
> + msg.spl_wakeup.mode = htobe32(mode);
> +
> + rc = write(ctx->fd, &msg, sizeof(msg));
> + if (rc != sizeof(msg)) {
> + pr_log(LOG_ERR, "FW: failed for core %x : %m\n", core);
> + return rc;
> + }
> +
> + return 0;
> +}
> +
> static void ipmi_init(struct opal_prd_ctx *ctx)
> {
> insert_module("ipmi_devintf");
> @@ -1353,9 +1372,24 @@ static int pm_complex_reset(uint64_t chip)
> return rc;
> }
>
> +static bool is_fsp(void)
> +{
> + char *path;
> + int rc;
> +
> + rc = asprintf(&path, "%s/fsps", devicetree_base);
> + if (rc < 0) {
> + pr_log(LOG_ERR, "PRD: error creating '/fsps' path %m");
> + return false;
> + }
> +
> + return access(path, F_OK) ? false : true;
> +}
> +
> static int handle_msg_occ_reset(struct opal_prd_ctx *ctx,
> struct opal_prd_msg *msg)
> {
> + struct opal_prd_msg omsg;
> uint32_t proc;
> int rc;
>
> @@ -1365,7 +1399,22 @@ static int handle_msg_occ_reset(struct opal_prd_ctx *ctx,
>
> rc = pm_complex_reset(proc);
>
> - return rc;
> + if (!is_fsp())
> + return rc;
> +
> + /* Send only for zz */
> + omsg.hdr.type = OPAL_PRD_MSG_TYPE_OCC_RESET_STATUS;
> + omsg.hdr.size = htobe16(sizeof(omsg));
> + omsg.occ_reset_status.chip = htobe64(proc);
> + omsg.occ_reset_status.status = htobe64(rc);
> +
> + rc = write(ctx->fd, &omsg, sizeof(omsg));
> + if (rc != sizeof(omsg)) {
> + pr_log(LOG_ERR, "FW: Failed to send OCC_RESET status message: %m");
> + return rc;
> + }
> +
> + return 0;
> }
>
> static int handle_msg_firmware_notify(struct opal_prd_ctx *ctx,
> diff --git a/external/opal-prd/thunk.S b/external/opal-prd/thunk.S
> index cca5890..ee3d7c3 100644
> --- a/external/opal-prd/thunk.S
> +++ b/external/opal-prd/thunk.S
> @@ -183,7 +183,7 @@ hinterface:
> DISABLED_THUNK(hservice_lid_load)
> DISABLED_THUNK(hservice_lid_unload)
> CALLBACK_THUNK(hservice_get_reserved_mem)
> - DISABLED_THUNK(hservice_wakeup)
> + CALLBACK_THUNK(hservice_wakeup)
> CALLBACK_THUNK(hservice_nanosleep)
> DISABLED_THUNK(hservice_report_occ_failure)
> CALLBACK_THUNK(hservice_clock_gettime)
> diff --git a/hw/occ.c b/hw/occ.c
> index 78c6a6a..a53ac92 100644
> --- a/hw/occ.c
> +++ b/hw/occ.c
> @@ -1837,6 +1837,46 @@ out:
> return rc;
> }
>
> +u32 last_seq_id;
> +
> +int fsp_occ_reset_status(u64 chipid, s64 status)
> +{
> + struct fsp_msg *stat;
> + int rc = OPAL_NO_MEM;
> +
> + if (status == 0) {
> + stat = fsp_mkmsg(FSP_CMD_RESET_OCC_STAT, 2, 0, last_seq_id);
> + if (!stat)
> + return rc;
> +
> + rc = fsp_queue_msg(stat, fsp_freemsg);
> + if (rc) {
> + fsp_freemsg(stat);
> + log_simple_error(&e_info(OPAL_RC_OCC_RESET),
> + "OCC: Error %d queueing FSP OCC RESET STATUS message\n",
> + rc);
> + }
> + } else {
> + struct proc_chip *chip = get_chip(chipid);
> +
> + if (!chip)
> + return OPAL_PARAMETER;
> +
> + stat = fsp_mkmsg(FSP_CMD_RESET_OCC_STAT, 2,
> + 0xfe00 | (chip->pcid & 0xff), last_seq_id);
> + if (!stat)
> + return rc;
> + rc = fsp_queue_msg(stat, fsp_freemsg);
> + if (rc) {
> + fsp_freemsg(stat);
> + log_simple_error(&e_info(OPAL_RC_OCC_RESET),
> + "OCC: Error %d queueing FSP OCC RESET STATUS message\n",
> + rc);
> + }
> + }
> + return rc;
> +}
> +
> static void occ_do_reset(u8 scope, u32 dbob_id, u32 seq_id)
> {
> struct fsp_msg *rsp, *stat;
> @@ -1877,7 +1917,18 @@ static void occ_do_reset(u8 scope, u32 dbob_id, u32 seq_id)
> * FSP will request OCC to left in stopped state.
> */
>
> - rc = host_services_occ_stop();
> + switch (proc_gen) {
> + case proc_gen_p8:
> + rc = host_services_occ_stop();
> + break;
> + case proc_gen_p9:
> + last_seq_id = seq_id;
> + for_each_chip(chip)
> + prd_occ_reset(chip->id);
> + return;
> + default:
> + return;
> + }
>
> /* Handle fallback to preload */
> if (rc == -ENOENT && chip->homer_base) {
> diff --git a/hw/prd.c b/hw/prd.c
> index d076c19..dcda9c8 100644
> --- a/hw/prd.c
> +++ b/hw/prd.c
> @@ -418,6 +418,14 @@ static int64_t opal_prd_msg(struct opal_prd_msg *msg)
> case OPAL_PRD_MSG_TYPE_FIRMWARE_REQUEST:
> rc = prd_msg_handle_firmware_req(msg);
> break;
> + case OPAL_PRD_MSG_TYPE_OCC_RESET_STATUS:
> + rc = fsp_occ_reset_status(msg->occ_reset_status.chip,
> + msg->occ_reset_status.status);
> + break;
> + case OPAL_PRD_MSG_TYPE_CORE_SPECIAL_WAKEUP:
> + rc = core_special_wakeup(msg->spl_wakeup.core,
> + msg->spl_wakeup.mode);
> + break;
> default:
> rc = OPAL_UNSUPPORTED;
> }
> diff --git a/include/opal-api.h b/include/opal-api.h
> index 0ff0db0..2f303f9 100644
> --- a/include/opal-api.h
> +++ b/include/opal-api.h
> @@ -1052,6 +1052,8 @@ enum opal_prd_msg_type {
> OPAL_PRD_MSG_TYPE_FIRMWARE_RESPONSE, /* HBRT <-- OPAL */
> OPAL_PRD_MSG_TYPE_FIRMWARE_NOTIFY, /* HBRT <-- OPAL */
> OPAL_PRD_MSG_TYPE_SBE_PASSTHROUGH, /* HBRT <-- OPAL */
> + OPAL_PRD_MSG_TYPE_OCC_RESET_STATUS, /* HBRT --> OPAL */
> + OPAL_PRD_MSG_TYPE_CORE_SPECIAL_WAKEUP, /* HBRT --> OPAL */
> };
>
> struct opal_prd_msg_header {
> @@ -1099,6 +1101,14 @@ struct opal_prd_msg {
> struct {
> __be64 chip;
> } sbe_passthrough;
> + struct {
> + __be64 chip;
> + __be64 status; /* 0 SUCCESS */
> + } occ_reset_status;
> + struct {
> + __be32 core;
> + __be32 mode;
> + } spl_wakeup;
> };
> };
>
> diff --git a/include/skiboot.h b/include/skiboot.h
> index 4b7d519..5eb9188 100644
> --- a/include/skiboot.h
> +++ b/include/skiboot.h
> @@ -317,4 +317,6 @@ extern int occ_sensor_group_clear(u32 group_hndl, int token);
> extern void occ_add_sensor_groups(struct dt_node *sg, u32 *phandles,
> int nr_phandles, int chipid);
>
> +extern int fsp_occ_reset_status(u64 chipid, s64 status);
> +extern int core_special_wakeup(u32 core, u32 mode);
> #endif /* __SKIBOOT_H */
>
More information about the Skiboot
mailing list