diff mbox series

[V2,1/2] opal-prd: Add support for runtime OCC reset in ZZ

Message ID 1512569822-29803-2-git-send-email-shilpa.bhat@linux.vnet.ibm.com
State Superseded
Headers show
Series Support runtime OCC reset/load in ZZ | expand

Commit Message

Shilpasri G Bhat Dec. 6, 2017, 2:17 p.m. UTC
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@linux.vnet.ibm.com>
---
 core/direct-controls.c       |  27 +++++++++++
 core/hostservices.c          |  46 +++++++++++++++++-
 external/opal-prd/opal-prd.c | 112 +++++++++++++++++++++++++++++++++++++++++++
 external/opal-prd/thunk.S    |   2 +-
 hw/occ.c                     |  51 +++++++++++++++++++-
 hw/prd.c                     |  22 +++++++++
 include/cpu.h                |   1 +
 include/hostservices.h       |   2 +
 include/opal-api.h           |  11 +++++
 include/skiboot.h            |   1 +
 10 files changed, 272 insertions(+), 3 deletions(-)

Comments

Nicholas Piggin Dec. 6, 2017, 3:10 p.m. UTC | #1
On Wed,  6 Dec 2017 19:47:01 +0530
Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com> 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@linux.vnet.ibm.com>
> ---
>  core/direct-controls.c       |  27 +++++++++++
>  core/hostservices.c          |  46 +++++++++++++++++-
>  external/opal-prd/opal-prd.c | 112 +++++++++++++++++++++++++++++++++++++++++++
>  external/opal-prd/thunk.S    |   2 +-
>  hw/occ.c                     |  51 +++++++++++++++++++-
>  hw/prd.c                     |  22 +++++++++
>  include/cpu.h                |   1 +
>  include/hostservices.h       |   2 +
>  include/opal-api.h           |  11 +++++
>  include/skiboot.h            |   1 +
>  10 files changed, 272 insertions(+), 3 deletions(-)
> 
> diff --git a/core/direct-controls.c b/core/direct-controls.c
> index ba3e4d1..39c9a75 100644
> --- a/core/direct-controls.c
> +++ b/core/direct-controls.c
> @@ -554,6 +554,33 @@ int dctl_core_is_gated(struct cpu_thread *t)
>  	return !!(val & P9_CORE_GATED);
>  }
>  
> +int dctl_clear_all_special_wakeup(void)
> +{
> +	struct proc_chip *chip;
> +	struct cpu_thread *c;
> +	int rc;
> +
> +	if (proc_gen != proc_gen_p9)
> +		return OPAL_UNSUPPORTED;
> +
> +	for_each_chip(chip)
> +		for_each_available_core_in_chip(c, chip->id) {
> +			lock(&c->dctl_lock);
> +			if (c->special_wakeup_count) {
> +				rc = p9_core_clear_special_wakeup(c);
> +				if (!rc) {
> +					c->special_wakeup_count = 0;
> +				} else {
> +					unlock(&c->dctl_lock);
> +					return rc;
> +				}
> +			}
> +			unlock(&c->dctl_lock);
> +		}
> +
> +	return OPAL_SUCCESS;
> +}

This seems wrong, because there may be other users of special wakeup
apart from host services.

What are the semantics expected for this? My guess is that it wants
to undo the effect of all previous calls to ->wakeup(). In that case
I think another counter is needed to count hservice wakeups.

Thanks,
Nick
Shilpasri G Bhat Dec. 7, 2017, 4:48 a.m. UTC | #2
Hi,

