"How to obtain the physical address of the space allocated by NVBUF_MEM_SURFACE_ARRAY?"

Hi, I encountered some issues. My requirement is to write a custom UI image into the memory of NVBUF_MEM_SURFACE_ARRAY and then pass this address to the FPGA for DMA transfer. However, I am unable to obtain the physical address of the NVBUF_MEM_SURFACE_ARRAY memory. I used to do this on the IMX8 development board, but now I need to switch platforms. How should I proceed? Thank you very much.

Error log:
[ 224.877369] Failed to attachement -12
[ 224.882494] 12
[ 224.882504] got dmabuf 00000000e815829f nvmap_dmabuf
[ 224.882575] Failed to attachement -12
[ 224.887076] 14
[ 224.887085] got dmabuf 000000004402ac59 nvmap_dmabuf
[ 224.887156] Failed to attachement -12
[ 224.891731] 16
[ 224.891740] got dmabuf 00000000e9ed1f60 nvmap_dmabuf
[ 224.891819] Failed to attachement -12
[ 224.896304] 18
[ 224.896313] got dmabuf 00000000cf2f2a57 nvmap_dmabuf
[ 224.896378] Failed to attachement -12

C++:
void NVBuffAllocTest::TestAlloc(int iWidth, int iHeight)
{
int testfd = open(“/dev/test”, O_RDWR);
if (testfd < 0)
{
std::cout<<“open /dev/test fail:”<<strerror(errno)<<std::endl;
return;
}
static int alloccnt = 0;

while (alloccnt < 10)
{
    alloccnt++;
    NvBufSurf::NvCommonAllocateParams allocParams;
    allocParams.width = iWidth;
    allocParams.height = iHeight;
    //    allocParams.layout = NVBUF_LAYOUT_BLOCK_LINEAR;
    allocParams.layout = NVBUF_LAYOUT_PITCH;
    allocParams.memType = NVBUF_MEM_SURFACE_ARRAY;
    allocParams.colorFormat = NVBUF_COLOR_FORMAT_ARGB;
    allocParams.memtag = NvBufSurfaceTag_VIDEO_ENC;
    //    allocParams.memtag = NvBufSurfaceTag_JPEG;

    int iDmaBufFd = -1;
    int iRet = NvBufSurf::NvAllocate(&allocParams, 1, &iDmaBufFd);
    if(iRet)
    {
        std::cout<<"Error in creating the input buffer."<<std::endl;
        if (testfd > 0)
        {
            close(testfd);
            testfd = -1;
        }
        return;
    }
    else
    {
        std::cout<<"the fd of the input buffer is:"<<iDmaBufFd<<std::endl;
    }
    NvBufSurface nvbuf_surf1;
    nvbuf_surf1.isContiguous = true;
    NvBufSurface *nvbuf_surf = &nvbuf_surf1;
    NvBufSurfaceAllocateParams input_params = {{0}};

    input_params.params.width = iWidth;
    input_params.params.height = iHeight;
    input_params.params.isContiguous = true;
    input_params.params.memType = NVBUF_MEM_SURFACE_ARRAY;
    input_params.params.layout = NVBUF_LAYOUT_PITCH;
    input_params.params.colorFormat = NVBUF_COLOR_FORMAT_ARGB;
    input_params.memtag = NvBufSurfaceTag_VIDEO_CONVERT;
    iRet = NvBufSurfaceAllocate(&nvbuf_surf, 1, &input_params);
    //iRet = NvBufSurfaceFromFd(iDmaBufFd, (void**)(&nvbuf_surf));
    std::cout<<"the buff batchsize:"<<nvbuf_surf->batchSize<<",isContiguous:"<<nvbuf_surf->isContiguous<<std::endl;
    NvBufSurfaceParams surfacePara = nvbuf_surf->surfaceList[0];
    std::cout<<"dataSize:"<<surfacePara.dataSize<<" "<<surfacePara.paramex<<std::endl;
    NvBufSurfaceParamsEx exSurfacePara = surfacePara.paramex[0];
    std::cout<<"phy addr:"<<exSurfacePara.planeParamsex.physicaladdress[0]<<std::endl;


    int buf = iDmaBufFd;
    write(testfd, &buf, sizeof(int));

}
if (testfd > 0)
{
    close(testfd);
    testfd = -1;
}

}

