From patchwork Thu May 25 07:05:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeremy Kerr X-Patchwork-Id: 766865 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3wYL2D67lzz9s3T for ; Thu, 25 May 2017 17:08:04 +1000 (AEST) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3wYL2D5Nf7zDqn6 for ; Thu, 25 May 2017 17:08:04 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from ozlabs.org (ozlabs.org [IPv6:2401:3900:2:1::2]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3wYL0f6DMdzDqhV for ; Thu, 25 May 2017 17:06:42 +1000 (AEST) Received: by ozlabs.org (Postfix, from userid 1023) id 3wYL0f3N4Hz9sNH; Thu, 25 May 2017 17:06:42 +1000 (AEST) From: Jeremy Kerr To: skiboot@lists.ozlabs.org Date: Thu, 25 May 2017 17:05:54 +1000 Message-Id: <1495695955-30718-12-git-send-email-jk@ozlabs.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1495695955-30718-1-git-send-email-jk@ozlabs.org> References: <1495695955-30718-1-git-send-email-jk@ozlabs.org> Subject: [Skiboot] [PATCH RFC 11/12] prd: Implement firmware side of opaque PRD channel X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Dan Crowell MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" This change introduces the firmware side of the opaque HBRT <--> OPAL message channel. We define a base message format to be shared with HBRT (in include/prd-fw-msg.h), and allow firmware requests and responses to be sent over this channel. We don't currently have any notifications defined, so have nothing to do for firmware_notify() at this stage. Signed-off-by: Jeremy Kerr CC: Daniel M Crowell --- hw/prd.c | 88 +++++++++++++++++++++++++++++++++++++++++++++------- include/prd-fw-msg.h | 37 ++++++++++++++++++++++ 2 files changed, 113 insertions(+), 12 deletions(-) create mode 100644 include/prd-fw-msg.h diff --git a/hw/prd.c b/hw/prd.c index 0db7e6b..da38e3a 100644 --- a/hw/prd.c +++ b/hw/prd.c @@ -22,6 +22,7 @@ #include #include #include +#include enum events { EVENT_ATTN = 1 << 0, @@ -31,7 +32,9 @@ enum events { static uint8_t events[MAX_CHIPS]; static uint64_t ipoll_status[MAX_CHIPS]; -static struct opal_prd_msg prd_msg; +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 bool prd_msg_inuse, prd_active; static struct dt_node *prd_node; static bool prd_enabled = false; @@ -104,6 +107,8 @@ static void prd_msg_consumed(void *data) proc = msg->occ_reset.chip; event = EVENT_OCC_RESET; break; + case OPAL_PRD_MSG_TYPE_FIRMWARE_RESPONSE: + break; default: prlog(PR_ERR, "PRD: invalid msg consumed, type: 0x%x\n", msg->hdr.type); @@ -162,18 +167,18 @@ static void send_next_pending_event(void) return; prd_msg_inuse = true; - prd_msg.token = 0; - prd_msg.hdr.size = sizeof(prd_msg); + prd_msg->token = 0; + prd_msg->hdr.size = sizeof(*prd_msg); if (event & EVENT_ATTN) { - prd_msg.hdr.type = OPAL_PRD_MSG_TYPE_ATTN; - populate_ipoll_msg(&prd_msg, proc); + prd_msg->hdr.type = OPAL_PRD_MSG_TYPE_ATTN; + populate_ipoll_msg(prd_msg, proc); } else if (event & EVENT_OCC_ERROR) { - prd_msg.hdr.type = OPAL_PRD_MSG_TYPE_OCC_ERROR; - prd_msg.occ_error.chip = proc; + prd_msg->hdr.type = OPAL_PRD_MSG_TYPE_OCC_ERROR; + prd_msg->occ_error.chip = proc; } else if (event & EVENT_OCC_RESET) { - prd_msg.hdr.type = OPAL_PRD_MSG_TYPE_OCC_RESET; - prd_msg.occ_reset.chip = proc; + prd_msg->hdr.type = OPAL_PRD_MSG_TYPE_OCC_RESET; + prd_msg->occ_reset.chip = proc; occ_msg_queue_occ_reset(); } @@ -182,8 +187,8 @@ static void send_next_pending_event(void) * disabled then we shouldn't propagate PRD events to the host. */ if (prd_enabled) - _opal_queue_msg(OPAL_MSG_PRD, &prd_msg, prd_msg_consumed, 4, - (uint64_t *) &prd_msg); + _opal_queue_msg(OPAL_MSG_PRD, prd_msg, prd_msg_consumed, 4, + (uint64_t *)prd_msg); } static void __prd_event(uint32_t proc, uint8_t event) @@ -316,6 +321,62 @@ static int prd_msg_handle_fini(void) return OPAL_SUCCESS; } +static int prd_msg_handle_firmware_req(struct opal_prd_msg *msg) +{ + unsigned long fw_req_len, fw_resp_len; + struct prd_fw_msg *fw_req, *fw_resp; + int rc; + + fw_req_len = be64_to_cpu(msg->fw_req.req_len); + fw_resp_len = be64_to_cpu(msg->fw_req.resp_len); + fw_req = (struct prd_fw_msg *)msg->fw_req.data; + + /* do we have a full firmware message? */ + if (fw_req_len < sizeof(struct prd_fw_msg)) + return -EINVAL; + + /* does the total (outer) PRD message len provide enough data for the + * claimed (inner) FW message? + */ + if (msg->hdr.size < fw_req_len + + offsetof(struct opal_prd_msg, fw_req.data)) + return -EINVAL; + + /* is there enough response buffer for a base response? Type-specific + * responses may be larger, but anything less than BASE_SIZE is + * invalid. */ + if (fw_resp_len < PRD_FW_MSG_BASE_SIZE) + return -EINVAL; + + /* prepare a response message. */ + lock(&events_lock); + prd_msg_inuse = true; + prd_msg->token = 0; + prd_msg->hdr.type = OPAL_PRD_MSG_TYPE_FIRMWARE_RESPONSE; + fw_resp = (void *)prd_msg->fw_resp.data; + + switch (be64_to_cpu(fw_req->type)) { + case PRD_FW_MSG_TYPE_REQ_NOP: + fw_resp->type = cpu_to_be64(PRD_FW_MSG_TYPE_RESP_NOP); + prd_msg->fw_resp.len = cpu_to_be64(PRD_FW_MSG_BASE_SIZE); + prd_msg->hdr.size = cpu_to_be16(sizeof(*prd_msg)); + rc = 0; + break; + default: + rc = -ENOSYS; + } + + if (!rc) + rc = _opal_queue_msg(OPAL_MSG_PRD, prd_msg, prd_msg_consumed, 4, + (uint64_t *) prd_msg); + else + prd_msg_inuse = false; + + unlock(&events_lock); + + return rc; +} + /* Entry from the host above */ static int64_t opal_prd_msg(struct opal_prd_msg *msg) { @@ -328,7 +389,7 @@ static int64_t opal_prd_msg(struct opal_prd_msg *msg) msg->hdr.type == OPAL_PRD_MSG_TYPE_FINI) return prd_msg_handle_fini(); - if (msg->hdr.size != sizeof(*msg)) + if (msg->hdr.size < sizeof(*msg)) return OPAL_PARAMETER; switch (msg->hdr.type) { @@ -341,6 +402,9 @@ static int64_t opal_prd_msg(struct opal_prd_msg *msg) case OPAL_PRD_MSG_TYPE_OCC_RESET_NOTIFY: rc = occ_msg_queue_occ_reset(); break; + case OPAL_PRD_MSG_TYPE_FIRMWARE_REQUEST: + rc = prd_msg_handle_firmware_req(msg); + break; default: rc = OPAL_UNSUPPORTED; } diff --git a/include/prd-fw-msg.h b/include/prd-fw-msg.h new file mode 100644 index 0000000..c00405d --- /dev/null +++ b/include/prd-fw-msg.h @@ -0,0 +1,37 @@ +/* Copyright 2017 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef __PRD_FW_MSG_H +#define __PRD_FW_MSG_H + +#include + +/* Messaging structure for the opaque channel between OPAL and HBRT. This + * format is used for the firmware_request and firmware_notify interfaces + */ +enum { + PRD_FW_MSG_TYPE_REQ_NOP = 0, + PRD_FW_MSG_TYPE_RESP_NOP = 1, +}; + +struct prd_fw_msg { + __be64 type; +}; + +#define PRD_FW_MSG_BASE_SIZE sizeof(__be64) + +#endif /* __PRD_FW_MSG_H */