From patchwork Thu May 11 16:24:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Lombard X-Patchwork-Id: 1780177 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org (client-ip=112.213.38.117; helo=lists.ozlabs.org; envelope-from=skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=ibm.com header.i=@ibm.com header.a=rsa-sha256 header.s=pp1 header.b=MKiS165b; dkim-atps=neutral Received: from lists.ozlabs.org (lists.ozlabs.org [112.213.38.117]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384)) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4QHHP41R4Pz213w for ; Fri, 12 May 2023 02:27:36 +1000 (AEST) Received: from boromir.ozlabs.org (localhost [IPv6:::1]) by lists.ozlabs.org (Postfix) with ESMTP id 4QHHP40KbMz3fYG for ; Fri, 12 May 2023 02:27:36 +1000 (AEST) Authentication-Results: lists.ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=ibm.com header.i=@ibm.com header.a=rsa-sha256 header.s=pp1 header.b=MKiS165b; dkim-atps=neutral X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=linux.ibm.com (client-ip=148.163.156.1; helo=mx0a-001b2d01.pphosted.com; envelope-from=clombard@linux.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=ibm.com header.i=@ibm.com header.a=rsa-sha256 header.s=pp1 header.b=MKiS165b; dkim-atps=neutral Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 4QHHL16JZlz3fPq for ; Fri, 12 May 2023 02:24:57 +1000 (AEST) Received: from pps.filterd (m0353729.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 34BG8R9b028073 for ; Thu, 11 May 2023 16:24:55 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=from : to : subject : date : message-id : in-reply-to : references : mime-version : content-transfer-encoding; s=pp1; bh=7C2g0LnEueiU9/IMV5I+Fc6lo+o9vxi/jTLZ/u1a0Pg=; b=MKiS165bQfpq2gOWmbo2NTJs2og2caJVL4B7NFSqI4iJZPzrV0gS0e9c4hKIRuj562XR VJ1nT/LWXNSEhmBUwNXUYIbtWi8MqI2J2t6TIZU5pI+otA1/ffUo74IX7V6rgPDWqVR9 WTf/dS/IqJ52qjWZLuRzmh9hclY1C29ulSotDaa+lOTWxM/Y6l04c5HKQrt/YdCiaXHb sos9+xKSxxNyk+5IKrwsqdbLhFYo5x+QNtzJRh+a7GNS+K5fQRJlocX42evpVW8Zo2Iv CAi22n+uOzbyxIsIzEKVkqLDjC0/cDUY+bcuMxYglmRSWo5SgP4DjcXFpARkmy/Fw4lm iA== Received: from ppma04fra.de.ibm.com (6a.4a.5195.ip4.static.sl-reverse.com [149.81.74.106]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3qh2t1aa35-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Thu, 11 May 2023 16:24:54 +0000 Received: from pps.filterd (ppma04fra.de.ibm.com [127.0.0.1]) by ppma04fra.de.ibm.com (8.17.1.19/8.17.1.19) with ESMTP id 34B68SHF008473 for ; Thu, 11 May 2023 16:24:52 GMT Received: from smtprelay03.fra02v.mail.ibm.com ([9.218.2.224]) by ppma04fra.de.ibm.com (PPS) with ESMTPS id 3qf7d1sgj0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Thu, 11 May 2023 16:24:52 +0000 Received: from smtpav06.fra02v.mail.ibm.com (smtpav06.fra02v.mail.ibm.com [10.20.54.105]) by smtprelay03.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 34BGOoPk5112482 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Thu, 11 May 2023 16:24:50 GMT Received: from smtpav06.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5A44420049 for ; Thu, 11 May 2023 16:24:50 +0000 (GMT) Received: from smtpav06.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1D0D220043 for ; Thu, 11 May 2023 16:24:50 +0000 (GMT) Received: from li-ac0ca24c-3330-11b2-a85c-93224c50ad7a.home (unknown [9.179.3.92]) by smtpav06.fra02v.mail.ibm.com (Postfix) with ESMTP for ; Thu, 11 May 2023 16:24:50 +0000 (GMT) From: Christophe Lombard To: skiboot@lists.ozlabs.org Date: Thu, 11 May 2023 18:24:34 +0200 Message-Id: <20230511162446.10457-10-clombard@linux.ibm.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20230511162446.10457-1-clombard@linux.ibm.com> References: <20230511162446.10457-1-clombard@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: Rom_rJLQ4x-7iS-Omq2ZN3LoZxwWnE25 X-Proofpoint-GUID: Rom_rJLQ4x-7iS-Omq2ZN3LoZxwWnE25 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.254,Aquarius:18.0.942,Hydra:6.0.573,FMLib:17.11.170.22 definitions=2023-05-11_13,2023-05-05_01,2023-02-09_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 impostorscore=0 suspectscore=0 clxscore=1015 spamscore=0 lowpriorityscore=0 mlxlogscore=999 priorityscore=1501 phishscore=0 malwarescore=0 mlxscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2304280000 definitions=main-2305110139 Subject: [Skiboot] [PATCH V7 09/21] core/pldm: Implement PLDM requester X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" Implement a way for sending PLDM requests for specific PLDM commands. Send a PLDM request message. Wait for corresponding response message, which once received, is returned to the caller. If there's data available, return success only if data is a PLDM response message that matches instance, pldm_type and command code. Reviewed-by: Abhishek Singh Tomar Signed-off-by: Christophe Lombard --- core/pldm/Makefile.inc | 2 +- core/pldm/pldm-mctp.c | 10 +- core/pldm/pldm-requester.c | 336 +++++++++++++++++++++++++++++++++++++ core/pldm/pldm.h | 9 + include/ast.h | 6 + 5 files changed, 361 insertions(+), 2 deletions(-) create mode 100644 core/pldm/pldm-requester.c diff --git a/core/pldm/Makefile.inc b/core/pldm/Makefile.inc index 9aa72a77..f2328a4b 100644 --- a/core/pldm/Makefile.inc +++ b/core/pldm/Makefile.inc @@ -7,7 +7,7 @@ SUBDIRS += $(PLDM_DIR) CPPFLAGS += -I$(SRC)/pldm/include/ CPPFLAGS += -I$(SRC)/pldm/include/libpldm/oem/ibm/ -PLDM_OBJS = pldm-mctp.o pldm-responder.o +PLDM_OBJS = pldm-mctp.o pldm-responder.o pldm-requester.o PLDM = $(PLDM_DIR)/built-in.a $(PLDM): $(PLDM_OBJS:%=$(PLDM_DIR)/%) diff --git a/core/pldm/pldm-mctp.c b/core/pldm/pldm-mctp.c index 241fd956..cfa6d2fc 100644 --- a/core/pldm/pldm-mctp.c +++ b/core/pldm/pldm-mctp.c @@ -54,6 +54,9 @@ int pldm_mctp_message_rx(uint8_t eid, bool tag_owner, uint8_t msg_tag, } switch (rx->hdrinf.msg_type) { + case PLDM_RESPONSE: + rc = pldm_requester_handle_response(rx); + break; case PLDM_REQUEST: rc = pldm_responder_handle_request(rx); break; @@ -84,8 +87,13 @@ int pldm_mctp_init(void) /* Register mandatory commands we'll respond to */ rc = pldm_responder_init(); - if (rc) + if (rc) { prlog(PR_ERR, "Failed to register mandatory commands\n"); + goto out; + } + + /* Requester implementation */ + pldm_requester_init(); out: prlog(PR_NOTICE, "%s - done, rc: %d\n", __func__, rc); diff --git a/core/pldm/pldm-requester.c b/core/pldm/pldm-requester.c new file mode 100644 index 00000000..07c6bdfd --- /dev/null +++ b/core/pldm/pldm-requester.c @@ -0,0 +1,336 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +// Copyright 2022 IBM Corp. + +#define pr_fmt(fmt) "PLDM: " fmt + +#include +#include +#include +#include +#include +#include +#include "pldm.h" + +#define TIMEOUT_MS 8000 + +struct pldm_request { + struct list_node link; + + /* originating request params */ + struct pldm_header_info hdrinf; + + /* messages requested */ + struct pldm_tx_data *tx; + + /* timeout handling */ + struct timer timeout; + uint64_t timeout_ms; + uint64_t start_time; + + /* completion callback */ + void (*complete)(struct pldm_rx_data *rx, void *data); + void *complete_data; +}; + +struct pldm_response { + void **msg; + size_t *msg_size; + bool done; + int rc; +}; + +/* pldm requests queue */ +static struct lock pldm_requests_lock = LOCK_UNLOCKED; +static LIST_HEAD(list_pldm_requests); + +static struct pldm_request *active_request; + +static bool matches_request(const struct pldm_rx_data *rx, + const struct pldm_request *req) +{ + if (req->hdrinf.instance != rx->hdrinf.instance) + return false; + if (req->hdrinf.pldm_type != rx->hdrinf.pldm_type) + return false; + if (req->hdrinf.command != rx->hdrinf.command) + return false; + + return true; +} + +static void send_and_wait_complete(struct pldm_rx_data *rx, void *data) +{ + struct pldm_response *resp = (struct pldm_response *)data; + int len; + + if (rx != NULL) { + len = rx->msg_len; + *resp->msg_size = len; + *resp->msg = zalloc(len); + memcpy(*resp->msg, rx->msg, len); + + resp->rc = OPAL_SUCCESS; + } else { + *resp->msg_size = 0; + *resp->msg = NULL; + resp->rc = OPAL_TIMEOUT; + } + + resp->done = true; +} + +static void handle_response(struct pldm_rx_data *rx) +{ + uint64_t now; + + if (active_request == NULL) { + prlog(PR_ERR, "%s: No active request\n", __func__); + return; + } + + /* unactivate the timer */ + if (rx != NULL) + cancel_timer(&active_request->timeout); + + if (active_request->complete) + active_request->complete(rx, active_request->complete_data); + + now = mftb(); + prlog(PR_TRACE, "%s: Finished after %ldms, t:%d c:%d i:%d \n", + __func__, + tb_to_msecs(now - active_request->start_time), + active_request->hdrinf.pldm_type, + active_request->hdrinf.command, + active_request->hdrinf.instance); + + free(active_request->tx); + free(active_request); + active_request = NULL; +} + +/* + * Timeout :( + */ +static void expiry(struct timer *t __unused, void *data, uint64_t now __unused) +{ + struct pldm_request *req = (struct pldm_request *)data; + + if (active_request == NULL) { + prlog(PR_ERR, "request timedout! (active request NULL)\n"); + return; + } + + prlog(PR_ERR, "PLDM: request timedout! (active request: t:0x%x c:0x%x i:%d)\n", + active_request->hdrinf.pldm_type, + active_request->hdrinf.command, + active_request->hdrinf.instance); + + prlog(PR_ERR, "PLDM: Original request t:0x%x c:0x%x i:%d -----\n", + req->hdrinf.pldm_type, + req->hdrinf.command, req->hdrinf.instance); + + /* no data received. Finish the procedure */ + handle_response(NULL); +} + +/* + * Handle PLDM message received from the PLDM terminus over MCTP + */ +int pldm_requester_handle_response(struct pldm_rx_data *rx) +{ + /* check the message received */ + if (active_request == NULL) { + prlog(PR_ERR, "%s: No active request. " + "Response received t:%d c:%d i:%d\n", + __func__, + rx->hdrinf.pldm_type, + rx->hdrinf.command, + rx->hdrinf.instance); + return OPAL_WRONG_STATE; + } + + if (!matches_request(rx, active_request)) { + prlog(PR_ERR, "%s: Unexpected response! t:%d c:%d i:%d want %d,%d,%d\n", + __func__, + rx->hdrinf.pldm_type, + rx->hdrinf.command, + rx->hdrinf.instance, + active_request->hdrinf.pldm_type, + active_request->hdrinf.command, + active_request->hdrinf.instance); + return OPAL_WRONG_STATE; + } + + /* The expected message seems correct */ + handle_response(rx); + + return OPAL_SUCCESS; +} + +/* + * Send the PLDM request + */ +static void requests_poller(void *data __unused) +{ + int rc = OPAL_SUCCESS; + + lock(&pldm_requests_lock); + + /* wait for the end of the processing of the current request */ + if (active_request) { + unlock(&pldm_requests_lock); + return; + } + + /* no new request to handle */ + if (list_empty(&list_pldm_requests)) { + unlock(&pldm_requests_lock); + return; + } + + /* remove the first entry in a list */ + active_request = list_pop(&list_pldm_requests, + struct pldm_request, + link); + + unlock(&pldm_requests_lock); + + /* Start timer to control a timeout from the PLDM terminus */ + init_timer(&active_request->timeout, expiry, active_request); + schedule_timer(&active_request->timeout, + msecs_to_tb(active_request->timeout_ms)); + active_request->start_time = mftb(); + + /* Send PLDM message over MCTP */ + prlog(PR_TRACE, "%s: Sending request to BMC t:%d c:%d i:%d -----\n", + __func__, + active_request->hdrinf.pldm_type, + active_request->hdrinf.command, + active_request->hdrinf.instance); + + rc = pldm_mctp_message_tx(active_request->tx); + if (rc) + prlog(PR_ERR, "%s: Error %d while sending request\n", + __func__, rc); +} + +/* + * Add PLDM request in the queue + */ +static int queue_request(struct pldm_tx_data *tx, + uint64_t timeout_ms, + void (*complete)(struct pldm_rx_data *rx, void *data), + void *complete_data) +{ + struct pldm_request *pending; + struct pldm_msg *pldm_msg; + size_t tx_size; + + tx_size = sizeof(struct pldm_tx_data) + tx->data_size; + + pending = zalloc(sizeof(struct pldm_request)); + if (!pending) { + prlog(PR_ERR, "%s: failed to allocate request\n", __func__); + return OPAL_NO_MEM; + } + + pending->timeout_ms = timeout_ms; + pending->complete = complete; + pending->complete_data = complete_data; + pending->tx = zalloc(tx_size); + if (!pending->tx) { + free(pending); + prlog(PR_ERR, "%s: failed to allocate pldm packet (size: 0x%lx)\n", + __func__, tx_size); + return OPAL_NO_MEM; + } + + memcpy(pending->tx, tx, tx_size); + + pldm_msg = (struct pldm_msg *)tx->data; + if (unpack_pldm_header(&pldm_msg->hdr, &pending->hdrinf)) { + free(pending->tx); + free(pending); + prlog(PR_ERR, "%s: error parsing pldm header\n", __func__); + return OPAL_PARAMETER; + } + + /* add an entry at the end of a linked list */ + prlog(PR_TRACE, "%s: Add request t:%d c:%d i:%d -----\n", + __func__, + pending->hdrinf.pldm_type, + pending->hdrinf.command, + pending->hdrinf.instance); + + lock(&pldm_requests_lock); + list_add_tail(&list_pldm_requests, &pending->link); + unlock(&pldm_requests_lock); + + /* call the poller if the list only contains this request */ + requests_poller(NULL); + + return OPAL_SUCCESS; +} + +/* + * Queue a PLDM request and don't wait. + * When a response is received, call the associated callback. + */ +int pldm_requester_queue(struct pldm_tx_data *tx, + void (*complete)(struct pldm_rx_data *rx, void *data), + void *complete_data) +{ + int rc = OPAL_SUCCESS; + + /* Queue PLDM request */ + rc = queue_request(tx, TIMEOUT_MS, complete, complete_data); + if (rc) { + prlog(PR_ERR, "%s: error %d while queuing request\n", + __func__, rc); + return rc; + } + + return rc; +} + +/* + * Queue a PLDM request and spin until we get a response. + */ +int pldm_requester_queue_and_wait(struct pldm_tx_data *tx, + void **msg, size_t *msg_size) +{ + struct pldm_response *resp; + int rc = OPAL_SUCCESS; + + resp = zalloc(sizeof(struct pldm_response)); + if (!resp) { + prlog(PR_ERR, "%s: failed to allocate response\n", __func__); + return OPAL_NO_MEM; + } + + resp->msg = msg; + resp->msg_size = msg_size; + + rc = pldm_requester_queue(tx, send_and_wait_complete, resp); + if (rc) + goto out; + + /* wait for a response from the BMC */ + for (;;) { + if (resp->done) + break; + + time_wait_ms(5); + } + rc = resp->rc; + +out: + free(resp); + return rc; +} + +void pldm_requester_init(void) +{ + /* requests poller */ + opal_add_poller(requests_poller, NULL); +} diff --git a/core/pldm/pldm.h b/core/pldm/pldm.h index 1cb0b424..d7a310c0 100644 --- a/core/pldm/pldm.h +++ b/core/pldm/pldm.h @@ -47,4 +47,13 @@ int pldm_mctp_message_rx(uint8_t eid, bool tag_owner, uint8_t msg_tag, int pldm_responder_handle_request(struct pldm_rx_data *rx); int pldm_responder_init(void); +/* Requester support */ +int pldm_requester_handle_response(struct pldm_rx_data *rx); +int pldm_requester_queue(struct pldm_tx_data *tx, + void (*complete)(struct pldm_rx_data *rx, void *data), + void *complete_data); +int pldm_requester_queue_and_wait(struct pldm_tx_data *tx, + void **msg, size_t *msg_size); +void pldm_requester_init(void); + #endif /* __COREPLDM_H__ */ diff --git a/include/ast.h b/include/ast.h index e9c39c6d..c831efc0 100644 --- a/include/ast.h +++ b/include/ast.h @@ -107,6 +107,12 @@ void ast_setup_sio_mbox(uint16_t io_base, uint8_t irq); */ #define HOST_TID 3 +/* + * Skiboot's PLDM Terminus ID. + * BMC TID is 1, HB is 2, Skiboot is 3. + */ +#define HOST_TID 3 + enum mctp_msg_type { MCTP_MSG_TYPE_CONTROL = 0x00, MCTP_MSG_TYPE_PLDM = 0x01,