Search code examples
linuxlinux-kernelpoolrestrictiondma

How can I allocate dma buffers in a very specific range in linux kernel?


I have a microprocessor which can access only 0xFFFFFF bytes in the DDR through its data cache. I can give it the offset where it can start to read these 0xFFFFFF the DDR

I want to allocate dma buffers for it.

I saw that I can give a mask to restrict the place these dma buffers can be allocated.

How can I know where the allocation will start for the dma_coherent_alloc to set the offset for the microprocessor?

Are there any other solutions ? Like allocating a big buffer and then do some suballocation in it (I don't know if the kernel already has some facilities for that)

Thanks in advance.


Solution

  • If you want to allocate in a specific region, you can reserve this memory in the device tree and use it through the DMA-API (dma_alloc_coherent for example)

    In your device tree:

    reserved-memory {
          #address-cells = <2>;
          #size-cells = <2>;
          ranges;
      
          reserved: buffer@0 {
             compatible = "shared-dma-pool"; // to be able to access this memory throught the DMA-API
             no-map;
             reg = <0x0 0x70000000 0x0 0x10000000>;
          };
       };
      
       reserved-driver@0 {
          compatible = "xlnx,reserved-memory";
          memory-region = <&reserved>;
       };
    

    In your device driver:

      /* Initialize reserved memory resources */
      rc = of_reserved_mem_device_init(dev);
      if(rc) {
        dev_err(dev, "Could not get reserved memory\n");
        goto error1;
      }
    
      /* Allocate memory */
      dma_set_coherent_mask(dev, 0xFFFFFFFF);
      lp->vaddr = dma_alloc_coherent(dev, ALLOC_SIZE, &lp->paddr, GFP_KERNEL);
      dev_info(dev, "Allocated coherent memory, vaddr: 0x%0llX, paddr: 0x%0llX\n", (u64)lp->vaddr, lp->paddr);
    

    Great explanation of how this works: https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18841683/Linux+Reserved+Memory