[PATCH v6 3/3] mpxy: Add MM source driver

Anup Patel anup at brainfault.org
Sun Nov 1 04:32:35 PST 2026


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

>
>  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

> @@ -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);" ?

> +
> +       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()

> +       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"

> 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.

Regards,
Anup



More information about the opensbi mailing list