driver:
static ssize_t demo_write(struct file *fp, const char __user *buf, size_t size, loff_t *pos)
{
int rc;
int iTestFd = -1;

rc = copy_from_user(&iTestFd, buf, sizeof(int));
if(rc < 0) {
    return -EFAULT;
    pr_err("copy_from_user failed!");
}
printk(KERN_DEBUG"%d\n", iTestFd);
importer_read(iTestFd);
return size;

}
static int importer_read(int dmabuf_fd)
{
struct dma_buf_attachment *attachment;
struct sg_table *sgt;
struct scatterlist *sg;
unsigned int si;
struct device *dev;
struct dma_buf *dmabuf;
int err;

dmabuf = dma_buf_get(dmabuf_fd); //share bug between sub devices
if (IS_ERR(dmabuf)) {
        err = PTR_ERR(dmabuf);
        printk(KERN_DEBUG"got dmabuf fail %d\n", err);
        goto err_buf_get;
}



printk(KERN_DEBUG"got dmabuf %p %s\n", dmabuf, dmabuf->exp_name);

dev = kzalloc(sizeof(*dev), GFP_KERNEL);
dev_set_name(dev, "try_get_sg");

attachment = dma_buf_attach(dmabuf, dev);
if (IS_ERR(attachment)) {
        err = PTR_ERR(attachment);
        printk(KERN_DEBUG"Failed to attach %d\n", err);
        goto err_buf_attach;
}

sgt = dma_buf_map_attachment(attachment, DMA_BIDIRECTIONAL);
if (IS_ERR(sgt)) {
        err = PTR_ERR(sgt);
        printk(KERN_DEBUG"Failed to attachement %d\n", err);
        goto err_buf_attachment;
}

printk(KERN_DEBUG"got sg->nents %d\n", sgt->nents);
printk(KERN_DEBUG"got sg->orig_nents %d dma_buf->size=%ld/%lx\n",
        sgt->orig_nents, dmabuf->size, dmabuf->size);

for_each_sg(sgt->sgl, sg, sgt->orig_nents, si) {
        dma_addr_t sg_addr = sg_dma_address(sg);
        u32 sg_len = sg_dma_len(sg);
        printk(KERN_DEBUG"sgt[%d] sg_addr = 0x%lx, sg_len = %d/%#x sg_phys= %#llx\n",
                        si,
                        (unsigned long)sg_addr, sg_len, sg_len,
                        (unsigned long long)sg_phys(sg));
}

dma_buf_unmap_attachment(attachment, sgt, DMA_BIDIRECTIONAL);

err_buf_attachment:
dma_buf_detach(dmabuf, attachment);

err_buf_attach:
dma_buf_put(dmabuf);

err_buf_get:

kfree(dev);
return err;

}

I referred to this issue.

How to get physical address from the dmabuf_fd?

Hi,
We don’t support it on default Jetpack release. Generally we will encode the frame data into H264/H265 and steam out through RTSP or UDP. Would suggest use this method.

Or you may try this:

GitHub - NVIDIA/jetson-rdma-picoevb: Minimal HW-based demo of GPUDirect RDMA on NVIDIA Jetson AGX Xavier running L4T

Thanks.I will try.

The suggested methods were tested, but there seem to be compilation issues, which might be platform-related. Due to certain project requirements, we might not adopt the above-mentioned approach. Currently, we are considering rewriting the driver. Could you provide some references or guidance? Are there any documents I can refer to for understanding the memory management mechanism of Jetson?