On 12/06/2017 08:40 PM, Nicholas Piggin wrote:
> On Wed,  6 Dec 2017 19:47:01 +0530
> Shilpasri G Bhat <shilpa.bhat@linux.vnet.ibm.com> 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@linux.vnet.ibm.com>
>> ---
>>  core/direct-controls.c       |  27 +++++++++++
>>  core/hostservices.c          |  46 +++++++++++++++++-
>>  external/opal-prd/opal-prd.c | 112 +++++++++++++++++++++++++++++++++++++++++++
>>  external/opal-prd/thunk.S    |   2 +-
>>  hw/occ.c                     |  51 +++++++++++++++++++-
>>  hw/prd.c                     |  22 +++++++++
>>  include/cpu.h                |   1 +
>>  include/hostservices.h       |   2 +
>>  include/opal-api.h           |  11 +++++
>>  include/skiboot.h            |   1 +
>>  10 files changed, 272 insertions(+), 3 deletions(-)
>>
>> diff --git a/core/direct-controls.c b/core/direct-controls.c
>> index ba3e4d1..39c9a75 100644
>> --- a/core/direct-controls.c
>> +++ b/core/direct-controls.c
>> @@ -554,6 +554,33 @@ int dctl_core_is_gated(struct cpu_thread *t)
>>  	return !!(val & P9_CORE_GATED);
>>  }
>>  
>> +int dctl_clear_all_special_wakeup(void)
>> +{
>> +	struct proc_chip *chip;
>> +	struct cpu_thread *c;
>> +	int rc;
>> +
>> +	if (proc_gen != proc_gen_p9)
>> +		return OPAL_UNSUPPORTED;
>> +
>> +	for_each_chip(chip)
>> +		for_each_available_core_in_chip(c, chip->id) {
>> +			lock(&c->dctl_lock);
>> +			if (c->special_wakeup_count) {
>> +				rc = p9_core_clear_special_wakeup(c);
>> +				if (!rc) {
>> +					c->special_wakeup_count = 0;
>> +				} else {
>> +					unlock(&c->dctl_lock);
>> +					return rc;
>> +				}
>> +			}
>> +			unlock(&c->dctl_lock);
>> +		}
>> +
>> +	return OPAL_SUCCESS;
>> +}
> 
> This seems wrong, because there may be other users of special wakeup
> apart from host services.
> 
> What are the semantics expected for this? My guess is that it wants
> to undo the effect of all previous calls to ->wakeup(). In that case
> I think another counter is needed to count hservice wakeups.
> 
> Thanks,
> Nick
> 

Yup agree. There is cpu->hbrt_spec_wakeup counter which is used in P8 to track
the special wakeup. I will use this counter itself for the above case.

Thanks and Regards,
Shilpa
diff mbox series

Patch

diff --git a/core/direct-controls.c b/core/direct-controls.c
index ba3e4d1..39c9a75 100644
--- a/core/direct-controls.c
+++ b/core/direct-controls.c
@@ -554,6 +554,33 @@  int dctl_core_is_gated(struct cpu_thread *t)
 	return !!(val & P9_CORE_GATED);
 }
 
+int dctl_clear_all_special_wakeup(void)
+{
+	struct proc_chip *chip;
+	struct cpu_thread *c;
+	int rc;
+
+	if (proc_gen != proc_gen_p9)
+		return OPAL_UNSUPPORTED;
+
+	for_each_chip(chip)
+		for_each_available_core_in_chip(c, chip->id) {
+			lock(&c->dctl_lock);
+			if (c->special_wakeup_count) {
+				rc = p9_core_clear_special_wakeup(c);
+				if (!rc) {
+					c->special_wakeup_count = 0;
+				} else {
+					unlock(&c->dctl_lock);
+					return rc;
+				}
+			}
+			unlock(&c->dctl_lock);
+		}
+
+	return OPAL_SUCCESS;
+}
+
 static int dctl_stop(struct cpu_thread *t)
 {
 	struct cpu_thread *c = t->primary;
diff --git a/core/hostservices.c b/core/hostservices.c
index dd8cae2..e8c4ce3 100644
--- a/core/hostservices.c
+++ b/core/hostservices.c
@@ -697,7 +697,7 @@  static int hservice_clr_special_wakeup(struct cpu_thread *cpu)
 	return 0;
 }
 
-static int hservice_wakeup(uint32_t i_core, uint32_t i_mode)
+static int hservice_wakeup_p8(uint32_t i_core, uint32_t i_mode)
 {
 	struct cpu_thread *cpu;
 	int rc = OPAL_SUCCESS;
@@ -755,6 +755,50 @@  static int hservice_wakeup(uint32_t i_core, uint32_t i_mode)
 	}
 }
 
