[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