Message ID | 20220913102724.65563-15-clombard@linux.vnet.ibm.com |
---|---|
State | Superseded |
Headers | show |
Series | Complete PLDM responder and enable PLDM support | expand |
On Tue, Sep 13, 2022 at 12:27:23PM +0200, Christophe Lombard wrote: > OPAL_IPMI_SEND/RECV are used to retrieve and write IPMI requests. > This support is needed for Linux driver. > Only IPMI_GET_DEVICE_ID_CMD and IPMI_GET_DEVICE_GUID_CMD commands are > supported. > > Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com> Reviewed-by: Abhishek Singh Tomar <abhishek@linux.ibm.com> > --- > core/pldm/Makefile.inc | 2 +- > core/pldm/pldm-opal.c | 291 +++++++++++++++++++++++++++++++++++++++++ > include/pldm.h | 5 + > 3 files changed, 297 insertions(+), 1 deletion(-) > create mode 100644 core/pldm/pldm-opal.c > > diff --git a/core/pldm/Makefile.inc b/core/pldm/Makefile.inc > index 00d6c458..14dd833e 100644 > --- a/core/pldm/Makefile.inc > +++ b/core/pldm/Makefile.inc > @@ -16,7 +16,7 @@ PLDM_OBJS = pldm-mctp.o pldm-responder.o pldm-requester.o > PLDM_OBJS += pldm-base-requests.o pldm-platform-requests.o > PLDM_OBJS += pldm-bios-requests.o pldm-fru-requests.o > PLDM_OBJS += pldm-file-io-requests.o pldm-lid-files.o > -PLDM_OBJS += pldm-watchdog.o pldm-rtc.o > +PLDM_OBJS += pldm-watchdog.o pldm-rtc.o pldm-opal.o > > PLDM = $(PLDM_DIR)/built-in.a > $(PLDM): $(PLDM_OBJS:%=$(PLDM_DIR)/%) > diff --git a/core/pldm/pldm-opal.c b/core/pldm/pldm-opal.c > new file mode 100644 > index 00000000..3169d9d0 > --- /dev/null > +++ b/core/pldm/pldm-opal.c > @@ -0,0 +1,291 @@ > +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later > +// Copyright 2022 IBM Corp. > + > +#define pr_fmt(fmt) "PLDM: " fmt > + > +#include <stdlib.h> > +#include <string.h> > +#include <device.h> > +#include <ipmi.h> > +#include <opal.h> > +#include <lock.h> > +#include <timebase.h> > +#include <ccan/list/list.h> > +#include "pldm.h" > + > +/* > + * Response data from IPMI Get device ID command (As defined in > + * Section 20.1 Get Device ID Command - IPMI standard spec). > + */ > +struct ipmi_dev_id { > + uint8_t dev_id; > + uint8_t dev_revision; > + uint8_t fw_rev1; > + uint8_t fw_rev2; > + uint8_t ipmi_ver; > + uint8_t add_dev_support; > + uint8_t manufactur_id[3]; > + uint8_t product_id[2]; > + uint8_t aux_fw_rev[4]; > +}; > + > +static struct lock msgq_lock = LOCK_UNLOCKED; > +static struct list_head msgq = LIST_HEAD_INIT(msgq); > +uint64_t opal_event_ipmi_recv; > + > +static void opal_send_complete(struct ipmi_msg *msg) > +{ > + lock(&msgq_lock); > + list_add_tail(&msgq, &msg->link); > + opal_update_pending_evt(opal_event_ipmi_recv, > + opal_event_ipmi_recv); > + unlock(&msgq_lock); > +} > + > +#define GUID_SIZE 16 > + > +static int opal_get_tid_req(struct opal_ipmi_msg *opal_ipmi_msg, > + uint64_t msg_len __unused) > +{ > + struct ipmi_msg *opal_ipmi_response = NULL; > + uint8_t guid[GUID_SIZE]; > + int bmc_tid; > + > + opal_ipmi_response = zalloc(sizeof(struct ipmi_msg) + GUID_SIZE); > + opal_ipmi_response->netfn = IPMI_NETFN_RETURN_CODE(opal_ipmi_msg->netfn); > + opal_ipmi_response->cmd = opal_ipmi_msg->cmd; > + > + memset(&guid, 0, GUID_SIZE); > + > + /* First byte of guid contains bmc tid */ > + bmc_tid = pldm_base_get_bmc_tid(); > + if (bmc_tid == -1) { > + opal_ipmi_response->resp_size = 0; > + opal_ipmi_response->cc = IPMI_ERR_UNSPECIFIED; > + goto out; > + } > + > + guid[0] = (uint8_t)bmc_tid; > + memcpy(opal_ipmi_response->data, guid, GUID_SIZE); > + > + opal_ipmi_response->resp_size = GUID_SIZE; > + opal_ipmi_response->cc = IPMI_CC_NO_ERROR; > + > +out: > + opal_send_complete(opal_ipmi_response); > + return OPAL_SUCCESS; > +} > + > +static int parse_bmc_version(uint8_t *bmc_version, > + struct ipmi_dev_id *devid) > +{ > + uint8_t *ptr; > + uint8_t temp; > + > + prlog(PR_TRACE, "%s - bmc version: %s len=%d\n", __func__, > + bmc_version, (int)strlen(bmc_version)); > + > + /* > + * parse bmc version string to find fw_rev1 and fw_rev2 > + * Firmware Name is in format : > + * fw1030.00-2.8-1030.2233.20220819a (NL1030_007) > + * so fw_rev1 = 10 > + * fw_rev2 = 20 > + * aux_fw_rev = "007" > + */ > + ptr = strstr(bmc_version, "NL"); > + if (ptr == NULL || strlen(ptr) < 8) > + return OPAL_PARAMETER; > + > + ptr += 2; > + /* > + * Convert first two byte to > + * fw_rev1 and net 2byte to fw_rev2 > + */ > + temp = ptr[2]; > + ptr[2] = '\0'; > + devid->fw_rev1 = (uint8_t)atoi(ptr); > + ptr += 2; > + ptr[0] = temp; > + > + temp = ptr[2]; > + ptr[2] = '\0'; > + devid->fw_rev2 = (uint8_t)atoi(ptr); > + ptr += 2; > + ptr[0] = temp; > + > + /* Aux version is truncated to 4 char only */ > + if (*ptr == '_') > + strncpy(devid->aux_fw_rev, ptr + 1, 3); > + > + prlog(PR_TRACE, "BMC Version major->%d minor->%d aux->%.4s\n", > + devid->fw_rev1, devid->fw_rev2, devid->aux_fw_rev); > + > + return OPAL_SUCCESS; > +} > + > +static int opal_get_bmc_info(struct opal_ipmi_msg *opal_ipmi_msg, > + uint64_t msg_len __unused) > +{ > + struct ipmi_msg *opal_ipmi_response = NULL; > + char bmc_version[100]; > + struct ipmi_dev_id devid; > + int rc; > + > + opal_ipmi_response = zalloc(sizeof(struct ipmi_msg) + > + sizeof(struct ipmi_dev_id)); > + opal_ipmi_response->resp_size = sizeof(struct ipmi_dev_id); > + opal_ipmi_response->netfn = IPMI_NETFN_RETURN_CODE(opal_ipmi_msg->netfn); > + opal_ipmi_response->cmd = opal_ipmi_msg->cmd; > + opal_ipmi_response->cc = IPMI_CC_NO_ERROR; > + > + memset(&devid, 0, sizeof(devid)); > + devid.ipmi_ver = OPAL_IPMI_MSG_FORMAT_VERSION_1; > + > + /* retrieve bmc version */ > + rc = pldm_fru_get_bmc_version(bmc_version); > + if (rc) { > + opal_ipmi_response->resp_size = 0; > + opal_ipmi_response->cc = IPMI_ERR_UNSPECIFIED; > + goto out; > + } > + > + /* parse the bmc version */ > + rc = parse_bmc_version(bmc_version, &devid); > + if (rc) { > + prlog(PR_ERR, "%s: Failed to parse BMC version, bmc version: %s\n", > + __func__, bmc_version); > + opal_ipmi_response->resp_size = 0; > + opal_ipmi_response->cc = IPMI_ERR_UNSPECIFIED; > + goto out; > + } > + > + memcpy(opal_ipmi_response->data, &devid, sizeof(devid)); > + > +out: > + opal_send_complete(opal_ipmi_response); > + return OPAL_SUCCESS; > +} > + > +static int64_t opal_ipmi_send(uint64_t interface __unused, > + struct opal_ipmi_msg *opal_ipmi_msg, > + uint64_t msg_len) > +{ > + int16_t ipmi_code; > + > + if (opal_ipmi_msg->version != OPAL_IPMI_MSG_FORMAT_VERSION_1) { > + prerror("OPAL IPMI: Incorrect version\n"); > + return OPAL_UNSUPPORTED; > + } > + > + msg_len -= sizeof(struct opal_ipmi_msg); > + if (msg_len > IPMI_MAX_REQ_SIZE) { > + prerror("OPAL IPMI: Invalid request length\n"); > + return OPAL_PARAMETER; > + } > + > + ipmi_code = IPMI_CODE(opal_ipmi_msg->netfn >> 2, opal_ipmi_msg->cmd); > + if ((ipmi_code == IPMI_CHASSIS_GET_SYS_BOOT_OPT_CMD) || > + (opal_ipmi_msg->cmd == IPMI_CODE(opal_ipmi_msg->netfn >> 2, 0x1a)) || > + (opal_ipmi_msg->cmd == IPMI_CODE(opal_ipmi_msg->netfn >> 2, 0x42))) { > + prerror("OPAL IPMI: Command not supported\n"); > + return OPAL_UNSUPPORTED; > + } > + > + prlog(PR_TRACE, "%s - cmd: 0x%02x netfn: 0x%02x len: 0x%02llx\n", > + __func__, opal_ipmi_msg->cmd, opal_ipmi_msg->netfn >> 2, > + msg_len); > + > + switch (opal_ipmi_msg->cmd) { > + case IPMI_GET_DEVICE_ID_CMD: > + return opal_get_bmc_info(opal_ipmi_msg, msg_len); > + > + case IPMI_GET_DEVICE_GUID_CMD: > + return opal_get_tid_req(opal_ipmi_msg, msg_len); > + } > + > + return OPAL_UNSUPPORTED; > +} > + > +static int64_t opal_ipmi_recv(uint64_t interface, > + struct opal_ipmi_msg *opal_ipmi_msg, > + __be64 *msg_len) > +{ > + struct ipmi_msg *msg; > + int64_t rc; > + > + lock(&msgq_lock); > + msg = list_top(&msgq, struct ipmi_msg, link); > + > + if (!msg) { > + rc = OPAL_EMPTY; > + goto out_unlock; > + } > + > + if (opal_ipmi_msg->version != OPAL_IPMI_MSG_FORMAT_VERSION_1) { > + prerror("OPAL IPMI: Incorrect version\n"); > + rc = OPAL_UNSUPPORTED; > + goto out_del_msg; > + } > + > + if (interface != IPMI_DEFAULT_INTERFACE) { > + prerror("IPMI: Invalid interface 0x%llx in %s\n", interface, __func__); > + rc = OPAL_PARAMETER; > + goto out_del_msg; > + } > + > + if (be64_to_cpu(*msg_len) - sizeof(struct opal_ipmi_msg) < msg->resp_size + 1) { > + rc = OPAL_RESOURCE; > + goto out_del_msg; > + } > + > + list_del(&msg->link); > + if (list_empty(&msgq)) > + opal_update_pending_evt(opal_event_ipmi_recv, 0); > + unlock(&msgq_lock); > + > + opal_ipmi_msg->cmd = msg->cmd; > + opal_ipmi_msg->netfn = msg->netfn; > + opal_ipmi_msg->data[0] = msg->cc; > + memcpy(&opal_ipmi_msg->data[1], msg->data, msg->resp_size); > + > + prlog(PR_TRACE, "%s - cmd: 0x%02x netfn: 0x%02x resp_size: 0x%02x\n", > + __func__, msg->cmd, msg->netfn >> 2, msg->resp_size); > + > + /* Add one as the completion code is returned in the message data */ > + *msg_len = cpu_to_be64(msg->resp_size + sizeof(struct opal_ipmi_msg) + 1); > + free(msg); > + > + return OPAL_SUCCESS; > + > +out_del_msg: > + list_del(&msg->link); > + if (list_empty(&msgq)) > + opal_update_pending_evt(opal_event_ipmi_recv, 0); > + free(msg); > + > +out_unlock: > + unlock(&msgq_lock); > + return rc; > +} > + > +void pldm_opal_init(void) > +{ > + struct dt_node *opal_ipmi, *opal_event = NULL; > + > + opal_ipmi = dt_new(opal_node, "ipmi"); > + dt_add_property_strings(opal_ipmi, "compatible", "ibm,opal-ipmi"); > + dt_add_property_cells(opal_ipmi, "ibm,ipmi-interface-id", > + IPMI_DEFAULT_INTERFACE); > + opal_event_ipmi_recv = opal_dynamic_event_alloc(); > + dt_add_property_cells(opal_ipmi, "interrupts", > + ilog2(opal_event_ipmi_recv)); > + > + opal_event = dt_find_by_name(opal_node, "event"); > + if (opal_event) > + dt_add_property_cells(opal_ipmi, "interrupt-parent", > + opal_event->phandle); > + > + opal_register(OPAL_IPMI_SEND, opal_ipmi_send, 3); > + opal_register(OPAL_IPMI_RECV, opal_ipmi_recv, 3); > +} > diff --git a/include/pldm.h b/include/pldm.h > index db24040d..cb9cee08 100644 > --- a/include/pldm.h > +++ b/include/pldm.h > @@ -59,4 +59,9 @@ int pldm_platform_send_progress_state_change( > */ > void pldm_rtc_init(void); > > +/** > + * Register ipmi host interface access callbacks > + */ > +void pldm_opal_init(void); > + > #endif /* __PLDM_H__ */ > -- > 2.37.3 > > _______________________________________________ > Skiboot mailing list > Skiboot@lists.ozlabs.org > https://lists.ozlabs.org/listinfo/skiboot
diff --git a/core/pldm/Makefile.inc b/core/pldm/Makefile.inc index 00d6c458..14dd833e 100644 --- a/core/pldm/Makefile.inc +++ b/core/pldm/Makefile.inc @@ -16,7 +16,7 @@ PLDM_OBJS = pldm-mctp.o pldm-responder.o pldm-requester.o PLDM_OBJS += pldm-base-requests.o pldm-platform-requests.o PLDM_OBJS += pldm-bios-requests.o pldm-fru-requests.o PLDM_OBJS += pldm-file-io-requests.o pldm-lid-files.o -PLDM_OBJS += pldm-watchdog.o pldm-rtc.o +PLDM_OBJS += pldm-watchdog.o pldm-rtc.o pldm-opal.o PLDM = $(PLDM_DIR)/built-in.a $(PLDM): $(PLDM_OBJS:%=$(PLDM_DIR)/%) diff --git a/core/pldm/pldm-opal.c b/core/pldm/pldm-opal.c new file mode 100644 index 00000000..3169d9d0 --- /dev/null +++ b/core/pldm/pldm-opal.c @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +// Copyright 2022 IBM Corp. + +#define pr_fmt(fmt) "PLDM: " fmt + +#include <stdlib.h> +#include <string.h> +#include <device.h> +#include <ipmi.h> +#include <opal.h> +#include <lock.h> +#include <timebase.h> +#include <ccan/list/list.h> +#include "pldm.h" + +/* + * Response data from IPMI Get device ID command (As defined in + * Section 20.1 Get Device ID Command - IPMI standard spec). + */ +struct ipmi_dev_id { + uint8_t dev_id; + uint8_t dev_revision; + uint8_t fw_rev1; + uint8_t fw_rev2; + uint8_t ipmi_ver; + uint8_t add_dev_support; + uint8_t manufactur_id[3]; + uint8_t product_id[2]; + uint8_t aux_fw_rev[4]; +}; + +static struct lock msgq_lock = LOCK_UNLOCKED; +static struct list_head msgq = LIST_HEAD_INIT(msgq); +uint64_t opal_event_ipmi_recv; + +static void opal_send_complete(struct ipmi_msg *msg) +{ + lock(&msgq_lock); + list_add_tail(&msgq, &msg->link); + opal_update_pending_evt(opal_event_ipmi_recv, + opal_event_ipmi_recv); + unlock(&msgq_lock); +} + +#define GUID_SIZE 16 + +static int opal_get_tid_req(struct opal_ipmi_msg *opal_ipmi_msg, + uint64_t msg_len __unused) +{ + struct ipmi_msg *opal_ipmi_response = NULL; + uint8_t guid[GUID_SIZE]; + int bmc_tid; + + opal_ipmi_response = zalloc(sizeof(struct ipmi_msg) + GUID_SIZE); + opal_ipmi_response->netfn = IPMI_NETFN_RETURN_CODE(opal_ipmi_msg->netfn); + opal_ipmi_response->cmd = opal_ipmi_msg->cmd; + + memset(&guid, 0, GUID_SIZE); + + /* First byte of guid contains bmc tid */ + bmc_tid = pldm_base_get_bmc_tid(); + if (bmc_tid == -1) { + opal_ipmi_response->resp_size = 0; + opal_ipmi_response->cc = IPMI_ERR_UNSPECIFIED; + goto out; + } + + guid[0] = (uint8_t)bmc_tid; + memcpy(opal_ipmi_response->data, guid, GUID_SIZE); + + opal_ipmi_response->resp_size = GUID_SIZE; + opal_ipmi_response->cc = IPMI_CC_NO_ERROR; + +out: + opal_send_complete(opal_ipmi_response); + return OPAL_SUCCESS; +} + +static int parse_bmc_version(uint8_t *bmc_version, + struct ipmi_dev_id *devid) +{ + uint8_t *ptr; + uint8_t temp; + + prlog(PR_TRACE, "%s - bmc version: %s len=%d\n", __func__, + bmc_version, (int)strlen(bmc_version)); + + /* + * parse bmc version string to find fw_rev1 and fw_rev2 + * Firmware Name is in format : + * fw1030.00-2.8-1030.2233.20220819a (NL1030_007) + * so fw_rev1 = 10 + * fw_rev2 = 20 + * aux_fw_rev = "007" + */ + ptr = strstr(bmc_version, "NL"); + if (ptr == NULL || strlen(ptr) < 8) + return OPAL_PARAMETER; + + ptr += 2; + /* + * Convert first two byte to + * fw_rev1 and net 2byte to fw_rev2 + */ + temp = ptr[2]; + ptr[2] = '\0'; + devid->fw_rev1 = (uint8_t)atoi(ptr); + ptr += 2; + ptr[0] = temp; + + temp = ptr[2]; + ptr[2] = '\0'; + devid->fw_rev2 = (uint8_t)atoi(ptr); + ptr += 2; + ptr[0] = temp; + + /* Aux version is truncated to 4 char only */ + if (*ptr == '_') + strncpy(devid->aux_fw_rev, ptr + 1, 3); + + prlog(PR_TRACE, "BMC Version major->%d minor->%d aux->%.4s\n", + devid->fw_rev1, devid->fw_rev2, devid->aux_fw_rev); + + return OPAL_SUCCESS; +} + +static int opal_get_bmc_info(struct opal_ipmi_msg *opal_ipmi_msg, + uint64_t msg_len __unused) +{ + struct ipmi_msg *opal_ipmi_response = NULL; + char bmc_version[100]; + struct ipmi_dev_id devid; + int rc; + + opal_ipmi_response = zalloc(sizeof(struct ipmi_msg) + + sizeof(struct ipmi_dev_id)); + opal_ipmi_response->resp_size = sizeof(struct ipmi_dev_id); + opal_ipmi_response->netfn = IPMI_NETFN_RETURN_CODE(opal_ipmi_msg->netfn); + opal_ipmi_response->cmd = opal_ipmi_msg->cmd; + opal_ipmi_response->cc = IPMI_CC_NO_ERROR; + + memset(&devid, 0, sizeof(devid)); + devid.ipmi_ver = OPAL_IPMI_MSG_FORMAT_VERSION_1; + + /* retrieve bmc version */ + rc = pldm_fru_get_bmc_version(bmc_version); + if (rc) { + opal_ipmi_response->resp_size = 0; + opal_ipmi_response->cc = IPMI_ERR_UNSPECIFIED; + goto out; + } + + /* parse the bmc version */ + rc = parse_bmc_version(bmc_version, &devid); + if (rc) { + prlog(PR_ERR, "%s: Failed to parse BMC version, bmc version: %s\n", + __func__, bmc_version); + opal_ipmi_response->resp_size = 0; + opal_ipmi_response->cc = IPMI_ERR_UNSPECIFIED; + goto out; + } + + memcpy(opal_ipmi_response->data, &devid, sizeof(devid)); + +out: + opal_send_complete(opal_ipmi_response); + return OPAL_SUCCESS; +} + +static int64_t opal_ipmi_send(uint64_t interface __unused, + struct opal_ipmi_msg *opal_ipmi_msg, + uint64_t msg_len) +{ + int16_t ipmi_code; + + if (opal_ipmi_msg->version != OPAL_IPMI_MSG_FORMAT_VERSION_1) { + prerror("OPAL IPMI: Incorrect version\n"); + return OPAL_UNSUPPORTED; + } + + msg_len -= sizeof(struct opal_ipmi_msg); + if (msg_len > IPMI_MAX_REQ_SIZE) { + prerror("OPAL IPMI: Invalid request length\n"); + return OPAL_PARAMETER; + } + + ipmi_code = IPMI_CODE(opal_ipmi_msg->netfn >> 2, opal_ipmi_msg->cmd); + if ((ipmi_code == IPMI_CHASSIS_GET_SYS_BOOT_OPT_CMD) || + (opal_ipmi_msg->cmd == IPMI_CODE(opal_ipmi_msg->netfn >> 2, 0x1a)) || + (opal_ipmi_msg->cmd == IPMI_CODE(opal_ipmi_msg->netfn >> 2, 0x42))) { + prerror("OPAL IPMI: Command not supported\n"); + return OPAL_UNSUPPORTED; + } + + prlog(PR_TRACE, "%s - cmd: 0x%02x netfn: 0x%02x len: 0x%02llx\n", + __func__, opal_ipmi_msg->cmd, opal_ipmi_msg->netfn >> 2, + msg_len); + + switch (opal_ipmi_msg->cmd) { + case IPMI_GET_DEVICE_ID_CMD: + return opal_get_bmc_info(opal_ipmi_msg, msg_len); + + case IPMI_GET_DEVICE_GUID_CMD: + return opal_get_tid_req(opal_ipmi_msg, msg_len); + } + + return OPAL_UNSUPPORTED; +} + +static int64_t opal_ipmi_recv(uint64_t interface, + struct opal_ipmi_msg *opal_ipmi_msg, + __be64 *msg_len) +{ + struct ipmi_msg *msg; + int64_t rc; + + lock(&msgq_lock); + msg = list_top(&msgq, struct ipmi_msg, link); + + if (!msg) { + rc = OPAL_EMPTY; + goto out_unlock; + } + + if (opal_ipmi_msg->version != OPAL_IPMI_MSG_FORMAT_VERSION_1) { + prerror("OPAL IPMI: Incorrect version\n"); + rc = OPAL_UNSUPPORTED; + goto out_del_msg; + } + + if (interface != IPMI_DEFAULT_INTERFACE) { + prerror("IPMI: Invalid interface 0x%llx in %s\n", interface, __func__); + rc = OPAL_PARAMETER; + goto out_del_msg; + } + + if (be64_to_cpu(*msg_len) - sizeof(struct opal_ipmi_msg) < msg->resp_size + 1) { + rc = OPAL_RESOURCE; + goto out_del_msg; + } + + list_del(&msg->link); + if (list_empty(&msgq)) + opal_update_pending_evt(opal_event_ipmi_recv, 0); + unlock(&msgq_lock); + + opal_ipmi_msg->cmd = msg->cmd; + opal_ipmi_msg->netfn = msg->netfn; + opal_ipmi_msg->data[0] = msg->cc; + memcpy(&opal_ipmi_msg->data[1], msg->data, msg->resp_size); + + prlog(PR_TRACE, "%s - cmd: 0x%02x netfn: 0x%02x resp_size: 0x%02x\n", + __func__, msg->cmd, msg->netfn >> 2, msg->resp_size); + + /* Add one as the completion code is returned in the message data */ + *msg_len = cpu_to_be64(msg->resp_size + sizeof(struct opal_ipmi_msg) + 1); + free(msg); + + return OPAL_SUCCESS; + +out_del_msg: + list_del(&msg->link); + if (list_empty(&msgq)) + opal_update_pending_evt(opal_event_ipmi_recv, 0); + free(msg); + +out_unlock: + unlock(&msgq_lock); + return rc; +} + +void pldm_opal_init(void) +{ + struct dt_node *opal_ipmi, *opal_event = NULL; + + opal_ipmi = dt_new(opal_node, "ipmi"); + dt_add_property_strings(opal_ipmi, "compatible", "ibm,opal-ipmi"); + dt_add_property_cells(opal_ipmi, "ibm,ipmi-interface-id", + IPMI_DEFAULT_INTERFACE); + opal_event_ipmi_recv = opal_dynamic_event_alloc(); + dt_add_property_cells(opal_ipmi, "interrupts", + ilog2(opal_event_ipmi_recv)); + + opal_event = dt_find_by_name(opal_node, "event"); + if (opal_event) + dt_add_property_cells(opal_ipmi, "interrupt-parent", + opal_event->phandle); + + opal_register(OPAL_IPMI_SEND, opal_ipmi_send, 3); + opal_register(OPAL_IPMI_RECV, opal_ipmi_recv, 3); +} diff --git a/include/pldm.h b/include/pldm.h index db24040d..cb9cee08 100644 --- a/include/pldm.h +++ b/include/pldm.h @@ -59,4 +59,9 @@ int pldm_platform_send_progress_state_change( */ void pldm_rtc_init(void); +/** + * Register ipmi host interface access callbacks + */ +void pldm_opal_init(void); + #endif /* __PLDM_H__ */
OPAL_IPMI_SEND/RECV are used to retrieve and write IPMI requests. This support is needed for Linux driver. Only IPMI_GET_DEVICE_ID_CMD and IPMI_GET_DEVICE_GUID_CMD commands are supported. Signed-off-by: Christophe Lombard <clombard@linux.vnet.ibm.com> --- core/pldm/Makefile.inc | 2 +- core/pldm/pldm-opal.c | 291 +++++++++++++++++++++++++++++++++++++++++ include/pldm.h | 5 + 3 files changed, 297 insertions(+), 1 deletion(-) create mode 100644 core/pldm/pldm-opal.c