I want to get data from a DMA enabled, PCIe hardware device into user-space as quickly as possible.
Q: How do I combine "direct I/O to user-space with/and/via a DMA transfer"
Reading through LDD3, it seems that I need to perform a few different types of IO operations!?
dma_alloc_coherent
gives me the physical address that I can pass to the hardware device. But would need to have setupget_user_pages
and perform acopy_to_user
type call when the transfer completes. This seems a waste, asking the Device to DMA into kernel memory (acting as buffer) then transferring it again to user-space. LDD3 p453:/* Only now is it safe to access the buffer, copy to user, etc. */
What I ideally want is some memory that:
- I can use in user-space (Maybe request driver via a ioctl call to create DMA'able memory/buffer?)
- I can get a physical address from to pass to the device so that all user-space has to do is perform a read on the driver
- the read method would activate the DMA transfer, block waiting for the DMA complete interrupt and release the user-space read afterwards (user-space is now safe to use/read memory).
Do I need single-page streaming mappings, setup mapping and user-space buffers mapped with get_user_pages
dma_map_page
?
My code so far sets up get_user_pages
at the given address from user-space (I call this the Direct I/O part). Then, dma_map_page
with a page from get_user_pages
. I give the device the return value from dma_map_page
as the DMA physical transfer address.
I am using some kernel modules as reference: drivers_scsi_st.c
and drivers-net-sh_eth.c
. I would look at infiniband code, but cant find which one is the most basic!
Many thanks in advance.