+static int hservice_wakeup_p9(u32 core, u32 mode)
+{
+	struct cpu_thread *cpu;
+
+	core &= SPR_PIR_P9_MASK;
+	core <<= 2;
+
+	switch (mode) {
+	case 0: /* Assert special wakeup */
+		cpu = find_cpu_by_pir(core);
+		if (!cpu)
+			return OPAL_PARAMETER;
+		prlog(PR_DEBUG, "HBRT: Special wakeup assert for core 0x%x,"
+		      " count=%d\n", core, cpu->special_wakeup_count);
+		return dctl_set_special_wakeup(cpu);
+	case 1: /* Deassert special wakeup */
+		cpu = find_cpu_by_pir(core);
+		if (!cpu)
+			return OPAL_PARAMETER;
+		prlog(PR_DEBUG, "HBRT: Special wakeup release for core"
+		      " 0x%x, count=%d\n", core, cpu->special_wakeup_count);
+		return dctl_clear_special_wakeup(cpu);
+	case 2: /* Clear all special wakeups */
+		prlog(PR_DEBUG, "HBRT: Special wakeup release for all cores\n");
+		return dctl_clear_all_special_wakeup();
+	default:
+		return OPAL_PARAMETER;
+	}
+}
+
+int hservice_wakeup(u32 core, u32 mode)
+{
+	switch (proc_gen) {
+	case proc_gen_p8:
+		return hservice_wakeup_p8(core, mode);
+	case proc_gen_p9:
+		return hservice_wakeup_p9(core, mode);
+	default:
+		break;
+	}
+
+	return OPAL_UNSUPPORTED;
+}
+
 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 b15063f..fb573e4 100644
--- a/external/opal-prd/opal-prd.c
+++ b/external/opal-prd/opal-prd.c
@@ -163,6 +163,9 @@  struct func_desc {
 	void *toc;
 } hbrt_entry;
 
+static int nr_chips;
+static u64 chips[256];
+
 static int read_prd_msg(struct opal_prd_ctx *ctx);
 
 static struct prd_range *find_range(const char *name, uint32_t instance)
@@ -524,6 +527,24 @@  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)
+{
+	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);
+
+	if (write(ctx->fd, &msg, sizeof(msg)) != sizeof(msg)) {
+		pr_log(LOG_ERR, "FW: Failed to send CORE_SPECIAL_WAKEUP msg %x : %m\n",
+		       core);
+		return -1;
+	}
+
+	return 0;
+}
+
 static void ipmi_init(struct opal_prd_ctx *ctx)
 {
 	insert_module("ipmi_devintf");
@@ -1173,6 +1194,52 @@  static void print_ranges(struct opal_prd_ctx *ctx)
 	}
 }
 
+static int chip_init(void)
+{
+	struct dirent *dirent;
+	char *path;
+	DIR *dir;
+	__be32 *chipid;
+	void *buf;
+	int rc, len, i;
+
+	dir = opendir(devicetree_base);
+	if (!dir) {
+		pr_log(LOG_ERR, "FW: Can't open %s", devicetree_base);
+		return  -1;
+	}
+
+	for (;;) {
+		dirent = readdir(dir);
+		if (!dirent)
+			break;
+
+		if (strncmp("xscom", dirent->d_name, 5))
+			continue;
+
+		rc = asprintf(&path, "%s/%s/ibm,chip-id", devicetree_base,
+			      dirent->d_name);
+		if (rc < 0) {
+			pr_log(LOG_ERR, "FW: Failed to create chip-id path");
+			return -1;
+		}
+
+		rc = open_and_read(path, &buf, &len);
+		if (rc) {
+			pr_log(LOG_ERR, "FW; Failed to read chipid");
+			return -1;
+		}
+		chipid = buf;
+		chips[nr_chips++] = be32toh(*chipid);
+	}
+
+	pr_log(LOG_DEBUG, "FW: Chip init");
+	for (i = 0; i < nr_chips; i++)
+		pr_log(LOG_DEBUG, "FW: Chip 0x%lx", chips[i]);
+
+	return 0;
+}
+
 static int prd_init_ranges(struct opal_prd_ctx *ctx)
 {
 	struct dirent *dirent;
@@ -1293,6 +1360,10 @@  static int prd_init(struct opal_prd_ctx *ctx)
 		return -1;
 	}
 
+	rc = chip_init();
+	if (rc)
+		pr_log(LOG_ERR, "FW: Failed to initialize chip IDs");
+
 	return 0;
 }
 
@@ -1436,6 +1507,41 @@  static int handle_msg_sbe_passthrough(struct opal_prd_ctx *ctx,
 	return rc;
 }
 
