title: Linux kernel device driver to DMA from a device into user-space memory
body: <p>I want to get data from a DMA enabled, PCIe hardware device into user-space as quickly as possible.</p>
  
  <p>Q: How do I combine "direct I/O to user-space with/and/via a DMA transfer"</p>
  
  <ol>
  <li><p>Reading through LDD3, it seems that I need to perform a few different types of IO operations!?  </p>
  
  <p><code>dma_alloc_coherent</code> gives me the physical address that I can pass to the hardware device.
  But would need to have setup <code>get_user_pages</code> and perform a <code>copy_to_user</code> 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: <code>/* Only now is it safe to access the buffer, copy to user, etc. */</code></p></li>
  <li><p>What I ideally want is some memory that:</p>
  
  <ul>
  <li>I can use in user-space (Maybe request driver via a ioctl call to create DMA'able memory/buffer?)  </li>
  <li>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  </li>
  <li>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).</li>
  </ul></li>
  </ol>
  
  <p>Do I need single-page streaming mappings, setup mapping and user-space buffers mapped with <code>get_user_pages</code> <code>dma_map_page</code>?</p>
  
  <p>My code so far sets up <code>get_user_pages</code> at the given address from user-space (I call this the Direct I/O part). Then, <code>dma_map_page</code> with a page from <code>get_user_pages</code>. I give the device the return value from <code>dma_map_page</code> as the DMA physical transfer address.</p>
  
  <p>I am using some kernel modules as reference: <code>drivers_scsi_st.c</code> and <code>drivers-net-sh_eth.c</code>. I would look at infiniband code, but cant find which one is the most basic!</p>
  
  <p>Many thanks in advance.</p>