Re: [PATCH 1/1] Userspace I/O (UIO): Documentatin for userspace DMA support
flat view
From: Michael Kerrisk <hidden>
Date: 2008-12-04 13:14:54
Also in:
lkml
Edward, A few small comments below On Wed, Dec 3, 2008 at 11:53 PM, Edward Estabrook [off-list ref] wrote:
From: Edward Estabrook <redacted> Here is a patch updating the Userspace IO documentation to detail support to dynamically allocate and use coherent DMA from userspace. This patch applies against 2.6.28-rc6. The gist of this implementation is to overload uio's mmap
Sometimes you write "uio", sometimes "UIO". Use just one?
functionality to allocate and map a new DMA region on demand. The bus-specific DMA address as returned by dma_alloc_coherent() is made available to userspace in the 1st long word
Perhaps use a clearer term than "long word"? Maybe '8 bytes'?
of the newly created region (as well as through the conventional 'addr' file in sysfs). The kernel-api change is that passing an offset value of 0xFFFFF000UL to a uio
s/api/API/
device's mmap() operation will dynamically allocate a DMA region. This cannot
break existing code as the previous UIO code only allowed a maximum of 5
mappings.
To allocate a DMA region you use the following:
/* Pass this magic number to mmap as offset to
* dynamically allocate a chunk of memory */
#define DMA_MEM_ALLOCATE_MMAP_OFFSET 0xFFFFF000UL
void* memory = mmap (NULL, size, PROT_READ | PROT_WRITE , MAP_SHARED,
fd, DMA_MEM_ALLOCATE_MMAP_OFFSET);
u_int64_t *addr = *(u_int64_t *) memory;
where 'size' is the size in bytes of the region you want and fd is thes/fd/'fd'/ (consistent with 'size')
opened /dev/uioN file. Allocation occurs in page sized pieces by design to ensure that
s/page sized pieces/page-sized pieces/
buffers are page-aligned. Memory is released when the uio_unregister_device() is called.
Cheers, Michael
quoted hunk ↗ jump to hunk
Signed-off-by: Edward Estabrook <redacted> ------ linux-2.6.28-rc6/Documentation/DocBook/uio-howto.tmpl.orig 2008-12-0312:03:43.000000000 -0800+++ linux-2.6.28-rc6/Documentation/DocBook/uio-howto.tmpl 2008-12-0313:11:53.000000000 -0800@@ -42,6 +42,12 @@ GPL version 2. <revhistory> <revision> + <revnumber>0.6</revnumber> + <date>2008-12-03</date> + <authorinitials>ee</authorinitials> + <revremark>Added description of DMA control.</revremark> + </revision> + <revision> <revnumber>0.5</revnumber> <date>2008-05-22</date> <authorinitials>hjk</authorinitials>@@ -284,11 +290,17 @@ interested in translating it, please ema require access to more than one PCI memory region in a driver. </para> <para> + Each UIO device can also dynamically allocate coherent DMA + memory regions and map these to userspace. Once created they + can be mapped like any other UIO memory region. +</para> +<para> Each mapping has its own directory in sysfs, the first mapping appears as <filename>/sys/class/uio/uioX/maps/map0/</filename>. Subsequent mappings create directories <filename>map1/</filename>, - <filename>map2/</filename>, and so on. These directories will only - appear if the size of the mapping is not 0. + <filename>map2/</filename>, and so on. These directories will + appear even if the size of the mapping is 0 to accommodate dynamically + created DMA mappings. </para> <para> Each <filename>mapX/</filename> directory contains two read-only files@@ -318,6 +330,24 @@ interested in translating it, please ema offset = N * getpagesize(); </programlisting> +<para> + From userspace a DMA region may be dynamically allocated and mapped + via the <function>mmap()</function> call by specifying the size of the + region in bytes in the <varname>length</varname> parameter and setting + <varname>offset = 0xFFFFF000</varname>. +</para> +<para> + The bus-specific DMA address as required to configure hardware DMA + registers will be stored in the first long word of the resulting mapped + region. +</para> +<programlisting format="linespecific"> +#define DMA_MEM_ALLOCATE_MMAP_OFFSET 0xFFFFF000UL +void* memory = mmap (NULL, size, PROT_READ | PROT_WRITE , MAP_SHARED, + fd, DMA_MEM_ALLOCATE_MMAP_OFFSET); +u_int64_t *addr = *(u_int64_t *) memory; +</programlisting> + </sect1> </chapter>@@ -572,6 +602,50 @@ to set up sysfs files for this mapping. </para> </sect1> +<sect1 id="dma_region_mmap"> +<title>Allocating DMA region with mmap()</title> + <para> + To allocate and map a DMA memory region you use + use <function>mmap()</function>. You may create as + many regions as system resources allow by repeated use of + <function>mmap()</function>. + </para> + <para> + Specify the size of the desired region, in bytes, in the + <varname>length</varname> parameter and set + <varname>offset = 0xFFFFF000</varname>. The region size will + be rounded up to a multiple of page size to ensure proper + alignment. + </para> + <para> + The bus-specific DMA address is stored in the first long word of the + resulting mapped region. The newly assigned memory index N is + returned in the second long word of the resulting mapped region. This + index is only required if the userspace driver needs to unmap and + then later remap the DMA region as the single call to + <function>mmap()</function> is sufficient to both allocate and map the + region. + </para> + <para> + Since every memory mapping has its own directory in sysfs + <filename>/sys/class/uio/uioX/maps/mapN/</filename> will be created + where N is the dynamically generated index of the mapping just + allocated. + </para> + <para> + Dynamically allocated DMA regions remain available for use + until <function>uio_unregister_device()</function> is called, at + which point the memory is released. + </para> +<programlisting format="linespecific"> + #define DMA_MEM_ALLOCATE_MMAP_OFFSET 0xFFFFF000UL + void* memory = mmap (NULL, size, PROT_READ | PROT_WRITE , MAP_SHARED, + fd, DMA_MEM_ALLOCATE_MMAP_OFFSET); + u_int64_t *addr = *(u_int64_t *) memory; +</programlisting> + +</sect1> + <sect1 id="wait_for_interrupts"> <title>Waiting for interrupts</title> <para>@@ -583,7 +657,7 @@ to set up sysfs files for this mapping. attention because an error occured. </para> <para> - <filename>/dev/uioX</filename> is a read-only file. A + <filename>/dev/uioX</filename> is a read-write file. A <function>read()</function> will always block until an interrupt occurs. There is only one legal value for the <varname>count</varname> parameter of --To unsubscribe from this list: send the line "unsubscribe linux-api" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html
-- Michael Kerrisk Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/ git://git.kernel.org/pub/scm/docs/man-pages/man-pages.git man-pages online: http://www.kernel.org/doc/man-pages/online_pages.html Found a bug? http://www.kernel.org/doc/man-pages/reporting_bugs.html -- To unsubscribe from this list: send the line "unsubscribe linux-api" in the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org More majordomo info at http://vger.kernel.org/majordomo-info.html