[Skiboot] [PATCH V2 09/21] core/pldm: Implement PLDM requester
Christophe Lombard
clombard at linux.vnet.ibm.com
Fri Mar 18 01:58:08 AEDT 2022
Le 16/03/2022 à 10:28, Abhishek SIngh Tomar a écrit :
> Hello Christophe
>
> In function queue_request() we pass eid as argument.
>
> function calling as follows:
> queue_request() -> start_req() -> pldm_send() -> ast_mctp_message_tx()
>
> In ast_mctp_message_tx() we pass BMC_EID forcefully but not taking into
> consideration queue_request() passed EID. Are both eid corresponds to
> destination?
You are right. We should consider the dest_id in pldm_send()
instead of force a default value.
>
> Regards
> Abhishek Singh Tomar
>
> On Fri, Mar 04, 2022 at 02:11:42PM +0100, Christophe Lombard wrote:
>> 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.
>>
>> Signed-off-by: Christophe Lombard <clombard at linux.vnet.ibm.com>
>> ---
>> core/pldm/Makefile.inc | 2 +-
>> core/pldm/pldm-common.c | 2 +
>> core/pldm/pldm-requester.c | 268 +++++++++++++++++++++++++++++++++++++
>> core/pldm/pldm.h | 6 +
>> 4 files changed, 277 insertions(+), 1 deletion(-)
>> create mode 100644 core/pldm/pldm-requester.c
>>
>> diff --git a/core/pldm/Makefile.inc b/core/pldm/Makefile.inc
>> index 3909c86f..c431288f 100644
>> --- a/core/pldm/Makefile.inc
>> +++ b/core/pldm/Makefile.inc
>> @@ -7,7 +7,7 @@ SUBDIRS += $(PLDM_DIR)
>> CPPFLAGS += -I$(SRC)/pldm/libpldm/
>> CPPFLAGS += -I$(SRC)/pldm/ibm/libpldm/
>>
>> -PLDM_OBJS = pldm-common.o pldm-responder.o
>> +PLDM_OBJS = pldm-common.o pldm-responder.o pldm-requester.o
>>
>> PLDM = $(PLDM_DIR)/built-in.a
>> $(PLDM): $(PLDM_OBJS:%=$(PLDM_DIR)/%)
>> diff --git a/core/pldm/pldm-common.c b/core/pldm/pldm-common.c
>> index 76cb1aa5..15ee2af9 100644
>> --- a/core/pldm/pldm-common.c
>> +++ b/core/pldm/pldm-common.c
>> @@ -76,6 +76,8 @@ static int pldm_handle(uint8_t eid, const uint8_t *buf, int len)
>> }
>>
>> switch (rx.hdrinf.msg_type) {
>> + case PLDM_RESPONSE:
>> + return pldm_rx_handle_response(&rx);
>> case PLDM_REQUEST:
>> return pldm_rx_handle_request(&rx);
>> break;
>> diff --git a/core/pldm/pldm-requester.c b/core/pldm/pldm-requester.c
>> new file mode 100644
>> index 00000000..58d01f80
>> --- /dev/null
>> +++ b/core/pldm/pldm-requester.c
>> @@ -0,0 +1,268 @@
>> +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
>> +// Copyright 2022 IBM Corp.
>> +
>> +#define pr_fmt(fmt) "PLDM: " fmt
>> +
>> +#include <cpu.h>
>> +#include <stdio.h>
>> +#include <string.h>
>> +#include <timebase.h>
>> +#include <pldm/libpldm/utils.h>
>> +#include "pldm.h"
>> +
>> +struct pldm_request {
>> + /* originating request params */
>> + int dest;
>> + int instance;
>> + int cmd_code;
>> + int type;
>> +
>> + uint64_t timeout_ms;
>> + uint64_t start_time;
>> +
>> + void *buf;
>> + int len;
>> +
>> + /* completion callback */
>> + void (*complete)(struct pldm_request *req,
>> + struct pldm_rx_data *resp);
>> + void *cb_data;
>> + int rc;
>> +
>> + struct list_node link;
>> +};
>> +
>> +/*
>> + * Sent out and waiting on a response.
>> + */
>> +static struct pldm_request *active_request;
>> +
>> +static bool matches_request(const struct pldm_rx_data *rx,
>> + const struct pldm_request *req)
>> +{
>> + if (req->instance != rx->hdrinf.instance)
>> + return false;
>> + if (req->type != rx->hdrinf.pldm_type)
>> + return false;
>> + if (req->cmd_code != rx->hdrinf.command)
>> + return false;
>> +
>> + return true;
>> +}
>> +
>> +/*
>> + * Requests that are ready to send.
>> + */
>> +LIST_HEAD(pldm_request_queue);
>> +
>> +static bool request_timed_out(struct pldm_request *req)
>> +{
>> + uint64_t deadline = req->start_time + msecs_to_tb(req->timeout_ms);
>> +
>> + return tb_compare(mftb(), deadline) == TB_AAFTERB;
>> +}
>> +
>> +/*
>> + * Send the PLDM request.
>> + */
>> +static void start_req(struct pldm_request *r)
>> +{
>> + if (active_request) {
>> + prlog(PR_ERR, "%s: request already active?\n",
>> + __func__);
>> + return;
>> + }
>> +
>> + r->start_time = mftb();
>> + active_request = r;
>> +
>> + pldm_send(r->buf, r->len);
>> +}
>> +
>> +static void complete_request(struct pldm_rx_data *rx)
>> +{
>> + struct pldm_request *req = active_request;
>> +
>> + if (req->complete)
>> + req->complete(req, rx);
>> +
>> + active_request = NULL;
>> +}
>> +
>> +/*
>> + * Add PLDM request in the queue/
>> + */
>> +static int queue_request(int dest_eid, void *buf, int len,
>> + uint64_t timeout_ms,
>> + void (*complete)(struct pldm_request *,
>> + struct pldm_rx_data *),
>> + void *cb_data)
>> +{
>> + struct pldm_header_info hdrinf;
>> + struct pldm_request *pending;
>> +
>> + if (active_request)
>> + return OPAL_BUSY;
>> +
>> + if (unpack_pldm_header(buf, &hdrinf)) {
>> + prlog(PR_ERR, "%s: error parsing pldm header\n",
>> + __func__);
>> + return OPAL_PARAMETER;
>> + }
>> +
>> + pending = zalloc(sizeof(struct pldm_request));
>> +
>> + pending->dest = dest_eid;
>> + pending->instance = hdrinf.instance;
>> + pending->type = hdrinf.pldm_type;
>> + pending->cmd_code = hdrinf.command;
>> + pending->timeout_ms = timeout_ms;
>> +
>> + pending->buf = buf;
>> + pending->len = len;
>> +
>> + pending->complete = complete;
>> + pending->cb_data = cb_data;
>> +
>> + start_req(pending);
>> +
>> + return OPAL_SUCCESS;
>> +}
>> +
>> +/*
>> + * Synchronus request handling.
>> + */
>> +struct pldm_do_request_data {
>> + void **buf;
>> + size_t *len;
>> + bool done;
>> + int rc;
>> +};
>> +
>> +static void do_request_cb(struct pldm_request *req,
>> + struct pldm_rx_data *resp)
>> +{
>> + struct pldm_do_request_data *cb_data = req->cb_data;
>> + int len = resp->msg_len;
>> +
>> + if (resp && !request_timed_out(req)) {
>> + *cb_data->len = len;
>> + *cb_data->buf = malloc(len);
>> + memcpy(*cb_data->buf, resp->msg, len);
>> +
>> + cb_data->rc = OPAL_SUCCESS;
>> + } else {
>> + *cb_data->len = 0;
>> + *cb_data->buf = NULL;
>> + cb_data->rc = OPAL_TIMEOUT;
>> + }
>> +
>> + cb_data->done = true;
>> +
>> + free(req);
>> +}
>> +
>> +/*
>> + * Timeout :(
>> + */
>> +static void pldm_timeout_cb(struct timer *t __unused, void *data,
>> + uint64_t now __unused)
>> +{
>> + struct pldm_do_request_data *cb_data = data;
>> +
>> + if (cb_data->done)
>> + return;
>> +
>> + prlog(PR_ERR, "%s, request timedout!\n", __func__);
>> + complete_request(NULL);
>> +}
>> +
>> +/*
>> + * Send a PLDM request and spin until we get a reply.
>> + */
>> +int pldm_do_request(uint8_t dest_eid,
>> + void *request_msg, size_t request_len,
>> + void **response_msg, size_t *response_len)
>> +{
>> + uint64_t now, queue_start, resp_start;
>> + struct pldm_do_request_data cb_data;
>> + struct timer pldm_timeout;
>> + uint64_t timeout_ms;
>> + int retries = 10;
>> + int rc;
>> +
>> + /* Start timer ton control a timeout from the PLDM terminus */
>> + init_timer(&pldm_timeout, pldm_timeout_cb, &cb_data);
>> + timeout_ms = 8000;
>> +
>> + memset(&cb_data, 0, sizeof(cb_data));
>> + cb_data.buf = response_msg;
>> + cb_data.len = response_len;
>> +
>> + /* Send PLDM request */
>> + queue_start = mftb();
>> + do {
>> + rc = queue_request(dest_eid,
>> + request_msg, request_len,
>> + timeout_ms, do_request_cb,
>> + &cb_data);
>> + if (rc == OPAL_BUSY) {
>> + time_wait_ms(10);
>> + retries--;
>> + }
>> + if (!retries) {
>> + prlog(PR_ERR, "%s, timed out trying to queue "
>> + "PLDM request\n", __func__);
>> + return OPAL_BUSY;
>> + }
>> + } while (rc == OPAL_BUSY);
>> +
>> + if (rc) {
>> + prlog(PR_ERR, "%s: Error %d while queuing request\n",
>> + __func__, rc);
>> + return rc;
>> + }
>> +
>> + /* Wait for answer from the PLDM terminus */
>> + schedule_timer(&pldm_timeout, msecs_to_tb(timeout_ms));
>> + resp_start = mftb();
>> + do {
>> + time_wait_ms(5);
>> + } while (!cb_data.done);
>> +
>> + cancel_timer(&pldm_timeout);
>> + now = mftb();
>> +
>> + prlog(PR_TRACE, "%s: Finished after %ldms, length: %ld "
>> + "(queuing: %ldms, resp: %ldms)\n",
>> + __func__,
>> + tb_to_msecs(now - queue_start),
>> + *cb_data.len,
>> + tb_to_msecs(resp_start - queue_start),
>> + tb_to_msecs(now - resp_start));
>> +
>> + return cb_data.rc;
>> +}
>> +
>> +/*
>> + * Handle PLDM message received from the PLDM terminus over MCTP.
>> + */
>> +int pldm_rx_handle_response(struct pldm_rx_data *rx)
>> +{
>> + /* check the message received */
>> + 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->type,
>> + active_request->cmd_code,
>> + active_request->instance
>> + );
>> + return OPAL_WRONG_STATE;
>> + }
>> +
>> + complete_request(rx);
>> + return OPAL_SUCCESS;
>> +}
>> diff --git a/core/pldm/pldm.h b/core/pldm/pldm.h
>> index 74f883d6..fd677742 100644
>> --- a/core/pldm/pldm.h
>> +++ b/core/pldm/pldm.h
>> @@ -46,4 +46,10 @@ void pldm_rx_message(uint8_t eid, void *data __unused, void *vmsg,
>> int pldm_rx_handle_request(struct pldm_rx_data *rx);
>> int pldm_mctp_responder_init(void);
>>
>> +/* Requester support */
>> +int pldm_do_request(uint8_t dest_eid,
>> + void *request_msg, size_t request_len,
>> + void **response_msg, size_t *response_len);
>> +int pldm_rx_handle_response(struct pldm_rx_data *rx);
>> +
>> #endif /* __COREPLDM_H__ */
>> --
>> 2.35.1
>>
>> _______________________________________________
>> Skiboot mailing list
>> Skiboot at lists.ozlabs.org
>> https://lists.ozlabs.org/listinfo/skiboot
More information about the Skiboot
mailing list