This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RPMSG Maximum Message Size

Hello,

I'm trying to increase the RPMSG message buffer size in virtio_rpmsg_bus.c by modifying the following definitions: RPMSG_NUM_BUFS (512) and RPMSG_BUF_SIZE (512). I understand that the total allocated memory can not change, so I want to change the size to 2048 and the number of buffers to 128 After making these changes and rebuilding the kernel, I'm still receiving the "message is too big (512, 2032)" error message. I did add a check that verified the actual value of RPMSG_BUF_SIZE, so maybe the size of 512 is hardcoded elsewhere...

The len of 512 is sourced from the function "virtqueue_get_buf(rvq, &len)." The buffers seems to be created by the following code snippet in the same driver:

sg_init_one(&sg, cpu_addr, RPMSG_BUF_SIZE);
err = virtqueue_add_buf(vrp->rvq, &sg, 0, 1, cpu_addr, GFP_KERNEL)

Did I miss something? I'm using Kernel 3.8.12 from GLSDK 6.04.00.02 for the OMAP54xEVM.

  • michael clark said:
    I'm still receiving the "message is too big (512, 2032)" error message.

    What are the values being printed in the parens above?

    I ask because the code from the repo just prints the len:

            if (len > RPMSG_BUF_SIZE - sizeof(struct rpmsg_hdr)) {
                    dev_err(dev, "message is too big (%d)\n", len);
                    return -EMSGSIZE;
            }

    So, assuming one of them is the len, it would make sense that the other value is (RPMSG_BUF_SIZE - sizeof(struct rpmsg_hdr)), and 2032 looks like it would be that if you changed RPMSG_BUF_SIZE to 2048.  If that is the case, then this message shouldn't have even been printed, since len of 512 is *not* > 2032.

    Regardless, it is not enough to just change the Linux side.  The other side of the Ipc communication is a remote core, handled by Ipc code in <ipcproduct>/packages/ti/ipc/rpmsg/RPMessage.c.  And it is not enough just to change size and number-of-buffers macros on the remote core side, there would be other places that also need to change.

    When customers want to use Ipc to send more data than can fit in a MessageQ buffer payload, we generally point them to CMEM and advise that they CMEM_alloc() their big buffer and pass the physical address of that buffer to the remote core using a small MessageQ buffer that contains that physical pointer.  They then use Resource_physToVirt() to convert to a remote core virtual address (if needed, sometimes just the physical address is enough if they're giving the buffer to HW).\

    Let us know if you need help exploring the CMEM solution, we can offer a few more details that would help.

    Regards,

    - Rob

     

  • Hi Rob,

    I think you referenced code from "rpmsg_send_offchannel_raw." Please see the function "rpmsg_recv_single," which is where the warning is emitted. I simply don't understand why the buffer length is reported as 512 when they are allocated as 2048 in function "rpmsg_probe". I'll continue reviewing the code and DSP/IPC side.

    /* half of the buffers is dedicated for RX */
    vrp->rbufs = bufs_va;
    
    /* and half is dedicated for TX */
    vrp->sbufs = bufs_va + total_buf_space / 2;
    
    /* set up the receive buffers */
    for (i = 0; i < vrp->num_bufs / 2; i++) {
         struct scatterlist sg;
         void *cpu_addr = vrp->rbufs + i * RPMSG_BUF_SIZE;
    
         sg_init_one(&sg, cpu_addr, RPMSG_BUF_SIZE);
    
         err = virtqueue_add_inbuf(vrp->rvq, &sg, 1, cpu_addr,
                                                         GFP_KERNEL);
        WARN_ON(err); /* sanity check; this can't really happen */
    }

    I only wanted to do this as a temporary solution and exercise, and I'm aware of the CMEM solution. In the near future, I was also planning to write a Linux driver to read/write to a DSP memory section, which would then extend to a larger CMEM section. I'm less familiar with the Linux side, so any help (code examples) would be appreciated. My intention is to stream "files" between the ARM/DSP in both directions, where the file size is around 10 MB. For now the desired transfer rate is about 3MB/s.

    Thanks!

  • michael clark said:
    I think you referenced code from "rpmsg_send_offchannel_raw."

    I ended up in that function because your original post had "message is too big (512, 2032)", but I was confused that there were 2 parameters printed.

    michael clark said:
    Please see the function "rpmsg_recv_single," which is where the warning is emitted

    OK, that makes more sense, although that particular function prints "inbound msg too big: (%d, %d)".  Here's the code:

            if (len > RPMSG_BUF_SIZE ||
                    msg->len > (len - sizeof(struct rpmsg_hdr))) {
                    dev_warn(dev, "inbound msg too big: (%d, %d)\n", len, msg->len);
                    return -EINVAL;
            }

    So, we can see that this message is printed because msg->len (2032) > (len - sizeof(struct rpmsg_hdr)) (something < 512).

    michael clark said:
    I simply don't understand why the buffer length is reported as 512 when they are allocated as 2048 in function "rpmsg_probe".

    The 'len' in this case was retrieved from the vring buffer itself, which was written by the SYS/BIOS-side sender using RPMessage, probably via this code from the RPMessage_send() function in <ipc>/packages/ti/ipc/rpmsg/RPMesage.c:

                VirtQueue_addUsedBuf(transport.virtQueue_toHost, token,
                                                                RPMSG_BUF_SIZE);
                VirtQueue_kick(transport.virtQueue_toHost);

    You may have already determined this for yourself since you said you were going to review the code on the DSP/IPC side.

    michael clark said:
    In the near future, I was also planning to write a Linux driver to read/write to a DSP memory section, which would then extend to a larger CMEM section

    There isn't really a kernel (i.e., Linux driver) interface for CMEM.  The CMEM kernel driver is for use by the CMEM user-level API library.  I think that's the best solution for you.

    Regards,

    - Rob