aboutsummaryrefslogtreecommitdiff
path: root/hw/prd.c
diff options
context:
space:
mode:
authorVasant Hegde <hegdevasant@linux.vnet.ibm.com>2019-10-22 16:58:30 +0530
committerOliver O'Halloran <oohall@gmail.com>2019-11-05 19:42:25 +1100
commit790a604e37206569506e3552dbf6b583656c7ab1 (patch)
tree79d59ac214a8f13661671c18f128f15bcc8ad07e /hw/prd.c
parentf15577959fc68652c910c4c5aa09876babc5f993 (diff)
downloadskiboot-790a604e37206569506e3552dbf6b583656c7ab1.zip
skiboot-790a604e37206569506e3552dbf6b583656c7ab1.tar.gz
skiboot-790a604e37206569506e3552dbf6b583656c7ab1.tar.bz2
prd: Fix prd message queuing interface
OPAL_MSG_PRD interface can handle message size <= OPAL_MSG_FIXED_PARAMS_SIZE. But kernel prd driver had a bug where it will not copy partial data to user space. This will create problem as opal-prd daemon tries to read message continuously. Commit 9cae036fa fixed this issue by enhancing opal-prd to allocate bigger message size based on device tree. For backward compatability (new OPAL and old kernel/userspace) lets restrict OPAL_MSG_PRD messaging interface to send upto 32 bytes data. This is fine as most of the messages are less than 32 bytes except FSP - HBRT messages ...which is new feature. Cc: Jeremy Kerr <jk@ozlabs.org> Cc: Vaidyanathan Srinivasan <svaidy@linux.vnet.ibm.com> Signed-off-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com> Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Diffstat (limited to 'hw/prd.c')
-rw-r--r--hw/prd.c46
1 files changed, 20 insertions, 26 deletions
diff --git a/hw/prd.c b/hw/prd.c
index d9198f0..9c4cb1f 100644
--- a/hw/prd.c
+++ b/hw/prd.c
@@ -149,6 +149,22 @@ static void prd_msg_consumed(void *data, int status)
unlock(&events_lock);
}
+/*
+ * OPAL_MSG_PRD interface can handle message size <= OPAL_MSG_FIXED_PARAMS_SIZE.
+ * But kernel prd driver had a bug where it will not copy partial data to user
+ * space. Use OPAL_MSG_PRD interface only if size is <= sizeof(opal_prg_msg).
+ */
+static inline int opal_queue_prd_msg(struct opal_prd_msg *msg)
+{
+ enum opal_msg_type msg_type = OPAL_MSG_PRD2;
+
+ if (be16_to_cpu(msg->hdr.size) <= 0x20)
+ msg_type = OPAL_MSG_PRD;
+
+ return _opal_queue_msg(msg_type, msg, prd_msg_consumed,
+ be16_to_cpu(msg->hdr.size), msg);
+}
+
static int populate_ipoll_msg(struct opal_prd_msg *msg, uint32_t proc)
{
uint64_t ipoll_mask;
@@ -224,8 +240,7 @@ static void send_next_pending_event(void)
* disabled then we shouldn't propagate PRD events to the host.
*/
if (prd_enabled) {
- rc = _opal_queue_msg(OPAL_MSG_PRD, prd_msg, prd_msg_consumed,
- prd_msg->hdr.size, prd_msg);
+ rc = opal_queue_prd_msg(prd_msg);
if (!rc)
prd_msg_inuse = true;
}
@@ -327,7 +342,6 @@ void prd_fw_resp_fsp_response(int status)
uint64_t fw_resp_len_old;
int rc;
uint16_t hdr_size;
- enum opal_msg_type msg_type = OPAL_MSG_PRD2;
lock(&events_lock);
@@ -348,16 +362,7 @@ void prd_fw_resp_fsp_response(int status)
prd_msg_fsp_req->hdr.size = cpu_to_be16(hdr_size);
}
- /*
- * 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_req->hdr.size < OPAL_MSG_FIXED_PARAMS_SIZE)
- msg_type = OPAL_MSG_PRD;
-
- rc = _opal_queue_msg(msg_type, prd_msg_fsp_req, prd_msg_consumed,
- prd_msg_fsp_req->hdr.size, prd_msg_fsp_req);
+ rc = opal_queue_prd_msg(prd_msg_fsp_req);
if (!rc)
prd_msg_inuse = true;
unlock(&events_lock);
@@ -367,7 +372,6 @@ 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: %s: PRD daemon is not ready\n",
@@ -407,16 +411,7 @@ int prd_hbrt_fsp_msg_notify(void *data, u32 dsize)
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);
+ rc = opal_queue_prd_msg(prd_msg_fsp_notify);
if (!rc)
prd_msg_inuse = true;
@@ -625,8 +620,7 @@ static int prd_msg_handle_firmware_req(struct opal_prd_msg *msg)
}
if (!rc) {
- rc = _opal_queue_msg(OPAL_MSG_PRD, prd_msg, prd_msg_consumed,
- prd_msg->hdr.size, prd_msg);
+ rc = opal_queue_prd_msg(prd_msg);
if (rc)
prd_msg_inuse = false;
} else {