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.

Using CMEM buffer for dma transfer by a linux driver

Hi there,

Am working with the CMEM allocated buffers which are passed on by the codec engine with coded video frames.

Trying is to transmit the frames without additional copying from CMEM buffer to kernel bufffer. On an earlier enquiry, it was confirmed that DMA over CMEM is feasible, provided the kernel supports highmem. Although it is not a straight forward/usual way of enabling DMA, would like to check if it can lead to increase in end-to-end frame rate.

Here is the partial memory layout:

   Region        : Start-End
   DMA             : X- Y
   vmalloc       : C + 0x800000 - D 
   lowmem     : B - C  
   pkmap        : A- B 

CMEM maps its entire region into kernel virtual address space using ioremap, during the start-up.  Lets say that it is mapped at the address C + 0x2000000 (vmalloc region), for example. Here is whats done so far:

First step: Enabled the DMA mode for the linux driver. Transferring data out data using dma_alloc_coherent allotted buffers (from the DMA region) done successfully. Driver is  initialized successfully, able to connect.

Second step: Enabled the Highmem support along with 2nd - level page tables option.

At this point, am trying to map the CMEM buffer into kernel lowmem space using kmap before passing it to the driver controller. The driver controller will later synchronize the buffer for dma transfer (using dma_map_single or dma_sync_single_for_device).

Note: The value of kernel variable high_memory is set to value C (vmalloc region start), as expected. The kmap is not called in any interrupt context. CMEM buffers appear page aligned.

Mapping the CMEM buffer using kmap is failing most of the times, but not always. When kmap succeeds, result is a pointer in the pkmap region A- B. And when it fails, it is because of boundary check function PageHighMem although the page is still in highmem region.

 Not sure what is causing this behavior. Should there be forced change in the zone definitions (ZONE_HIGHMEM)? Use alloc_pages instead?

On a general note, is it advisable to use this method(DMA transfer from CMEM area on ARM Linux)? Given the overhead (highmem), are there any observations noted on performance, stability?

Looking for suggestions or alternatives.

Thanks,

Shreya

  • Not sure if the CMEM area can be considered as highmem. And its already mapped to kernel virtual address space with ioremap. Dont know  for what purpose highmem support is needed for.

    So, how can the CMEM buffers be made DMA accessible?

  • Hi,

    "CMEM_alloc" returns virtual addres of CMEM buffer, then you can use "CMEM_getPhys",
    to get physical addres of that contiguous buffer, which  can then be used in DMA transfer.

    CMEM_AllocParams  prm;
    prm.type      = CMEM_HEAP;
    prm.flags     = CMEM_CACHED;//CMEM_NONCACHED;
    prm.alignment = 32;//128
    bufInfo->virtAddr = (Uint8*)CMEM_alloc(bufSize,&prm);
    bufInfo->physAddr = (Uint8*)CMEM_getPhys(bufInfo->virtAddr);

    ....
    //DMA:
     copy2D.srcPhysAddr = (unsigned long)bufInfo->physAddr;

    ------
    Regards.

     

  • Hi,

    This driver is in kernel mode. And am tweaking the video frame buffer in kernel context just before dispatching it to for DMA transfer.

    Its working with few quick fixes.

    I could not get around the boundary check in the DMA module. So, I have disabled it for now. I would like to revert this change, by defining the right upper boundary. Which is in the kernel variable high_memory  and is currently being set to value C (vmalloc region start). But I believe it should be set to D instead  (vmalloc region end). Any thoughts on that?

    Here is the partial memory layout:

       Region        : Start-End
       DMA             : X- Y
       vmalloc       : C + 0x800000 - D 
       lowmem     : B - C  
       pkmap        : A- B

    Thanks,

    Shreya