diff options
author | Vasant Hegde <hegdevasant@linux.vnet.ibm.com> | 2019-10-22 16:58:30 +0530 |
---|---|---|
committer | Oliver O'Halloran <oohall@gmail.com> | 2019-11-05 19:42:25 +1100 |
commit | 790a604e37206569506e3552dbf6b583656c7ab1 (patch) | |
tree | 79d59ac214a8f13661671c18f128f15bcc8ad07e /hw/prd.c | |
parent | f15577959fc68652c910c4c5aa09876babc5f993 (diff) | |
download | skiboot-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.c | 46 |
1 files changed, 20 insertions, 26 deletions
@@ -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 { |