[Skiboot] [PATCH V6 04/21] core/pldm: Add PLDM responder support

Abhishek SIngh Tomar abhishek at linux.ibm.com
Thu Sep 29 22:28:05 AEST 2022


On Tue, Sep 13, 2022 at 12:26:48PM +0200, Christophe Lombard wrote:
> PLDM defines data representations and commands that abstract the platform
> management hardware.
> 
> A PLDM Terminus (or responder) is defined as the point of communication
> termination for PLDM messages and the PLDM functions associated with those
> messages.
> A PLDM terminus is not required to process more than one request at a time
> (that is, it can be "single threaded" and does not have to accept and act
> on new requests until it has finished responding to any previous request).
> 
> Some PLDM control and discovery requests (PLDM_TYPE = PLDM_BASE) are
> mandatory a PLDM terminus has to answer.
> 
> These following mandatory PLDM command codes for PLDM messaging control
> and discovery will be defined in next patches.
>     GetTID          0x02
>     GetPLDMVersion  0x03
>     GetPLDMTypes    0x04
>     GetPLDMCommands 0x05
> 
> Signed-off-by: Christophe Lombard <clombard at linux.vnet.ibm.com>
Reviewed-by: Abhishek Singh Tomar <abhishek at linux.ibm.com>
> ---
>  core/pldm/Makefile.inc     |   2 +-
>  core/pldm/pldm-mctp.c      |  18 ++++-
>  core/pldm/pldm-responder.c | 145 +++++++++++++++++++++++++++++++++++++
>  core/pldm/pldm.h           |   6 ++
>  4 files changed, 169 insertions(+), 2 deletions(-)
>  create mode 100644 core/pldm/pldm-responder.c
> 
> diff --git a/core/pldm/Makefile.inc b/core/pldm/Makefile.inc
> index c878ef1f..dbca102a 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-mctp.o
> +PLDM_OBJS = pldm-mctp.o pldm-responder.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 832b767a..51dbad0a 100644
> --- a/core/pldm/pldm-mctp.c
> +++ b/core/pldm/pldm-mctp.c
> @@ -75,6 +75,14 @@ static int handle_message_rx(uint8_t eid, const uint8_t *buf, int len)
>  		return OPAL_EMPTY;
>  	}
> 
> +	switch (rx.hdrinf.msg_type) {
> +	case PLDM_REQUEST:
> +		return pldm_responder_handle_request(&rx);
> +	break;
> +	default:
> +	break;
> +	}
> +
>  	return OPAL_UNSUPPORTED;
>  }
> 
> @@ -105,9 +113,17 @@ int pldm_mctp_init(uint8_t mode)
> 
>  	/* MCTP Binding */
>  	rc = ast_mctp_init(mode, message_rx);
> -	if (rc)
> +	if (rc) {
>  		prlog(PR_ERR, "Failed to bind MCTP\n");
> +		goto out;
> +	}
> +
> +	/* Register mandatory commands we'll respond to */
> +	rc = pldm_responder_init();
> +	if (rc)
> +		prlog(PR_ERR, "Failed to register mandatory commands\n");
> 
> +out:
>  	prlog(PR_NOTICE, "%s - done, rc: %d\n", __func__, rc);
>  	return rc;
>  }
> diff --git a/core/pldm/pldm-responder.c b/core/pldm/pldm-responder.c
> new file mode 100644
> index 00000000..94289cac
> --- /dev/null
> +++ b/core/pldm/pldm-responder.c
> @@ -0,0 +1,145 @@
> +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
> +// Copyright 2022 IBM Corp.
> +
> +#define pr_fmt(fmt) "PLDM: " fmt
> +
> +#include <bitmap.h>
> +#include <cpu.h>
> +#include <opal.h>
> +#include <stdio.h>
> +#include <string.h>
> +#include <pldm/libpldm/utils.h>
> +#include "pldm.h"
> +
> +struct pldm_type {
> +	const char *name;
> +	int pldm_type_id;
> +	ver32_t version;
> +
> +	struct list_head commands;
> +	struct list_node link;
> +};
> +
> +struct pldm_cmd {
> +	const char *name;
> +	int pldm_cmd_id;
> +
> +	int (*handler)(const struct pldm_rx_data *req);
> +
> +	struct list_node link; /* link in the msg type's command list */
> +};
> +
> +/*
> + * Send a response with just a completion code and no payload
> + */
> +static int cc_resp(const struct pldm_rx_data *req, uint8_t type,
> +			uint8_t command, uint8_t cc)
> +{
> +	char response_msg[PKT_SIZE(uint8_t)];
> +	int rc;
> +
> +	memset(response_msg, 0, sizeof(response_msg));
> +
> +	encode_cc_only_resp(req->hdrinf.instance,
> +			    type,
> +			    command,
> +			    cc,
> +			    (struct pldm_msg *)response_msg);
> +
> +	rc = pldm_mctp_message_tx(req->source_eid, response_msg, sizeof(response_msg));
> +	if (rc) {
> +		prlog(PR_ERR, "Failed to send response message containing only cc, "
> +			      "rc = %d, cc = %d\n", rc, cc);
> +		return OPAL_HARDWARE;
> +	}
> +
> +	return OPAL_SUCCESS;
> +}
> +
> +/*
> + * PLDM Type / Command wrangling.
> + */
> +LIST_HEAD(pldm_type_list);
> +
> +static const struct pldm_type *find_type(int type_id)
> +{
> +	struct pldm_type *iter;
> +
> +	list_for_each(&pldm_type_list, iter, link) {
> +		if (iter->pldm_type_id == type_id)
> +			return iter;
> +	}
> +
> +	return NULL;
> +}
> +
> +static const struct pldm_cmd *find_cmd(const struct pldm_type *type, int cmd)
> +{
> +	struct pldm_cmd *iter;
> +
> +	list_for_each(&type->commands, iter, link)
> +		if (iter->pldm_cmd_id == cmd)
> +			return iter;
> +
> +	return NULL;
> +}
> +
> +static void add_type(struct pldm_type *new_type)
> +{
> +	assert(new_type->pldm_type_id < 32); /* limited by GetPLDMTypes */
> +	assert(!find_type(new_type->pldm_type_id));
> +
> +	list_head_init(&new_type->commands);
> +	list_add_tail(&pldm_type_list, &new_type->link);
> +
> +	prlog(PR_DEBUG, "Registered type %s (%d)\n",
> +	      new_type->name, new_type->pldm_type_id);
> +}
> +
> +/*
> + * PLDM Base commands support
> + */
> +static struct pldm_type pldm_base_type = {
> +	.name = "base",
> +	.pldm_type_id = PLDM_BASE,
> +	.version = { 0xF1, 0xF0, 0xF0, 0x00 },
> +};
> +
> +int pldm_responder_handle_request(struct pldm_rx_data *rx)
> +{
> +	const struct pldm_type *type;
> +	const struct pldm_cmd *cmd;
> +
> +	prlog(PR_INFO, "Receive PLDM request from BMC, type: 0x%x, command: 0x%x\n",
> +			rx->hdrinf.pldm_type, rx->hdrinf.command);
> +
> +	type = find_type(rx->hdrinf.pldm_type);
> +	if (!type) {
> +		prlog(PR_ERR, "Type not supported, type: 0x%x\n",
> +			      rx->hdrinf.pldm_type);
> +		cc_resp(rx, rx->hdrinf.pldm_type,
> +			rx->hdrinf.command,
> +			PLDM_ERROR_INVALID_PLDM_TYPE);
> +		return OPAL_UNSUPPORTED;
> +	}
> +
> +	cmd = find_cmd(type, rx->hdrinf.command);
> +	if (!cmd) {
> +		prlog(PR_ERR, "Command not supported, type: 0x%x, command: 0x%x\n",
> +			      rx->hdrinf.pldm_type, rx->hdrinf.command);
> +		cc_resp(rx, rx->hdrinf.pldm_type,
> +			rx->hdrinf.command,
> +			PLDM_ERROR_UNSUPPORTED_PLDM_CMD);
> +		return OPAL_UNSUPPORTED;
> +	}
> +
> +	return cmd->handler(rx);
> +}
> +
> +int pldm_responder_init(void)
> +{
> +	/* Register mandatory commands we'll respond to - DSP0240 */
> +	add_type(&pldm_base_type);
> +
> +	return OPAL_SUCCESS;
> +}
> diff --git a/core/pldm/pldm.h b/core/pldm/pldm.h
> index a006d1f4..3add1bac 100644
> --- a/core/pldm/pldm.h
> +++ b/core/pldm/pldm.h
> @@ -20,6 +20,8 @@ void printbuf(const char *name, const char *msg, int len);
>  #define BMC_EID  8
>  #define HOST_EID 9
> 
> +#define PKT_SIZE(x) (sizeof(struct pldm_msg_hdr) + sizeof(x))
> +
>  struct pldm_rx_data {
>  	struct pldm_header_info hdrinf; /* parsed message header */
> 
> @@ -30,4 +32,8 @@ struct pldm_rx_data {
> 
>  int pldm_mctp_message_tx(uint8_t dest_id, uint8_t *buf, int len);
> 
> +/* Responder support */
> +int pldm_responder_handle_request(struct pldm_rx_data *rx);
> +int pldm_responder_init(void);
> +
>  #endif /* __COREPLDM_H__ */
> -- 
> 2.37.3
> 
> _______________________________________________
> Skiboot mailing list
> Skiboot at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/skiboot


More information about the Skiboot mailing list