+static int handle_msg_fsp_occ_reset(struct opal_prd_msg *msg)
+{
+	struct opal_prd_msg omsg;
+	int rc = -1, i;
+
+	pr_debug("FW: FSP requested OCC reset");
+
+	if (!hservice_runtime->reset_pm_complex) {
+		pr_log_nocall("reset_pm_complex");
+		return rc;
+	}
+
+	for (i = 0; i < nr_chips; i++) {
+		pr_debug("PM: calling pm_complex_reset(0x%lx)", chips[i]);
+		rc = call_reset_pm_complex(chips[i]);
+		if (rc) {
+			pr_log(LOG_ERR, "PM: Failed pm_complex_reset(0x%lx) %m",
+			       chips[i]);
+			break;
+		}
+	}
+
+	omsg.hdr.type = OPAL_PRD_MSG_TYPE_FSP_OCC_RESET_STATUS;
+	omsg.hdr.size = htobe16(sizeof(omsg));
+	omsg.fsp_occ_reset_status.chip = msg->occ_reset.chip;
+	omsg.fsp_occ_reset_status.status = htobe64(rc);
+
+	if (write(ctx->fd, &omsg, sizeof(omsg)) != sizeof(omsg)) {
+		pr_log(LOG_ERR, "FW: Failed to send FSP_OCC_RESET_STATUS msg: %m");
+		return -1;
+	}
+
+	return rc;
+}
+
 static int handle_prd_msg(struct opal_prd_ctx *ctx, struct opal_prd_msg *msg)
 {
 	int rc = -1;
@@ -1456,6 +1562,9 @@  static int handle_prd_msg(struct opal_prd_ctx *ctx, struct opal_prd_msg *msg)
 	case OPAL_PRD_MSG_TYPE_SBE_PASSTHROUGH:
 		rc = handle_msg_sbe_passthrough(ctx, msg);
 		break;
+	case OPAL_PRD_MSG_TYPE_FSP_OCC_RESET:
+		rc = handle_msg_fsp_occ_reset(msg);
+		break;
 	default:
 		pr_log(LOG_WARNING, "Invalid incoming message type 0x%x",
 				msg->hdr.type);
@@ -1988,6 +2097,9 @@  static int run_prd_daemon(struct opal_prd_ctx *ctx)
 		hinterface.pnor_write = NULL;
 	}
 
+	if (!is_fsp_system())
+		hinterface.wakeup = NULL;
+
 	ipmi_init(ctx);
 
 	pr_debug("HBRT: calling hservices_init");
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 0ffa3e8..3507d5f 100644
--- a/hw/occ.c
+++ b/hw/occ.c
@@ -1843,6 +1843,44 @@  out:
 	return rc;
 }
 
