[PATCH v5 3/3] mpxy: Add MM source driver
Pawandeep Oza
pawandeep.oza at oss.qualcomm.com
Fri Oct 23 14:21:26 PDT 2026
From: Oza Pawandeep <pawandeep.oza at oss.qualcomm.com>
Add the MPXY MM source driver for forwarding RPMI Management Mode
requests through the MPXY request-forwarding bridge.
The driver:
- Registers the `opensbi,rpmi-mpxy-reqfwd-mm` FDT-compatible source.
- Defines MM service metadata for get attributes and communicate services.
- Builds request-forwarding responses for MM GET_ATTRIBUTES and
COMMUNICATE requests.
- Handles MM response completion and copies response payloads back to the
source buffer.
- Extracts and stores the MM shared-memory address and size from the
GET_ATTRIBUTES response.
- Registers the MM source with the Management Mode RPMI service group.
Signed-off-by: Oza Pawandeep <pawandeep.oza at oss.qualcomm.com>
---
lib/utils/mpxy/fdt_mpxy_bridge.c | 3 +
lib/utils/mpxy/mpxy_source_mm.c | 208 +++++++++++++++++++++++++++++++
lib/utils/mpxy/objects.mk | 2 +-
3 files changed, 212 insertions(+), 1 deletion(-)
create mode 100644 lib/utils/mpxy/mpxy_source_mm.c
diff --git a/lib/utils/mpxy/fdt_mpxy_bridge.c b/lib/utils/mpxy/fdt_mpxy_bridge.c
index ac44c3a6..4cf78b9b 100644
--- a/lib/utils/mpxy/fdt_mpxy_bridge.c
+++ b/lib/utils/mpxy/fdt_mpxy_bridge.c
@@ -30,7 +30,10 @@
#define SBI_MPXY_BRIDGE_PROP_CHAN "riscv,sbi-mpxy-channel-id"
+extern struct mpxy_bridge_source_driver mpxy_rpmi_mm_driver;
+
static const struct mpxy_bridge_source_driver *source_drivers[] = {
+ &mpxy_rpmi_mm_driver,
};
static uint16_t token = 0;
diff --git a/lib/utils/mpxy/mpxy_source_mm.c b/lib/utils/mpxy/mpxy_source_mm.c
new file mode 100644
index 00000000..1d19ba7d
--- /dev/null
+++ b/lib/utils/mpxy/mpxy_source_mm.c
@@ -0,0 +1,208 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Qualcomm, Inc
+ *
+ * Authors:
+ * Pawandeep Oza <pawandeep.oza at oss.qualcomm.com>
+ */
+
+#include <sbi_utils/mpxy/fdt_mpxy.h>
+#include <sbi_utils/mpxy/fdt_mpxy_bridge.h>
+#include <sbi_utils/mpxy/fdt_mpxy_rpmi.h>
+#include <sbi_utils/mailbox/rpmi_mailbox.h>
+
+static struct mpxy_rpmi_service_data mm_srvcdata[] = {
+ [0] = {
+ .id = RPMI_MM_SRV_ENABLE_NOTIFICATION,
+ .min_tx_len = sizeof(struct rpmi_enable_notification_req),
+ .max_tx_len = sizeof(struct rpmi_enable_notification_req),
+ .min_rx_len = sizeof(struct rpmi_enable_notification_resp),
+ .max_rx_len = sizeof(struct rpmi_enable_notification_resp),
+ },
+ [1] = {
+ .id = RPMI_MM_SRV_GET_ATTRIBUTES,
+ .min_tx_len = 0,
+ .max_tx_len = 0,
+ .min_rx_len = sizeof(struct rpmi_mm_get_attributes_rsp),
+ .max_rx_len = sizeof(struct rpmi_mm_get_attributes_rsp),
+ },
+ [2] = {
+ .id = RPMI_MM_SRV_COMMUNICATE,
+ .min_tx_len = sizeof(struct rpmi_mm_communicate_req),
+ .max_tx_len = sizeof(struct rpmi_mm_communicate_req),
+ .min_rx_len = sizeof(struct rpmi_mm_communicate_rsp),
+ .max_rx_len = sizeof(struct rpmi_mm_communicate_rsp),
+ },
+};
+
+static struct rpmi_mm_shmem_info {
+ u64 addr;
+ u32 size;
+} mm_shmem;
+
+static int mpxy_rpmi_build_reqfwd_resp(struct mpxy_bridge_src_ctx *src,
+ struct mpxy_bridge_dst_ctx *dst,
+ const u8 *data, u32 data_len)
+{
+ struct rpmi_request_forward_resp *resp;
+ u32 hdr_len = sizeof(struct rpmi_message_header);
+ u32 avail;
+ u32 offset;
+ u32 returned;
+ int ret = SBI_OK;
+
+ do {
+ resp = (struct rpmi_request_forward_resp *)dst->respbuf;
+ offset = dst->start_index;
+ avail = dst->resp_bufsize - sizeof(*resp);
+
+ if (offset > data_len) {
+ ret = SBI_EINVAL;
+ break;
+ }
+
+ if (offset == 0) {
+ if (avail <= hdr_len) {
+ ret = SBI_EINVAL;
+ break;
+ }
+ avail -= hdr_len;
+ }
+
+ returned = data_len - offset;
+ if (returned > avail)
+ returned = avail;
+
+ resp->status = RPMI_SUCCESS;
+
+ if (offset == 0) {
+ sbi_memcpy(resp->data, (u8 *)&src->header, hdr_len);
+ sbi_memcpy(resp->data + hdr_len, data, returned);
+ resp->returned = hdr_len + returned;
+ resp->remaining = data_len - returned;
+ *dst->resp_len_ptr = sizeof(*resp) + hdr_len + returned;
+ } else {
+ sbi_memcpy(resp->data, data + offset, returned);
+ resp->returned = returned;
+ resp->remaining = data_len - offset - returned;
+ *dst->resp_len_ptr = sizeof(*resp) + returned;
+ }
+ } while (0);
+
+ if (ret) {
+ resp->status = RPMI_ERR_INVALID_PARAM;
+ resp->returned = 0;
+ resp->remaining = 0;
+ }
+
+ return ret;
+}
+
+static int mpxy_rpmi_mm_xfer(struct mpxy_bridge_src_ctx *src,
+ struct mpxy_bridge_dst_ctx *dst)
+{
+ if (!src || !src->msgbuf || !dst || !dst->respbuf || !dst->resp_len_ptr)
+ return SBI_EINVAL;
+
+ switch (src->header.service_id) {
+ case RPMI_MM_SRV_GET_ATTRIBUTES:
+ return mpxy_rpmi_build_reqfwd_resp(src, dst, NULL,
+ mm_srvcdata[RPMI_MM_SRV_GET_ATTRIBUTES - 1].min_tx_len);
+
+ case RPMI_MM_SRV_COMMUNICATE:
+ return mpxy_rpmi_build_reqfwd_resp(src, dst, (const u8 *)src->msgbuf,
+ mm_srvcdata[RPMI_MM_SRV_COMMUNICATE - 1].min_tx_len);
+
+ default:
+ return SBI_ENOTSUPP;
+ }
+}
+
+static int mpxy_rpmi_get_payload(void *msgbuf, u32 msg_len,
+ const u8 **payload, u32 *payload_len)
+{
+ struct rpmi_message_header *hdr;
+ u32 len;
+
+ hdr = (struct rpmi_message_header *)msgbuf;
+ len = (u32)le16_to_cpu(hdr->datalen);
+
+ *payload = (const u8 *)msgbuf + sizeof(struct rpmi_message_header);
+ *payload_len = len;
+
+ return SBI_OK;
+}
+
+static int mpxy_rpmi_copy_payload(struct mpxy_bridge_src_ctx *src,
+ const u8 *payload, u32 payload_len)
+{
+ sbi_memcpy((u8 *)src->respbuf, payload, payload_len);
+ src->resp_length = payload_len;
+
+ return SBI_OK;
+}
+
+static int mpxy_rpmi_mm_complete(struct mpxy_bridge_src_ctx *src,
+ void *msgbuf, u32 msg_len)
+{
+ const u8 *payload;
+ u32 payload_len;
+ int ret;
+
+ ret = mpxy_rpmi_get_payload(msgbuf, msg_len,
+ &payload, &payload_len);
+ if (ret)
+ return ret;
+
+ switch (src->header.service_id) {
+ case RPMI_MM_SRV_GET_ATTRIBUTES:
+ struct rpmi_mm_get_attributes_rsp *attr_rsp;
+ attr_rsp = (struct rpmi_mm_get_attributes_rsp *)payload;
+
+ mm_shmem.addr = ((u64)le32_to_cpu(attr_rsp->mma.shmem_addr_hi) << 32) |
+ (u64)le32_to_cpu(attr_rsp->mma.shmem_addr_lo);
+ mm_shmem.size = le32_to_cpu(attr_rsp->mma.shmem_size);
+ attr_rsp->status = RPMI_SUCCESS;
+ break;
+
+ case RPMI_MM_SRV_COMMUNICATE:
+ break;
+
+ default:
+ return SBI_ENOTSUPP;
+ }
+
+ ret = mpxy_rpmi_copy_payload(src, payload, payload_len);
+ if (ret)
+ return ret;
+
+ return SBI_OK;
+}
+
+static const struct mpxy_bridge_source_ops mm_ops = {
+ .xfer = mpxy_rpmi_mm_xfer,
+ .complete = mpxy_rpmi_mm_complete,
+};
+
+static const struct fdt_match mm_match[] = {
+ {
+ .compatible = "opensbi,rpmi-mpxy-reqfwd-mm",
+ },
+ { }
+};
+
+static int mpxy_rpmi_mm_probe(const void *fdt, int nodeoff,
+ const struct fdt_match *match)
+{
+ (void)match;
+
+ sbi_printf("%s\n", __func__);
+ return mpxy_bridge_register_source(fdt, nodeoff, &mm_ops, mm_srvcdata,
+ array_size(mm_srvcdata), RPMI_SRVGRP_MANAGEMENT_MODE);
+}
+
+const struct mpxy_bridge_source_driver mpxy_rpmi_mm_driver = {
+ .match_table = mm_match,
+ .probe = mpxy_rpmi_mm_probe,
+};
\ No newline at end of file
diff --git a/lib/utils/mpxy/objects.mk b/lib/utils/mpxy/objects.mk
index 0ba79d59..09c2a313 100644
--- a/lib/utils/mpxy/objects.mk
+++ b/lib/utils/mpxy/objects.mk
@@ -34,4 +34,4 @@ carray-fdt_mpxy_drivers-$(CONFIG_FDT_MPXY_RPMI_LOGGING) += fdt_mpxy_rpmi_logging
libsbiutils-objs-$(CONFIG_FDT_MPXY_RPMI_LOGGING) += mpxy/fdt_mpxy_rpmi_logging.o
carray-fdt_mpxy_drivers-$(CONFIG_FDT_MPXY_BRIDGE) += fdt_mpxy_bridge
-libsbiutils-objs-$(CONFIG_FDT_MPXY_BRIDGE) += mpxy/fdt_mpxy_bridge.o
+libsbiutils-objs-$(CONFIG_FDT_MPXY_BRIDGE) += mpxy/fdt_mpxy_bridge.o mpxy/mpxy_source_mm.o
--
2.43.0
More information about the opensbi
mailing list