Skip to content

Commit

Permalink
prd: Implement generic FSP - HBRT interface
Browse files Browse the repository at this point in the history
This patch implements generic interface to pass data from FSP to HBRT during
runtime (FSP -> OPAL -> opal-prd -> HBRT).

OPAL gets notification from FSP for new HBRT messages. We will convert MBOX
message to firmware_notify format and send it to HBRT.

Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
  • Loading branch information
Vasant Hegde authored and stewartsmith committed Jun 3, 2019
1 parent fb702bf commit eb86b14
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 2 deletions.
62 changes: 62 additions & 0 deletions core/hostservices.c
Original file line number Diff line number Diff line change
Expand Up @@ -879,3 +879,65 @@ int hservice_send_hbrt_msg(void *data, u64 dsize)
fsp_tce_unmap(PSI_DMA_HBRT_FSP_MSG, PSI_DMA_HBRT_FSP_MSG_SIZE);
return rc;
}

void hservice_hbrt_msg_response(uint32_t rc)
{
struct fsp_msg *resp;

resp = fsp_mkmsg(FSP_RSP_FSP_TO_HBRT | (uint8_t)rc, 0);
if (!resp) {
prlog(PR_DEBUG,
"HBRT: Failed to allocate FSP - HBRT response message\n");
return;
}

if (fsp_queue_msg(resp, fsp_freemsg)) {
prlog(PR_DEBUG,
"HBRT: Failed to send FSP - HBRT response message\n");
fsp_freemsg(resp);
return;
}
}

/* FSP sends HBRT notification message. Pass this message to HBRT */
static bool hservice_hbrt_msg_notify(uint32_t cmd_sub_mod, struct fsp_msg *msg)
{
u32 tce_token, len;
void *buf;

if (cmd_sub_mod != FSP_CMD_FSP_TO_HBRT)
return false;

prlog(PR_TRACE, "HBRT: FSP - HBRT message generated\n");

tce_token = msg->data.words[1];
len = msg->data.words[2];
buf = fsp_inbound_buf_from_tce(tce_token);
if (!buf) {
prlog(PR_DEBUG, "HBRT: Invalid inbound data\n");
hservice_hbrt_msg_response(FSP_STATUS_INVALID_DATA);
return true;
}

if (prd_hbrt_fsp_msg_notify(buf, len))
hservice_hbrt_msg_response(FSP_STATUS_GENERIC_FAILURE);

return true;
}

static struct fsp_client fsp_hbrt_msg_client = {
.message = hservice_hbrt_msg_notify,
};

/* Register for FSP 0xF2 class messages */
void hservice_fsp_init(void)
{
if (proc_gen < proc_gen_p9)
return;

if (!fsp_present())
return;

/* Register for Class F2 */
fsp_register_client(&fsp_hbrt_msg_client, FSP_MCLASS_HBRT);
}
2 changes: 2 additions & 0 deletions hw/fsp/fsp.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ static struct fsp_cmdclass fsp_cmdclass[FSP_MCLASS_LAST - FSP_MCLASS_FIRST + 1]
DEF_CLASS(FSP_MCLASS_DIAG, 16),
DEF_CLASS(FSP_MCLASS_PCIE_LINK_TOPO, 16),
DEF_CLASS(FSP_MCLASS_OCC, 16),
DEF_CLASS(FSP_MCLASS_TRUSTED_BOOT, 2),
DEF_CLASS(FSP_MCLASS_HBRT, 2),
};

static void fsp_trace_msg(struct fsp_msg *msg, u8 dir __unused)
Expand Down
77 changes: 76 additions & 1 deletion hw/prd.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ static uint8_t _prd_msg_buf[sizeof(struct opal_prd_msg) +
sizeof(struct prd_fw_msg)];
static struct opal_prd_msg *prd_msg = (struct opal_prd_msg *)&_prd_msg_buf;
static struct opal_prd_msg *prd_msg_fsp_req;
static struct opal_prd_msg *prd_msg_fsp_notify;
static bool prd_msg_inuse, prd_active;
static struct dt_node *prd_node;
static bool prd_enabled = false;
Expand Down Expand Up @@ -82,10 +83,11 @@ static uint64_t prd_ipoll_mask;

static void send_next_pending_event(void);

static void prd_msg_consumed(void *data, int status __unused)
static void prd_msg_consumed(void *data, int status)
{
struct opal_prd_msg *msg = data;
uint32_t proc;
int notify_status = OPAL_SUCCESS;
uint8_t event = 0;

lock(&events_lock);
Expand Down Expand Up @@ -118,6 +120,18 @@ static void prd_msg_consumed(void *data, int status __unused)
prd_msg_fsp_req = NULL;
}
break;
case OPAL_PRD_MSG_TYPE_FIRMWARE_NOTIFY:
if (prd_msg_fsp_notify) {
free(prd_msg_fsp_notify);
prd_msg_fsp_notify = NULL;
}
if (status != 0) {
prlog(PR_DEBUG,
"PRD: Failed to send FSP -> HBRT message\n");
notify_status = FSP_STATUS_GENERIC_FAILURE;
}
hservice_hbrt_msg_response(notify_status);
break;
case OPAL_PRD_MSG_TYPE_SBE_PASSTHROUGH:
proc = msg->sbe_passthrough.chip;
event = EVENT_SBE_PASSTHROUGH;
Expand Down Expand Up @@ -356,6 +370,67 @@ void prd_fw_resp_fsp_response(int status)
unlock(&events_lock);
}