+static u32 last_seq_id;
+
+int fsp_occ_reset_status(u64 chipid, s64 status)
+{
+	struct fsp_msg *stat;
+	int rc = OPAL_NO_MEM;
+	int status_word = 0;
+
+	prlog(PR_INFO, "HBRT: OCC stop() completed with %lld\n", status);
+
+	if (status) {
+		struct proc_chip *chip = get_chip(chipid);
+
+		if (!chip)
+			return OPAL_PARAMETER;
+
+		status_word = 0xfe00 | (chip->pcid & 0xff);
+		log_simple_error(&e_info(OPAL_RC_OCC_RESET),
+				 "OCC: Error %lld in OCC reset of chip %lld\n",
+				 status, chipid);
+	} else {
+		occ_msg_queue_occ_reset();
+	}
+
+	stat = fsp_mkmsg(FSP_CMD_RESET_OCC_STAT, 2, status_word, 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;
@@ -1883,7 +1921,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;
+		chip = next_chip(NULL);
+		prd_fsp_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 c00e10a..5f9758d 100644
--- a/hw/prd.c
+++ b/hw/prd.c
@@ -23,12 +23,14 @@ 
 #include <fsp.h>
 #include <mem_region.h>
 #include <prd-fw-msg.h>
+#include <hostservices.h>
 
 enum events {
 	EVENT_ATTN	= 1 << 0,
 	EVENT_OCC_ERROR	= 1 << 1,
 	EVENT_OCC_RESET	= 1 << 2,
 	EVENT_SBE_PASSTHROUGH = 1 << 3,
+	EVENT_FSP_OCC_RESET = 1 << 4,
 };
 
 static uint8_t events[MAX_CHIPS];
@@ -114,6 +116,10 @@  static void prd_msg_consumed(void *data)
 		proc = msg->sbe_passthrough.chip;
 		event = EVENT_SBE_PASSTHROUGH;
 		break;
+	case OPAL_PRD_MSG_TYPE_FSP_OCC_RESET:
+		proc = msg->occ_reset.chip;
+		event = EVENT_FSP_OCC_RESET;
+		break;
 	default:
 		prlog(PR_ERR, "PRD: invalid msg consumed, type: 0x%x\n",
 				msg->hdr.type);
@@ -188,6 +194,9 @@  static void send_next_pending_event(void)
 	} else if (event & EVENT_SBE_PASSTHROUGH) {
 		prd_msg->hdr.type = OPAL_PRD_MSG_TYPE_SBE_PASSTHROUGH;
 		prd_msg->sbe_passthrough.chip = proc;
+	} else if (event & EVENT_FSP_OCC_RESET) {
+		prd_msg->hdr.type = OPAL_PRD_MSG_TYPE_FSP_OCC_RESET;
+		prd_msg->occ_reset.chip = proc;
 	}
 
 	/*
@@ -274,6 +283,11 @@  void prd_occ_reset(uint32_t proc)
 	prd_event(proc, EVENT_OCC_RESET);
 }
 
+void prd_fsp_occ_reset(uint32_t proc)
+{
+	prd_event(proc, EVENT_FSP_OCC_RESET);
+}
+
 void prd_sbe_passthrough(uint32_t proc)
 {
 	prd_event(proc, EVENT_SBE_PASSTHROUGH);
@@ -430,6 +444,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_FSP_OCC_RESET_STATUS:
+		rc = fsp_occ_reset_status(msg->fsp_occ_reset_status.chip,
+					  msg->fsp_occ_reset_status.status);
+		break;
+	case OPAL_PRD_MSG_TYPE_CORE_SPECIAL_WAKEUP:
+		rc = hservice_wakeup(msg->spl_wakeup.core,
+				     msg->spl_wakeup.mode);
+		break;
 	default:
 		rc = OPAL_UNSUPPORTED;
 	}
diff --git a/include/cpu.h b/include/cpu.h
index 2804105..47b1555 100644
--- a/include/cpu.h
+++ b/include/cpu.h
@@ -310,5 +310,6 @@  extern void cpu_fast_reboot_complete(void);
 int dctl_set_special_wakeup(struct cpu_thread *t);
 int dctl_clear_special_wakeup(struct cpu_thread *t);
 int dctl_core_is_gated(struct cpu_thread *t);
+int dctl_clear_all_special_wakeup(void);
 
 #endif /* __CPU_H */
diff --git a/include/hostservices.h b/include/hostservices.h
index 62ef04b..cca3a3a 100644
--- a/include/hostservices.h
+++ b/include/hostservices.h
@@ -39,5 +39,7 @@  void host_services_occ_base_setup(void);
 int find_master_and_slave_occ(uint64_t **master, uint64_t **slave,
 			      int *nr_masters, int *nr_slaves);
 int hservice_send_error_log(uint32_t plid, uint32_t dsize, void *data);
+int hservice_wakeup(u32 core, u32 mode);
+int fsp_occ_reset_status(u64 chipid, s64 status);
 
 #endif /* __HOSTSERVICES_H */
diff --git a/include/opal-api.h b/include/opal-api.h
index 1c1b9cc..ef32f65 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -1061,6 +1061,9 @@  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_FSP_OCC_RESET, /* HBRT <-- OPAL */
+	OPAL_PRD_MSG_TYPE_FSP_OCC_RESET_STATUS, /* HBRT --> OPAL */
+	OPAL_PRD_MSG_TYPE_CORE_SPECIAL_WAKEUP, /* HBRT --> OPAL */
 };
 
 struct opal_prd_msg_header {
@@ -1108,6 +1111,14 @@  struct opal_prd_msg {
 		struct {
 			__be64	chip;
 		} sbe_passthrough;
+		struct {
+			__be64 chip;
+			__be64 status; /* 0 SUCCESS */
+		} fsp_occ_reset_status;
+		struct {
+			__be32 core;
+			__be32 mode;
+		} spl_wakeup;
 	};
 };
 
diff --git a/include/skiboot.h b/include/skiboot.h
index db91325..795ee4f 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -293,6 +293,7 @@  extern void prd_occ_reset(uint32_t proc);
 extern void prd_sbe_passthrough(uint32_t proc);
 extern void prd_init(void);
 extern void prd_register_reserved_memory(void);
+extern void prd_fsp_occ_reset(uint32_t proc);
 
 /* Flatten device-tree */
 extern void *create_dtb(const struct dt_node *root, bool exclusive);