[PATCH v6 3/3] mpxy: Add MM source driver
Pawandeep Oza
pawandeep.oza at oss.qualcomm.com
Mon Nov 2 15:40:06 PST 2026
On Sun, Nov 1, 2026 at 4:32 AM Anup Patel <anup at brainfault.org> wrote:
>
> On Mon, Oct 26, 2026 at 9:44 PM Pawandeep Oza
> <pawandeep.oza at oss.qualcomm.com> wrote:
> >
> > 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,
> > };
>
> Once we move to carray based source driver array, no change will be
> needed in fdt_mpxy_rpmi_bridge.c
Oza: I already tried that but that will tie it with the opensbi driver
framework - while we want to
tie it with bridge driver so that probe can be called from there.
>
> >
> > 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
>
> This source file should be named fdt_mpxy_rpmi_bridge_mm.c
oza: done
>
> > @@ -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;
>
> Why not directly do "return mpxy_rpmi_copy_payload(src, payload,
> payload_len);" ?
oza: yes
>
> > +
> > + 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__);
>
> Drop this sbi_printf()
oza: yes
>
> > + 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
>
> Remove this "\No newline at end of file"
Oza: I dont see it - let me add new line at the end though.
>
> > 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
>
> This will look quite different with carray.
>
> Also, a separate Kconfig opiton FDT_MPXY_RPMI_BRIDGE_MM is needed so
> that MM based bridge source can be disabled.
I tried that - there was some issue with that I think - may be in the
next patch when I add tee source driver let me attempt that ?
>
> Regards,
> Anup
More information about the opensbi
mailing list