int prd_hbrt_fsp_msg_notify(void *data, u32 dsize)
{
int size;
int rc = FSP_STATUS_GENERIC_FAILURE;
enum opal_msg_type msg_type = OPAL_MSG_PRD2;

if (!prd_enabled || !prd_active) {
prlog(PR_NOTICE, "PRD: PRD daemon is not ready\n");
return rc;
}

/* Calculate prd message size */
size = sizeof(prd_msg->hdr) + sizeof(prd_msg->token) +
sizeof(prd_msg->fw_notify) + dsize;

if (size > OPAL_PRD_MSG_SIZE_MAX) {
prlog(PR_DEBUG, "PRD: FSP - HBRT notify message size (0x%x)"
" is bigger than prd interface can handle\n", size);
return rc;
}

lock(&events_lock);

/* FSP - HBRT messages are serialized */
if (prd_msg_fsp_notify) {
prlog(PR_DEBUG, "PRD: FSP - HBRT notify message is busy\n");
goto unlock_events;
}

/* Handle message allocation */
prd_msg_fsp_notify = zalloc(size);
if (!prd_msg_fsp_notify) {
prlog(PR_DEBUG,
"PRD: %s: Failed to allocate memory.\n", __func__);
goto unlock_events;
}

prd_msg_fsp_notify->hdr.type = OPAL_PRD_MSG_TYPE_FIRMWARE_NOTIFY;
prd_msg_fsp_notify->hdr.size = cpu_to_be16(size);
prd_msg_fsp_notify->token = 0;
prd_msg_fsp_notify->fw_notify.len = cpu_to_be64(dsize);
memcpy(&(prd_msg_fsp_notify->fw_notify.data), data, dsize);

/*
* If prd message size is <= OPAL_MSG_FIXED_PARAMS_SIZE then use
* OPAL_MSG_PRD to pass data to kernel. So that it works fine on
* older kernel (which does not support OPAL_MSG_PRD2).
*/
if (prd_msg_fsp_notify->hdr.size < OPAL_MSG_FIXED_PARAMS_SIZE)
msg_type = OPAL_MSG_PRD;

rc = _opal_queue_msg(msg_type, prd_msg_fsp_notify,
prd_msg_consumed, size, prd_msg_fsp_notify);
if (!rc)
prd_msg_inuse = true;

unlock_events:
unlock(&events_lock);
return rc;
}

/* incoming message handlers */
static int prd_msg_handle_attn_ack(struct opal_prd_msg *msg)
{
Expand Down
6 changes: 5 additions & 1 deletion include/fsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,9 @@
#define FSP_MCLASS_DIAG 0xee
#define FSP_MCLASS_PCIE_LINK_TOPO 0xef
#define FSP_MCLASS_OCC 0xf0
#define FSP_MCLASS_LAST 0xf0
#define FSP_MCLASS_TRUSTED_BOOT 0xf1
#define FSP_MCLASS_HBRT 0xf2
#define FSP_MCLASS_LAST 0xf2

/*
* Commands are provided in rxxyyzz form where:
Expand Down Expand Up @@ -584,6 +586,8 @@
* Class F2
*/
#define FSP_CMD_HBRT_TO_FSP 0x1f20100 /* HV->FSP: HBRT message */
#define FSP_CMD_FSP_TO_HBRT 0x0f20200 /* FSP->HV: HBRT message */
#define FSP_RSP_FSP_TO_HBRT 0x0f28200 /* HV->FSP: HBRT message */


/*
Expand Down
2 changes: 2 additions & 0 deletions include/hostservices.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,7 @@ int hservice_wakeup(uint32_t i_core, uint32_t i_mode);
int fsp_occ_reset_status(u64 chipid, s64 status);
int fsp_occ_load_start_status(u64 chipid, s64 status);
int hservice_send_hbrt_msg(void *data, u64 dsize);
void hservice_hbrt_msg_response(uint32_t rc);
void hservice_fsp_init(void);

#endif /* __HOSTSERVICES_H */
1 change: 1 addition & 0 deletions include/skiboot.h
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ extern void prd_register_reserved_memory(void);
extern void prd_fsp_occ_reset(uint32_t proc);
extern void prd_fsp_occ_load_start(u32 proc);
extern void prd_fw_resp_fsp_response(int status);
extern int prd_hbrt_fsp_msg_notify(void *data, u32 dsize);

/* Flatten device-tree */
extern void *create_dtb(const struct dt_node *root, bool exclusive);
Expand Down
1 change: 1 addition & 0 deletions platforms/ibm-fsp/zz.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ static uint32_t ibm_fsp_occ_timeout(void)
static void zz_init(void)
{
ibm_fsp_init();
hservice_fsp_init();
}

DECLARE_PLATFORM(zz) = {
Expand Down

0 comments on commit eb86b14

Please sign in to comment.