From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755573AbYLDExj (ORCPT ); Wed, 3 Dec 2008 23:53:39 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752747AbYLDEx3 (ORCPT ); Wed, 3 Dec 2008 23:53:29 -0500 Received: from wa-out-1112.google.com ([209.85.146.182]:37509 "EHLO wa-out-1112.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751701AbYLDEx2 (ORCPT ); Wed, 3 Dec 2008 23:53:28 -0500 DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:to:subject:cc:mime-version:content-type :content-transfer-encoding:content-disposition; b=o8y2gG4OGGfwCishYJqXVp7+LLzC3j/WS1ghVm1IYpCr6vZzZKXe70aefrOgaZ96Ei dX3YLvL9tdWhf3fbJn+HwPGrPM3gxGhKGP8fG/7w96M5sSNN6jDr86PxzWBwz+DvLESw GYzKfN/N7CDUJXU6GWNNbjHpxwl7qALEgByF8= Message-ID: <208aa0f00812032053w5efb99dbk94511b0f8c1f0925@mail.gmail.com> Date: Wed, 3 Dec 2008 20:53:27 -0800 From: "Edward Estabrook" To: linux-kernel@vger.kernel.org Subject: [PATCH 1/1] Userspace I/O (UIO): Documentatin for userspace DMA support Cc: linux-api@vger.kernel.org, "Greg KH" , hjk@linutronix.de, edward_estabrook@agilent.com MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Edward Estabrook 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 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 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 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 the opened /dev/uioN file. Allocation occurs in page sized pieces by design to ensure that buffers are page-aligned. Memory is released when the uio_unregister_device() is called. Signed-off-by: Edward Estabrook --- --- linux-2.6.28-rc6/Documentation/DocBook/uio-howto.tmpl.orig 2008-12-03 12:03:43.000000000 -0800 +++ linux-2.6.28-rc6/Documentation/DocBook/uio-howto.tmpl 2008-12-03 13:11:53.000000000 -0800 @@ -42,6 +42,12 @@ GPL version 2. + 0.6 + 2008-12-03 + ee + Added description of DMA control. + + 0.5 2008-05-22 hjk @@ -284,11 +290,17 @@ interested in translating it, please ema require access to more than one PCI memory region in a driver. + 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. + + Each mapping has its own directory in sysfs, the first mapping appears as /sys/class/uio/uioX/maps/map0/. Subsequent mappings create directories map1/, - map2/, and so on. These directories will only - appear if the size of the mapping is not 0. + map2/, and so on. These directories will + appear even if the size of the mapping is 0 to accommodate dynamically + created DMA mappings. Each mapX/ directory contains two read-only files @@ -318,6 +330,24 @@ interested in translating it, please ema offset = N * getpagesize(); + + From userspace a DMA region may be dynamically allocated and mapped + via the mmap() call by specifying the size of the + region in bytes in the length parameter and setting + offset = 0xFFFFF000. + + + 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. + + +#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; + + @@ -572,6 +602,50 @@ to set up sysfs files for this mapping. + +Allocating DMA region with mmap() + + To allocate and map a DMA memory region you use + use mmap(). You may create as + many regions as system resources allow by repeated use of + mmap(). + + + Specify the size of the desired region, in bytes, in the + length parameter and set + offset = 0xFFFFF000. The region size will + be rounded up to a multiple of page size to ensure proper + alignment. + + + 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 + mmap() is sufficient to both allocate and map the + region. + + + Since every memory mapping has its own directory in sysfs + /sys/class/uio/uioX/maps/mapN/ will be created + where N is the dynamically generated index of the mapping just + allocated. + + + Dynamically allocated DMA regions remain available for use + until uio_unregister_device() is called, at + which point the memory is released. + + + #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; + + + + Waiting for interrupts @@ -583,7 +657,7 @@ to set up sysfs files for this mapping. attention because an error occured. - /dev/uioX is a read-only file. A + /dev/uioX is a read-write file. A read() will always block until an interrupt occurs. There is only one legal value for the count parameter of