[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