Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DMA and I/O memory region under Linux

I'm writing this because I have some doubts about the behaviour of DMA. I'm reading about the PCI layout and how the device drivers interacts with the card, and I read about DMA. Since I understood, PCI cards doesn't have a DMA controller, instead of that they request to be a master of the bus, and then they are able to take a DMA address and do transfers between memory and device ( through the bus ).

This DMA address is a portion of RAM, actually it's a physical address and before do nothing you need to convert that in something that your drivers can use, like a kernel virtual memory. I've checked that with this code:

    /* Virtual kernel address */
    kernel_buff = pci_alloc_consistent(dev, PAGE_SIZE, &dma_addr);

    pr_info("Kernel buffer - %12p , Dma_addr - %12p\n", kernel_buff, (void *)dma_addr );
    pr_info( "Kernelbuffer - dma_addr - %12p\n", kernel_buff - dma_addr);

    strcpy(kernel_buff, "Test dma\n");

    /* Test memory */

    ptest = (void *)dma_addr;
    ptest = phys_to_virt((unsigned long)ptest);

    pr_info("Ptest virtual memory(%p) containts - %s\n", ptest, (char *)ptest);

And the output was:

[425971.835669] Kernel buffer - ffff8800ca70a000 , Dma_addr -     ca70a000
[425971.835671] Kernelbuffer - dma_addr - ffff880000000000
[425971.835673] Ptest virtual memory(ffff8800ca70a000) containts - Test dma

This is how I understood that DMA is a portion of RAM.

My doubt is about how this transfer is made. I mean, every time that I write in this buffer, the data that the buffer constains will be transfered to the device? Or only the adress of the memory location, and then the device will read from this location?

This is about DMA.

And about I/O memory maps:

When we request a I/O memory region of the device with for example:

pci_resource_start

We are requesting the region of the memory where device's registers is located? So in this way we have this memory location into the RAM ? And we wan write/read as a normal memory locations.

And the final point is that, we use DMA because the I/O memory mapping only allows few bytes per cycle since this process involves the CPU, right? So we can transfer amounts of data between memory locations( RAM and bus of device) without the cpu.

like image 710
leberus Avatar asked Aug 06 '14 13:08

leberus


People also ask

What is DMA in Linux?

Direct memory access, or DMA, is the advanced topic that completes our overview of memory issues. DMA is the hardware mechanism that allows peripheral components to transfer their I/O data directly to and from main memory without the need for the system processor to be involved in the transfer.

Does Linux use DMA?

So that Linux can use the dynamic DMA mapping, it needs some help from the drivers, namely it has to take into account that DMA addresses should be mapped only for the time they are actually used and unmapped after the DMA transfer. The following API will work of course even on platforms where no such hardware exists.

Is DMA memory-mapped IO?

Not exactly. DMA is when two devices that aren't the CPU use the memory bus to communicate (with one device usually being main memory, and the process being orchestrated by the CPU). Memory-mapped IO is the CPU talking to device on the memory bus that is not main memory.

What is DMA able memory?

Many devices can temporarily take control of the bus and perform data transfers to (and from) main memory or other devices. Because the device is doing the work without the help of the CPU, this type of data transfer is known as direct memory access (DMA).


1 Answers

The steps involved to transfer the data to the device could be summarized as follows :

  1. Assume that you have the data in a buffer.
  2. The driver creates a DMA mapping for this buffer (say using pci_alloc_consistent() or the newer dma_alloc_coherent()), and returns the corresponding DMA bus address.
  3. This DMA bus address is to be informed to the device. This is done by writing into the correct DMA registers of the device through writel() (assuming that the device registers are memory mapped).
  4. The device also needs to be informed about the amount of data that is being transferred and such (by writing to the appropriate registers of the device using writel())
  5. Now issue the command to the device to start the DMA transactions by writing to one of its control registers (again possibly using writel()).
  6. Once the data transaction is completed, the device issues an interrupt.
  7. In the interrupt handler, the driver may unallocate the buffer which was used for transaction and might as well perform DMA unmapping.

And there you have it.. The data is transferred to the device!

Now coming to the question regarding the IO memory maps :

First of all when we call pci_resource_start(), we do not "request" the IO ports. This is the way by which we are just gathering info. about the ports. The request is done using pci_request_regions(). To be specific to your questions :

We are requesting the region of the memory where device's registers is located?

Using this, we are requesting the kernel to give access to this region of memory (memory mapped ports) where the device's registers are located.

So in this way we have this memory location into the RAM ?

No, we do not have this memory location in RAM, it is only memory mapped, which means that the device shares the same address, data and control lines with the RAM and hence, same instruction that are used to access the RAM can also be used to access the device registers.

You've answered your last question yourself. DMA provides huge amounts to data to be transferred efficiently. But, there are cases where you need to use the memory mapping to transfer the data. The best example is already stated in the explanation of DMA transaction process, where, you need to transfer the address and control information to the device. This could be done only through memory mapped IO.

Hope this helps.

like image 64
raghav3276 Avatar answered Oct 04 '22 18:10

raghav3276