DMA-API.txt: standardize document format
Each text file under Documentation follows a different format. Some doesn't even have titles! Change its representation to follow the adopted standard, using ReST markups for it to be parseable by Sphinx: - Fix some title marks to match ReST; - use :Author: for author name; - foo_ is an hyperlink. Get rid of it; - Mark literal blocks as such; - Use tables on some places that are almost using the table format. Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> Signed-off-by: Jonathan Corbet <corbet@lwn.net>
This commit is contained in:
parent
a2fbbcea7b
commit
03158a70ad
|
@ -1,7 +1,8 @@
|
||||||
Dynamic DMA mapping using the generic device
|
============================================
|
||||||
============================================
|
Dynamic DMA mapping using the generic device
|
||||||
|
============================================
|
||||||
|
|
||||||
James E.J. Bottomley <James.Bottomley@HansenPartnership.com>
|
:Author: James E.J. Bottomley <James.Bottomley@HansenPartnership.com>
|
||||||
|
|
||||||
This document describes the DMA API. For a more gentle introduction
|
This document describes the DMA API. For a more gentle introduction
|
||||||
of the API (and actual examples), see Documentation/DMA-API-HOWTO.txt.
|
of the API (and actual examples), see Documentation/DMA-API-HOWTO.txt.
|
||||||
|
@ -12,10 +13,10 @@ machines. Unless you know that your driver absolutely has to support
|
||||||
non-consistent platforms (this is usually only legacy platforms) you
|
non-consistent platforms (this is usually only legacy platforms) you
|
||||||
should only use the API described in part I.
|
should only use the API described in part I.
|
||||||
|
|
||||||
Part I - dma_ API
|
Part I - dma_API
|
||||||
-------------------------------------
|
----------------
|
||||||
|
|
||||||
To get the dma_ API, you must #include <linux/dma-mapping.h>. This
|
To get the dma_API, you must #include <linux/dma-mapping.h>. This
|
||||||
provides dma_addr_t and the interfaces described below.
|
provides dma_addr_t and the interfaces described below.
|
||||||
|
|
||||||
A dma_addr_t can hold any valid DMA address for the platform. It can be
|
A dma_addr_t can hold any valid DMA address for the platform. It can be
|
||||||
|
@ -26,9 +27,11 @@ address space and the DMA address space.
|
||||||
Part Ia - Using large DMA-coherent buffers
|
Part Ia - Using large DMA-coherent buffers
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
||||||
void *
|
::
|
||||||
dma_alloc_coherent(struct device *dev, size_t size,
|
|
||||||
dma_addr_t *dma_handle, gfp_t flag)
|
void *
|
||||||
|
dma_alloc_coherent(struct device *dev, size_t size,
|
||||||
|
dma_addr_t *dma_handle, gfp_t flag)
|
||||||
|
|
||||||
Consistent memory is memory for which a write by either the device or
|
Consistent memory is memory for which a write by either the device or
|
||||||
the processor can immediately be read by the processor or device
|
the processor can immediately be read by the processor or device
|
||||||
|
@ -51,20 +54,24 @@ consolidate your requests for consistent memory as much as possible.
|
||||||
The simplest way to do that is to use the dma_pool calls (see below).
|
The simplest way to do that is to use the dma_pool calls (see below).
|
||||||
|
|
||||||
The flag parameter (dma_alloc_coherent() only) allows the caller to
|
The flag parameter (dma_alloc_coherent() only) allows the caller to
|
||||||
specify the GFP_ flags (see kmalloc()) for the allocation (the
|
specify the ``GFP_`` flags (see kmalloc()) for the allocation (the
|
||||||
implementation may choose to ignore flags that affect the location of
|
implementation may choose to ignore flags that affect the location of
|
||||||
the returned memory, like GFP_DMA).
|
the returned memory, like GFP_DMA).
|
||||||
|
|
||||||
void *
|
::
|
||||||
dma_zalloc_coherent(struct device *dev, size_t size,
|
|
||||||
dma_addr_t *dma_handle, gfp_t flag)
|
void *
|
||||||
|
dma_zalloc_coherent(struct device *dev, size_t size,
|
||||||
|
dma_addr_t *dma_handle, gfp_t flag)
|
||||||
|
|
||||||
Wraps dma_alloc_coherent() and also zeroes the returned memory if the
|
Wraps dma_alloc_coherent() and also zeroes the returned memory if the
|
||||||
allocation attempt succeeded.
|
allocation attempt succeeded.
|
||||||
|
|
||||||
void
|
::
|
||||||
dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
|
|
||||||
dma_addr_t dma_handle)
|
void
|
||||||
|
dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
|
||||||
|
dma_addr_t dma_handle)
|
||||||
|
|
||||||
Free a region of consistent memory you previously allocated. dev,
|
Free a region of consistent memory you previously allocated. dev,
|
||||||
size and dma_handle must all be the same as those passed into
|
size and dma_handle must all be the same as those passed into
|
||||||
|
@ -78,7 +85,7 @@ may only be called with IRQs enabled.
|
||||||
Part Ib - Using small DMA-coherent buffers
|
Part Ib - Using small DMA-coherent buffers
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
||||||
To get this part of the dma_ API, you must #include <linux/dmapool.h>
|
To get this part of the dma_API, you must #include <linux/dmapool.h>
|
||||||
|
|
||||||
Many drivers need lots of small DMA-coherent memory regions for DMA
|
Many drivers need lots of small DMA-coherent memory regions for DMA
|
||||||
descriptors or I/O buffers. Rather than allocating in units of a page
|
descriptors or I/O buffers. Rather than allocating in units of a page
|
||||||
|
@ -88,6 +95,8 @@ not __get_free_pages(). Also, they understand common hardware constraints
|
||||||
for alignment, like queue heads needing to be aligned on N-byte boundaries.
|
for alignment, like queue heads needing to be aligned on N-byte boundaries.
|
||||||
|
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
struct dma_pool *
|
struct dma_pool *
|
||||||
dma_pool_create(const char *name, struct device *dev,
|
dma_pool_create(const char *name, struct device *dev,
|
||||||
size_t size, size_t align, size_t alloc);
|
size_t size, size_t align, size_t alloc);
|
||||||
|
@ -103,16 +112,21 @@ in bytes, and must be a power of two). If your device has no boundary
|
||||||
crossing restrictions, pass 0 for alloc; passing 4096 says memory allocated
|
crossing restrictions, pass 0 for alloc; passing 4096 says memory allocated
|
||||||
from this pool must not cross 4KByte boundaries.
|
from this pool must not cross 4KByte boundaries.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
void *dma_pool_zalloc(struct dma_pool *pool, gfp_t mem_flags,
|
void *
|
||||||
dma_addr_t *handle)
|
dma_pool_zalloc(struct dma_pool *pool, gfp_t mem_flags,
|
||||||
|
dma_addr_t *handle)
|
||||||
|
|
||||||
Wraps dma_pool_alloc() and also zeroes the returned memory if the
|
Wraps dma_pool_alloc() and also zeroes the returned memory if the
|
||||||
allocation attempt succeeded.
|
allocation attempt succeeded.
|
||||||
|
|
||||||
|
|
||||||
void *dma_pool_alloc(struct dma_pool *pool, gfp_t gfp_flags,
|
::
|
||||||
dma_addr_t *dma_handle);
|
|
||||||
|
void *
|
||||||
|
dma_pool_alloc(struct dma_pool *pool, gfp_t gfp_flags,
|
||||||
|
dma_addr_t *dma_handle);
|
||||||
|
|
||||||
This allocates memory from the pool; the returned memory will meet the
|
This allocates memory from the pool; the returned memory will meet the
|
||||||
size and alignment requirements specified at creation time. Pass
|
size and alignment requirements specified at creation time. Pass
|
||||||
|
@ -122,16 +136,20 @@ blocking. Like dma_alloc_coherent(), this returns two values: an
|
||||||
address usable by the CPU, and the DMA address usable by the pool's
|
address usable by the CPU, and the DMA address usable by the pool's
|
||||||
device.
|
device.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
void dma_pool_free(struct dma_pool *pool, void *vaddr,
|
void
|
||||||
dma_addr_t addr);
|
dma_pool_free(struct dma_pool *pool, void *vaddr,
|
||||||
|
dma_addr_t addr);
|
||||||
|
|
||||||
This puts memory back into the pool. The pool is what was passed to
|
This puts memory back into the pool. The pool is what was passed to
|
||||||
dma_pool_alloc(); the CPU (vaddr) and DMA addresses are what
|
dma_pool_alloc(); the CPU (vaddr) and DMA addresses are what
|
||||||
were returned when that routine allocated the memory being freed.
|
were returned when that routine allocated the memory being freed.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
void dma_pool_destroy(struct dma_pool *pool);
|
void
|
||||||
|
dma_pool_destroy(struct dma_pool *pool);
|
||||||
|
|
||||||
dma_pool_destroy() frees the resources of the pool. It must be
|
dma_pool_destroy() frees the resources of the pool. It must be
|
||||||
called in a context which can sleep. Make sure you've freed all allocated
|
called in a context which can sleep. Make sure you've freed all allocated
|
||||||
|
@ -141,32 +159,40 @@ memory back to the pool before you destroy it.
|
||||||
Part Ic - DMA addressing limitations
|
Part Ic - DMA addressing limitations
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
int
|
::
|
||||||
dma_set_mask_and_coherent(struct device *dev, u64 mask)
|
|
||||||
|
int
|
||||||
|
dma_set_mask_and_coherent(struct device *dev, u64 mask)
|
||||||
|
|
||||||
Checks to see if the mask is possible and updates the device
|
Checks to see if the mask is possible and updates the device
|
||||||
streaming and coherent DMA mask parameters if it is.
|
streaming and coherent DMA mask parameters if it is.
|
||||||
|
|
||||||
Returns: 0 if successful and a negative error if not.
|
Returns: 0 if successful and a negative error if not.
|
||||||
|
|
||||||
int
|
::
|
||||||
dma_set_mask(struct device *dev, u64 mask)
|
|
||||||
|
int
|
||||||
|
dma_set_mask(struct device *dev, u64 mask)
|
||||||
|
|
||||||
Checks to see if the mask is possible and updates the device
|
Checks to see if the mask is possible and updates the device
|
||||||
parameters if it is.
|
parameters if it is.
|
||||||
|
|
||||||
Returns: 0 if successful and a negative error if not.
|
Returns: 0 if successful and a negative error if not.
|
||||||
|
|
||||||
int
|
::
|
||||||
dma_set_coherent_mask(struct device *dev, u64 mask)
|
|
||||||
|
int
|
||||||
|
dma_set_coherent_mask(struct device *dev, u64 mask)
|
||||||
|
|
||||||
Checks to see if the mask is possible and updates the device
|
Checks to see if the mask is possible and updates the device
|
||||||
parameters if it is.
|
parameters if it is.
|
||||||
|
|
||||||
Returns: 0 if successful and a negative error if not.
|
Returns: 0 if successful and a negative error if not.
|
||||||
|
|
||||||
u64
|
::
|
||||||
dma_get_required_mask(struct device *dev)
|
|
||||||
|
u64
|
||||||
|
dma_get_required_mask(struct device *dev)
|
||||||
|
|
||||||
This API returns the mask that the platform requires to
|
This API returns the mask that the platform requires to
|
||||||
operate efficiently. Usually this means the returned mask
|
operate efficiently. Usually this means the returned mask
|
||||||
|
@ -182,94 +208,107 @@ call to set the mask to the value returned.
|
||||||
Part Id - Streaming DMA mappings
|
Part Id - Streaming DMA mappings
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
dma_addr_t
|
::
|
||||||
dma_map_single(struct device *dev, void *cpu_addr, size_t size,
|
|
||||||
enum dma_data_direction direction)
|
dma_addr_t
|
||||||
|
dma_map_single(struct device *dev, void *cpu_addr, size_t size,
|
||||||
|
enum dma_data_direction direction)
|
||||||
|
|
||||||
Maps a piece of processor virtual memory so it can be accessed by the
|
Maps a piece of processor virtual memory so it can be accessed by the
|
||||||
device and returns the DMA address of the memory.
|
device and returns the DMA address of the memory.
|
||||||
|
|
||||||
The direction for both APIs may be converted freely by casting.
|
The direction for both APIs may be converted freely by casting.
|
||||||
However the dma_ API uses a strongly typed enumerator for its
|
However the dma_API uses a strongly typed enumerator for its
|
||||||
direction:
|
direction:
|
||||||
|
|
||||||
|
======================= =============================================
|
||||||
DMA_NONE no direction (used for debugging)
|
DMA_NONE no direction (used for debugging)
|
||||||
DMA_TO_DEVICE data is going from the memory to the device
|
DMA_TO_DEVICE data is going from the memory to the device
|
||||||
DMA_FROM_DEVICE data is coming from the device to the memory
|
DMA_FROM_DEVICE data is coming from the device to the memory
|
||||||
DMA_BIDIRECTIONAL direction isn't known
|
DMA_BIDIRECTIONAL direction isn't known
|
||||||
|
======================= =============================================
|
||||||
|
|
||||||
Notes: Not all memory regions in a machine can be mapped by this API.
|
.. note::
|
||||||
Further, contiguous kernel virtual space may not be contiguous as
|
|
||||||
physical memory. Since this API does not provide any scatter/gather
|
|
||||||
capability, it will fail if the user tries to map a non-physically
|
|
||||||
contiguous piece of memory. For this reason, memory to be mapped by
|
|
||||||
this API should be obtained from sources which guarantee it to be
|
|
||||||
physically contiguous (like kmalloc).
|
|
||||||
|
|
||||||
Further, the DMA address of the memory must be within the
|
Not all memory regions in a machine can be mapped by this API.
|
||||||
dma_mask of the device (the dma_mask is a bit mask of the
|
Further, contiguous kernel virtual space may not be contiguous as
|
||||||
addressable region for the device, i.e., if the DMA address of
|
physical memory. Since this API does not provide any scatter/gather
|
||||||
the memory ANDed with the dma_mask is still equal to the DMA
|
capability, it will fail if the user tries to map a non-physically
|
||||||
address, then the device can perform DMA to the memory). To
|
contiguous piece of memory. For this reason, memory to be mapped by
|
||||||
ensure that the memory allocated by kmalloc is within the dma_mask,
|
this API should be obtained from sources which guarantee it to be
|
||||||
the driver may specify various platform-dependent flags to restrict
|
physically contiguous (like kmalloc).
|
||||||
the DMA address range of the allocation (e.g., on x86, GFP_DMA
|
|
||||||
guarantees to be within the first 16MB of available DMA addresses,
|
|
||||||
as required by ISA devices).
|
|
||||||
|
|
||||||
Note also that the above constraints on physical contiguity and
|
Further, the DMA address of the memory must be within the
|
||||||
dma_mask may not apply if the platform has an IOMMU (a device which
|
dma_mask of the device (the dma_mask is a bit mask of the
|
||||||
maps an I/O DMA address to a physical memory address). However, to be
|
addressable region for the device, i.e., if the DMA address of
|
||||||
portable, device driver writers may *not* assume that such an IOMMU
|
the memory ANDed with the dma_mask is still equal to the DMA
|
||||||
exists.
|
address, then the device can perform DMA to the memory). To
|
||||||
|
ensure that the memory allocated by kmalloc is within the dma_mask,
|
||||||
|
the driver may specify various platform-dependent flags to restrict
|
||||||
|
the DMA address range of the allocation (e.g., on x86, GFP_DMA
|
||||||
|
guarantees to be within the first 16MB of available DMA addresses,
|
||||||
|
as required by ISA devices).
|
||||||
|
|
||||||
Warnings: Memory coherency operates at a granularity called the cache
|
Note also that the above constraints on physical contiguity and
|
||||||
line width. In order for memory mapped by this API to operate
|
dma_mask may not apply if the platform has an IOMMU (a device which
|
||||||
correctly, the mapped region must begin exactly on a cache line
|
maps an I/O DMA address to a physical memory address). However, to be
|
||||||
boundary and end exactly on one (to prevent two separately mapped
|
portable, device driver writers may *not* assume that such an IOMMU
|
||||||
regions from sharing a single cache line). Since the cache line size
|
exists.
|
||||||
may not be known at compile time, the API will not enforce this
|
|
||||||
requirement. Therefore, it is recommended that driver writers who
|
|
||||||
don't take special care to determine the cache line size at run time
|
|
||||||
only map virtual regions that begin and end on page boundaries (which
|
|
||||||
are guaranteed also to be cache line boundaries).
|
|
||||||
|
|
||||||
DMA_TO_DEVICE synchronisation must be done after the last modification
|
.. warning::
|
||||||
of the memory region by the software and before it is handed off to
|
|
||||||
the device. Once this primitive is used, memory covered by this
|
|
||||||
primitive should be treated as read-only by the device. If the device
|
|
||||||
may write to it at any point, it should be DMA_BIDIRECTIONAL (see
|
|
||||||
below).
|
|
||||||
|
|
||||||
DMA_FROM_DEVICE synchronisation must be done before the driver
|
Memory coherency operates at a granularity called the cache
|
||||||
accesses data that may be changed by the device. This memory should
|
line width. In order for memory mapped by this API to operate
|
||||||
be treated as read-only by the driver. If the driver needs to write
|
correctly, the mapped region must begin exactly on a cache line
|
||||||
to it at any point, it should be DMA_BIDIRECTIONAL (see below).
|
boundary and end exactly on one (to prevent two separately mapped
|
||||||
|
regions from sharing a single cache line). Since the cache line size
|
||||||
|
may not be known at compile time, the API will not enforce this
|
||||||
|
requirement. Therefore, it is recommended that driver writers who
|
||||||
|
don't take special care to determine the cache line size at run time
|
||||||
|
only map virtual regions that begin and end on page boundaries (which
|
||||||
|
are guaranteed also to be cache line boundaries).
|
||||||
|
|
||||||
DMA_BIDIRECTIONAL requires special handling: it means that the driver
|
DMA_TO_DEVICE synchronisation must be done after the last modification
|
||||||
isn't sure if the memory was modified before being handed off to the
|
of the memory region by the software and before it is handed off to
|
||||||
device and also isn't sure if the device will also modify it. Thus,
|
the device. Once this primitive is used, memory covered by this
|
||||||
you must always sync bidirectional memory twice: once before the
|
primitive should be treated as read-only by the device. If the device
|
||||||
memory is handed off to the device (to make sure all memory changes
|
may write to it at any point, it should be DMA_BIDIRECTIONAL (see
|
||||||
are flushed from the processor) and once before the data may be
|
below).
|
||||||
accessed after being used by the device (to make sure any processor
|
|
||||||
cache lines are updated with data that the device may have changed).
|
|
||||||
|
|
||||||
void
|
DMA_FROM_DEVICE synchronisation must be done before the driver
|
||||||
dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
|
accesses data that may be changed by the device. This memory should
|
||||||
enum dma_data_direction direction)
|
be treated as read-only by the driver. If the driver needs to write
|
||||||
|
to it at any point, it should be DMA_BIDIRECTIONAL (see below).
|
||||||
|
|
||||||
|
DMA_BIDIRECTIONAL requires special handling: it means that the driver
|
||||||
|
isn't sure if the memory was modified before being handed off to the
|
||||||
|
device and also isn't sure if the device will also modify it. Thus,
|
||||||
|
you must always sync bidirectional memory twice: once before the
|
||||||
|
memory is handed off to the device (to make sure all memory changes
|
||||||
|
are flushed from the processor) and once before the data may be
|
||||||
|
accessed after being used by the device (to make sure any processor
|
||||||
|
cache lines are updated with data that the device may have changed).
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
void
|
||||||
|
dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
|
||||||
|
enum dma_data_direction direction)
|
||||||
|
|
||||||
Unmaps the region previously mapped. All the parameters passed in
|
Unmaps the region previously mapped. All the parameters passed in
|
||||||
must be identical to those passed in (and returned) by the mapping
|
must be identical to those passed in (and returned) by the mapping
|
||||||
API.
|
API.
|
||||||
|
|
||||||
dma_addr_t
|
::
|
||||||
dma_map_page(struct device *dev, struct page *page,
|
|
||||||
unsigned long offset, size_t size,
|
dma_addr_t
|
||||||
enum dma_data_direction direction)
|
dma_map_page(struct device *dev, struct page *page,
|
||||||
void
|
unsigned long offset, size_t size,
|
||||||
dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
|
enum dma_data_direction direction)
|
||||||
enum dma_data_direction direction)
|
|
||||||
|
void
|
||||||
|
dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
|
||||||
|
enum dma_data_direction direction)
|
||||||
|
|
||||||
API for mapping and unmapping for pages. All the notes and warnings
|
API for mapping and unmapping for pages. All the notes and warnings
|
||||||
for the other mapping APIs apply here. Also, although the <offset>
|
for the other mapping APIs apply here. Also, although the <offset>
|
||||||
|
@ -277,20 +316,24 @@ and <size> parameters are provided to do partial page mapping, it is
|
||||||
recommended that you never use these unless you really know what the
|
recommended that you never use these unless you really know what the
|
||||||
cache width is.
|
cache width is.
|
||||||
|
|
||||||
dma_addr_t
|
::
|
||||||
dma_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
|
|
||||||
enum dma_data_direction dir, unsigned long attrs)
|
|
||||||
|
|
||||||
void
|
dma_addr_t
|
||||||
dma_unmap_resource(struct device *dev, dma_addr_t addr, size_t size,
|
dma_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
|
||||||
enum dma_data_direction dir, unsigned long attrs)
|
enum dma_data_direction dir, unsigned long attrs)
|
||||||
|
|
||||||
|
void
|
||||||
|
dma_unmap_resource(struct device *dev, dma_addr_t addr, size_t size,
|
||||||
|
enum dma_data_direction dir, unsigned long attrs)
|
||||||
|
|
||||||
API for mapping and unmapping for MMIO resources. All the notes and
|
API for mapping and unmapping for MMIO resources. All the notes and
|
||||||
warnings for the other mapping APIs apply here. The API should only be
|
warnings for the other mapping APIs apply here. The API should only be
|
||||||
used to map device MMIO resources, mapping of RAM is not permitted.
|
used to map device MMIO resources, mapping of RAM is not permitted.
|
||||||
|
|
||||||
int
|
::
|
||||||
dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
|
|
||||||
|
int
|
||||||
|
dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
|
||||||
|
|
||||||
In some circumstances dma_map_single(), dma_map_page() and dma_map_resource()
|
In some circumstances dma_map_single(), dma_map_page() and dma_map_resource()
|
||||||
will fail to create a mapping. A driver can check for these errors by testing
|
will fail to create a mapping. A driver can check for these errors by testing
|
||||||
|
@ -298,9 +341,11 @@ the returned DMA address with dma_mapping_error(). A non-zero return value
|
||||||
means the mapping could not be created and the driver should take appropriate
|
means the mapping could not be created and the driver should take appropriate
|
||||||
action (e.g. reduce current DMA mapping usage or delay and try again later).
|
action (e.g. reduce current DMA mapping usage or delay and try again later).
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
int
|
int
|
||||||
dma_map_sg(struct device *dev, struct scatterlist *sg,
|
dma_map_sg(struct device *dev, struct scatterlist *sg,
|
||||||
int nents, enum dma_data_direction direction)
|
int nents, enum dma_data_direction direction)
|
||||||
|
|
||||||
Returns: the number of DMA address segments mapped (this may be shorter
|
Returns: the number of DMA address segments mapped (this may be shorter
|
||||||
than <nents> passed in if some elements of the scatter/gather list are
|
than <nents> passed in if some elements of the scatter/gather list are
|
||||||
|
@ -316,7 +361,7 @@ critical that the driver do something, in the case of a block driver
|
||||||
aborting the request or even oopsing is better than doing nothing and
|
aborting the request or even oopsing is better than doing nothing and
|
||||||
corrupting the filesystem.
|
corrupting the filesystem.
|
||||||
|
|
||||||
With scatterlists, you use the resulting mapping like this:
|
With scatterlists, you use the resulting mapping like this::
|
||||||
|
|
||||||
int i, count = dma_map_sg(dev, sglist, nents, direction);
|
int i, count = dma_map_sg(dev, sglist, nents, direction);
|
||||||
struct scatterlist *sg;
|
struct scatterlist *sg;
|
||||||
|
@ -337,9 +382,11 @@ Then you should loop count times (note: this can be less than nents times)
|
||||||
and use sg_dma_address() and sg_dma_len() macros where you previously
|
and use sg_dma_address() and sg_dma_len() macros where you previously
|
||||||
accessed sg->address and sg->length as shown above.
|
accessed sg->address and sg->length as shown above.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
void
|
void
|
||||||
dma_unmap_sg(struct device *dev, struct scatterlist *sg,
|
dma_unmap_sg(struct device *dev, struct scatterlist *sg,
|
||||||
int nents, enum dma_data_direction direction)
|
int nents, enum dma_data_direction direction)
|
||||||
|
|
||||||
Unmap the previously mapped scatter/gather list. All the parameters
|
Unmap the previously mapped scatter/gather list. All the parameters
|
||||||
must be the same as those and passed in to the scatter/gather mapping
|
must be the same as those and passed in to the scatter/gather mapping
|
||||||
|
@ -348,18 +395,27 @@ API.
|
||||||
Note: <nents> must be the number you passed in, *not* the number of
|
Note: <nents> must be the number you passed in, *not* the number of
|
||||||
DMA address entries returned.
|
DMA address entries returned.
|
||||||
|
|
||||||
void
|
::
|
||||||
dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
|
|
||||||
enum dma_data_direction direction)
|
void
|
||||||
void
|
dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
|
||||||
dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size,
|
size_t size,
|
||||||
enum dma_data_direction direction)
|
enum dma_data_direction direction)
|
||||||
void
|
|
||||||
dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
|
void
|
||||||
enum dma_data_direction direction)
|
dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
|
||||||
void
|
size_t size,
|
||||||
dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
|
enum dma_data_direction direction)
|
||||||
enum dma_data_direction direction)
|
|
||||||
|
void
|
||||||
|
dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
|
||||||
|
int nents,
|
||||||
|
enum dma_data_direction direction)
|
||||||
|
|
||||||
|
void
|
||||||
|
dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
|
||||||
|
int nents,
|
||||||
|
enum dma_data_direction direction)
|
||||||
|
|
||||||
Synchronise a single contiguous or scatter/gather mapping for the CPU
|
Synchronise a single contiguous or scatter/gather mapping for the CPU
|
||||||
and device. With the sync_sg API, all the parameters must be the same
|
and device. With the sync_sg API, all the parameters must be the same
|
||||||
|
@ -367,36 +423,41 @@ as those passed into the single mapping API. With the sync_single API,
|
||||||
you can use dma_handle and size parameters that aren't identical to
|
you can use dma_handle and size parameters that aren't identical to
|
||||||
those passed into the single mapping API to do a partial sync.
|
those passed into the single mapping API to do a partial sync.
|
||||||
|
|
||||||
Notes: You must do this:
|
|
||||||
|
|
||||||
- Before reading values that have been written by DMA from the device
|
.. note::
|
||||||
(use the DMA_FROM_DEVICE direction)
|
|
||||||
- After writing values that will be written to the device using DMA
|
You must do this:
|
||||||
(use the DMA_TO_DEVICE) direction
|
|
||||||
- before *and* after handing memory to the device if the memory is
|
- Before reading values that have been written by DMA from the device
|
||||||
DMA_BIDIRECTIONAL
|
(use the DMA_FROM_DEVICE direction)
|
||||||
|
- After writing values that will be written to the device using DMA
|
||||||
|
(use the DMA_TO_DEVICE) direction
|
||||||
|
- before *and* after handing memory to the device if the memory is
|
||||||
|
DMA_BIDIRECTIONAL
|
||||||
|
|
||||||
See also dma_map_single().
|
See also dma_map_single().
|
||||||
|
|
||||||
dma_addr_t
|
::
|
||||||
dma_map_single_attrs(struct device *dev, void *cpu_addr, size_t size,
|
|
||||||
enum dma_data_direction dir,
|
|
||||||
unsigned long attrs)
|
|
||||||
|
|
||||||
void
|
dma_addr_t
|
||||||
dma_unmap_single_attrs(struct device *dev, dma_addr_t dma_addr,
|
dma_map_single_attrs(struct device *dev, void *cpu_addr, size_t size,
|
||||||
size_t size, enum dma_data_direction dir,
|
enum dma_data_direction dir,
|
||||||
unsigned long attrs)
|
unsigned long attrs)
|
||||||
|
|
||||||
int
|
void
|
||||||
dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
|
dma_unmap_single_attrs(struct device *dev, dma_addr_t dma_addr,
|
||||||
int nents, enum dma_data_direction dir,
|
size_t size, enum dma_data_direction dir,
|
||||||
unsigned long attrs)
|
unsigned long attrs)
|
||||||
|
|
||||||
void
|
int
|
||||||
dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl,
|
dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl,
|
||||||
int nents, enum dma_data_direction dir,
|
int nents, enum dma_data_direction dir,
|
||||||
unsigned long attrs)
|
unsigned long attrs)
|
||||||
|
|
||||||
|
void
|
||||||
|
dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl,
|
||||||
|
int nents, enum dma_data_direction dir,
|
||||||
|
unsigned long attrs)
|
||||||
|
|
||||||
The four functions above are just like the counterpart functions
|
The four functions above are just like the counterpart functions
|
||||||
without the _attrs suffixes, except that they pass an optional
|
without the _attrs suffixes, except that they pass an optional
|
||||||
|
@ -410,37 +471,38 @@ is identical to those of the corresponding function
|
||||||
without the _attrs suffix. As a result dma_map_single_attrs()
|
without the _attrs suffix. As a result dma_map_single_attrs()
|
||||||
can generally replace dma_map_single(), etc.
|
can generally replace dma_map_single(), etc.
|
||||||
|
|
||||||
As an example of the use of the *_attrs functions, here's how
|
As an example of the use of the ``*_attrs`` functions, here's how
|
||||||
you could pass an attribute DMA_ATTR_FOO when mapping memory
|
you could pass an attribute DMA_ATTR_FOO when mapping memory
|
||||||
for DMA:
|
for DMA::
|
||||||
|
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
/* DMA_ATTR_FOO should be defined in linux/dma-mapping.h and
|
/* DMA_ATTR_FOO should be defined in linux/dma-mapping.h and
|
||||||
* documented in Documentation/DMA-attributes.txt */
|
* documented in Documentation/DMA-attributes.txt */
|
||||||
...
|
...
|
||||||
|
|
||||||
unsigned long attr;
|
unsigned long attr;
|
||||||
attr |= DMA_ATTR_FOO;
|
attr |= DMA_ATTR_FOO;
|
||||||
....
|
....
|
||||||
n = dma_map_sg_attrs(dev, sg, nents, DMA_TO_DEVICE, attr);
|
n = dma_map_sg_attrs(dev, sg, nents, DMA_TO_DEVICE, attr);
|
||||||
....
|
....
|
||||||
|
|
||||||
Architectures that care about DMA_ATTR_FOO would check for its
|
Architectures that care about DMA_ATTR_FOO would check for its
|
||||||
presence in their implementations of the mapping and unmapping
|
presence in their implementations of the mapping and unmapping
|
||||||
routines, e.g.:
|
routines, e.g.:::
|
||||||
|
|
||||||
void whizco_dma_map_sg_attrs(struct device *dev, dma_addr_t dma_addr,
|
void whizco_dma_map_sg_attrs(struct device *dev, dma_addr_t dma_addr,
|
||||||
size_t size, enum dma_data_direction dir,
|
size_t size, enum dma_data_direction dir,
|
||||||
unsigned long attrs)
|
unsigned long attrs)
|
||||||
{
|
{
|
||||||
....
|
....
|
||||||
if (attrs & DMA_ATTR_FOO)
|
if (attrs & DMA_ATTR_FOO)
|
||||||
/* twizzle the frobnozzle */
|
/* twizzle the frobnozzle */
|
||||||
....
|
....
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Part II - Advanced dma_ usage
|
Part II - Advanced dma usage
|
||||||
-----------------------------
|
----------------------------
|
||||||
|
|
||||||
Warning: These pieces of the DMA API should not be used in the
|
Warning: These pieces of the DMA API should not be used in the
|
||||||
majority of cases, since they cater for unlikely corner cases that
|
majority of cases, since they cater for unlikely corner cases that
|
||||||
|
@ -450,9 +512,11 @@ If you don't understand how cache line coherency works between a
|
||||||
processor and an I/O device, you should not be using this part of the
|
processor and an I/O device, you should not be using this part of the
|
||||||
API at all.
|
API at all.
|
||||||
|
|
||||||
void *
|
::
|
||||||
dma_alloc_noncoherent(struct device *dev, size_t size,
|
|
||||||
dma_addr_t *dma_handle, gfp_t flag)
|
void *
|
||||||
|
dma_alloc_noncoherent(struct device *dev, size_t size,
|
||||||
|
dma_addr_t *dma_handle, gfp_t flag)
|
||||||
|
|
||||||
Identical to dma_alloc_coherent() except that the platform will
|
Identical to dma_alloc_coherent() except that the platform will
|
||||||
choose to return either consistent or non-consistent memory as it sees
|
choose to return either consistent or non-consistent memory as it sees
|
||||||
|
@ -468,39 +532,49 @@ only use this API if you positively know your driver will be
|
||||||
required to work on one of the rare (usually non-PCI) architectures
|
required to work on one of the rare (usually non-PCI) architectures
|
||||||
that simply cannot make consistent memory.
|
that simply cannot make consistent memory.
|
||||||
|
|
||||||
void
|
::
|
||||||
dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr,
|
|
||||||
dma_addr_t dma_handle)
|
void
|
||||||
|
dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr,
|
||||||
|
dma_addr_t dma_handle)
|
||||||
|
|
||||||
Free memory allocated by the nonconsistent API. All parameters must
|
Free memory allocated by the nonconsistent API. All parameters must
|
||||||
be identical to those passed in (and returned by
|
be identical to those passed in (and returned by
|
||||||
dma_alloc_noncoherent()).
|
dma_alloc_noncoherent()).
|
||||||
|
|
||||||
int
|
::
|
||||||
dma_get_cache_alignment(void)
|
|
||||||
|
int
|
||||||
|
dma_get_cache_alignment(void)
|
||||||
|
|
||||||
Returns the processor cache alignment. This is the absolute minimum
|
Returns the processor cache alignment. This is the absolute minimum
|
||||||
alignment *and* width that you must observe when either mapping
|
alignment *and* width that you must observe when either mapping
|
||||||
memory or doing partial flushes.
|
memory or doing partial flushes.
|
||||||
|
|
||||||
Notes: This API may return a number *larger* than the actual cache
|
.. note::
|
||||||
line, but it will guarantee that one or more cache lines fit exactly
|
|
||||||
into the width returned by this call. It will also always be a power
|
|
||||||
of two for easy alignment.
|
|
||||||
|
|
||||||
void
|
This API may return a number *larger* than the actual cache
|
||||||
dma_cache_sync(struct device *dev, void *vaddr, size_t size,
|
line, but it will guarantee that one or more cache lines fit exactly
|
||||||
enum dma_data_direction direction)
|
into the width returned by this call. It will also always be a power
|
||||||
|
of two for easy alignment.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
void
|
||||||
|
dma_cache_sync(struct device *dev, void *vaddr, size_t size,
|
||||||
|
enum dma_data_direction direction)
|
||||||
|
|
||||||
Do a partial sync of memory that was allocated by
|
Do a partial sync of memory that was allocated by
|
||||||
dma_alloc_noncoherent(), starting at virtual address vaddr and
|
dma_alloc_noncoherent(), starting at virtual address vaddr and
|
||||||
continuing on for size. Again, you *must* observe the cache line
|
continuing on for size. Again, you *must* observe the cache line
|
||||||
boundaries when doing this.
|
boundaries when doing this.
|
||||||
|
|
||||||
int
|
::
|
||||||
dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
|
|
||||||
dma_addr_t device_addr, size_t size, int
|
int
|
||||||
flags)
|
dma_declare_coherent_memory(struct device *dev, phys_addr_t phys_addr,
|
||||||
|
dma_addr_t device_addr, size_t size, int
|
||||||
|
flags)
|
||||||
|
|
||||||
Declare region of memory to be handed out by dma_alloc_coherent() when
|
Declare region of memory to be handed out by dma_alloc_coherent() when
|
||||||
it's asked for coherent memory for this device.
|
it's asked for coherent memory for this device.
|
||||||
|
@ -516,21 +590,21 @@ size is the size of the area (must be multiples of PAGE_SIZE).
|
||||||
|
|
||||||
flags can be ORed together and are:
|
flags can be ORed together and are:
|
||||||
|
|
||||||
DMA_MEMORY_MAP - request that the memory returned from
|
- DMA_MEMORY_MAP - request that the memory returned from
|
||||||
dma_alloc_coherent() be directly writable.
|
dma_alloc_coherent() be directly writable.
|
||||||
|
|
||||||
DMA_MEMORY_IO - request that the memory returned from
|
- DMA_MEMORY_IO - request that the memory returned from
|
||||||
dma_alloc_coherent() be addressable using read()/write()/memcpy_toio() etc.
|
dma_alloc_coherent() be addressable using read()/write()/memcpy_toio() etc.
|
||||||
|
|
||||||
One or both of these flags must be present.
|
One or both of these flags must be present.
|
||||||
|
|
||||||
DMA_MEMORY_INCLUDES_CHILDREN - make the declared memory be allocated by
|
- DMA_MEMORY_INCLUDES_CHILDREN - make the declared memory be allocated by
|
||||||
dma_alloc_coherent of any child devices of this one (for memory residing
|
dma_alloc_coherent of any child devices of this one (for memory residing
|
||||||
on a bridge).
|
on a bridge).
|
||||||
|
|
||||||
DMA_MEMORY_EXCLUSIVE - only allocate memory from the declared regions.
|
- DMA_MEMORY_EXCLUSIVE - only allocate memory from the declared regions.
|
||||||
Do not allow dma_alloc_coherent() to fall back to system memory when
|
Do not allow dma_alloc_coherent() to fall back to system memory when
|
||||||
it's out of memory in the declared region.
|
it's out of memory in the declared region.
|
||||||
|
|
||||||
The return value will be either DMA_MEMORY_MAP or DMA_MEMORY_IO and
|
The return value will be either DMA_MEMORY_MAP or DMA_MEMORY_IO and
|
||||||
must correspond to a passed in flag (i.e. no returning DMA_MEMORY_IO
|
must correspond to a passed in flag (i.e. no returning DMA_MEMORY_IO
|
||||||
|
@ -543,15 +617,17 @@ must be accessed using the correct bus functions. If your driver
|
||||||
isn't prepared to handle this contingency, it should not specify
|
isn't prepared to handle this contingency, it should not specify
|
||||||
DMA_MEMORY_IO in the input flags.
|
DMA_MEMORY_IO in the input flags.
|
||||||
|
|
||||||
As a simplification for the platforms, only *one* such region of
|
As a simplification for the platforms, only **one** such region of
|
||||||
memory may be declared per device.
|
memory may be declared per device.
|
||||||
|
|
||||||
For reasons of efficiency, most platforms choose to track the declared
|
For reasons of efficiency, most platforms choose to track the declared
|
||||||
region only at the granularity of a page. For smaller allocations,
|
region only at the granularity of a page. For smaller allocations,
|
||||||
you should use the dma_pool() API.
|
you should use the dma_pool() API.
|
||||||
|
|
||||||
void
|
::
|
||||||
dma_release_declared_memory(struct device *dev)
|
|
||||||
|
void
|
||||||
|
dma_release_declared_memory(struct device *dev)
|
||||||
|
|
||||||
Remove the memory region previously declared from the system. This
|
Remove the memory region previously declared from the system. This
|
||||||
API performs *no* in-use checking for this region and will return
|
API performs *no* in-use checking for this region and will return
|
||||||
|
@ -559,9 +635,11 @@ unconditionally having removed all the required structures. It is the
|
||||||
driver's job to ensure that no parts of this memory region are
|
driver's job to ensure that no parts of this memory region are
|
||||||
currently in use.
|
currently in use.
|
||||||
|
|
||||||
void *
|
::
|
||||||
dma_mark_declared_memory_occupied(struct device *dev,
|
|
||||||
dma_addr_t device_addr, size_t size)
|
void *
|
||||||
|
dma_mark_declared_memory_occupied(struct device *dev,
|
||||||
|
dma_addr_t device_addr, size_t size)
|
||||||
|
|
||||||
This is used to occupy specific regions of the declared space
|
This is used to occupy specific regions of the declared space
|
||||||
(dma_alloc_coherent() will hand out the first free region it finds).
|
(dma_alloc_coherent() will hand out the first free region it finds).
|
||||||
|
@ -592,38 +670,37 @@ option has a performance impact. Do not enable it in production kernels.
|
||||||
If you boot the resulting kernel will contain code which does some bookkeeping
|
If you boot the resulting kernel will contain code which does some bookkeeping
|
||||||
about what DMA memory was allocated for which device. If this code detects an
|
about what DMA memory was allocated for which device. If this code detects an
|
||||||
error it prints a warning message with some details into your kernel log. An
|
error it prints a warning message with some details into your kernel log. An
|
||||||
example warning message may look like this:
|
example warning message may look like this::
|
||||||
|
|
||||||
------------[ cut here ]------------
|
WARNING: at /data2/repos/linux-2.6-iommu/lib/dma-debug.c:448
|
||||||
WARNING: at /data2/repos/linux-2.6-iommu/lib/dma-debug.c:448
|
check_unmap+0x203/0x490()
|
||||||
check_unmap+0x203/0x490()
|
Hardware name:
|
||||||
Hardware name:
|
forcedeth 0000:00:08.0: DMA-API: device driver frees DMA memory with wrong
|
||||||
forcedeth 0000:00:08.0: DMA-API: device driver frees DMA memory with wrong
|
function [device address=0x00000000640444be] [size=66 bytes] [mapped as
|
||||||
function [device address=0x00000000640444be] [size=66 bytes] [mapped as
|
single] [unmapped as page]
|
||||||
single] [unmapped as page]
|
Modules linked in: nfsd exportfs bridge stp llc r8169
|
||||||
Modules linked in: nfsd exportfs bridge stp llc r8169
|
Pid: 0, comm: swapper Tainted: G W 2.6.28-dmatest-09289-g8bb99c0 #1
|
||||||
Pid: 0, comm: swapper Tainted: G W 2.6.28-dmatest-09289-g8bb99c0 #1
|
Call Trace:
|
||||||
Call Trace:
|
<IRQ> [<ffffffff80240b22>] warn_slowpath+0xf2/0x130
|
||||||
<IRQ> [<ffffffff80240b22>] warn_slowpath+0xf2/0x130
|
[<ffffffff80647b70>] _spin_unlock+0x10/0x30
|
||||||
[<ffffffff80647b70>] _spin_unlock+0x10/0x30
|
[<ffffffff80537e75>] usb_hcd_link_urb_to_ep+0x75/0xc0
|
||||||
[<ffffffff80537e75>] usb_hcd_link_urb_to_ep+0x75/0xc0
|
[<ffffffff80647c22>] _spin_unlock_irqrestore+0x12/0x40
|
||||||
[<ffffffff80647c22>] _spin_unlock_irqrestore+0x12/0x40
|
[<ffffffff8055347f>] ohci_urb_enqueue+0x19f/0x7c0
|
||||||
[<ffffffff8055347f>] ohci_urb_enqueue+0x19f/0x7c0
|
[<ffffffff80252f96>] queue_work+0x56/0x60
|
||||||
[<ffffffff80252f96>] queue_work+0x56/0x60
|
[<ffffffff80237e10>] enqueue_task_fair+0x20/0x50
|
||||||
[<ffffffff80237e10>] enqueue_task_fair+0x20/0x50
|
[<ffffffff80539279>] usb_hcd_submit_urb+0x379/0xbc0
|
||||||
[<ffffffff80539279>] usb_hcd_submit_urb+0x379/0xbc0
|
[<ffffffff803b78c3>] cpumask_next_and+0x23/0x40
|
||||||
[<ffffffff803b78c3>] cpumask_next_and+0x23/0x40
|
[<ffffffff80235177>] find_busiest_group+0x207/0x8a0
|
||||||
[<ffffffff80235177>] find_busiest_group+0x207/0x8a0
|
[<ffffffff8064784f>] _spin_lock_irqsave+0x1f/0x50
|
||||||
[<ffffffff8064784f>] _spin_lock_irqsave+0x1f/0x50
|
[<ffffffff803c7ea3>] check_unmap+0x203/0x490
|
||||||
[<ffffffff803c7ea3>] check_unmap+0x203/0x490
|
[<ffffffff803c8259>] debug_dma_unmap_page+0x49/0x50
|
||||||
[<ffffffff803c8259>] debug_dma_unmap_page+0x49/0x50
|
[<ffffffff80485f26>] nv_tx_done_optimized+0xc6/0x2c0
|
||||||
[<ffffffff80485f26>] nv_tx_done_optimized+0xc6/0x2c0
|
[<ffffffff80486c13>] nv_nic_irq_optimized+0x73/0x2b0
|
||||||
[<ffffffff80486c13>] nv_nic_irq_optimized+0x73/0x2b0
|
[<ffffffff8026df84>] handle_IRQ_event+0x34/0x70
|
||||||
[<ffffffff8026df84>] handle_IRQ_event+0x34/0x70
|
[<ffffffff8026ffe9>] handle_edge_irq+0xc9/0x150
|
||||||
[<ffffffff8026ffe9>] handle_edge_irq+0xc9/0x150
|
[<ffffffff8020e3ab>] do_IRQ+0xcb/0x1c0
|
||||||
[<ffffffff8020e3ab>] do_IRQ+0xcb/0x1c0
|
[<ffffffff8020c093>] ret_from_intr+0x0/0xa
|
||||||
[<ffffffff8020c093>] ret_from_intr+0x0/0xa
|
<EOI> <4>---[ end trace f6435a98e2a38c0e ]---
|
||||||
<EOI> <4>---[ end trace f6435a98e2a38c0e ]---
|
|
||||||
|
|
||||||
The driver developer can find the driver and the device including a stacktrace
|
The driver developer can find the driver and the device including a stacktrace
|
||||||
of the DMA-API call which caused this warning.
|
of the DMA-API call which caused this warning.
|
||||||
|
@ -637,43 +714,42 @@ details.
|
||||||
The debugfs directory for the DMA-API debugging code is called dma-api/. In
|
The debugfs directory for the DMA-API debugging code is called dma-api/. In
|
||||||
this directory the following files can currently be found:
|
this directory the following files can currently be found:
|
||||||
|
|
||||||
dma-api/all_errors This file contains a numeric value. If this
|
=============================== ===============================================
|
||||||
|
dma-api/all_errors This file contains a numeric value. If this
|
||||||
value is not equal to zero the debugging code
|
value is not equal to zero the debugging code
|
||||||
will print a warning for every error it finds
|
will print a warning for every error it finds
|
||||||
into the kernel log. Be careful with this
|
into the kernel log. Be careful with this
|
||||||
option, as it can easily flood your logs.
|
option, as it can easily flood your logs.
|
||||||
|
|
||||||
dma-api/disabled This read-only file contains the character 'Y'
|
dma-api/disabled This read-only file contains the character 'Y'
|
||||||
if the debugging code is disabled. This can
|
if the debugging code is disabled. This can
|
||||||
happen when it runs out of memory or if it was
|
happen when it runs out of memory or if it was
|
||||||
disabled at boot time
|
disabled at boot time
|
||||||
|
|
||||||
dma-api/error_count This file is read-only and shows the total
|
dma-api/error_count This file is read-only and shows the total
|
||||||
numbers of errors found.
|
numbers of errors found.
|
||||||
|
|
||||||
dma-api/num_errors The number in this file shows how many
|
dma-api/num_errors The number in this file shows how many
|
||||||
warnings will be printed to the kernel log
|
warnings will be printed to the kernel log
|
||||||
before it stops. This number is initialized to
|
before it stops. This number is initialized to
|
||||||
one at system boot and be set by writing into
|
one at system boot and be set by writing into
|
||||||
this file
|
this file
|
||||||
|
|
||||||
dma-api/min_free_entries
|
dma-api/min_free_entries This read-only file can be read to get the
|
||||||
This read-only file can be read to get the
|
|
||||||
minimum number of free dma_debug_entries the
|
minimum number of free dma_debug_entries the
|
||||||
allocator has ever seen. If this value goes
|
allocator has ever seen. If this value goes
|
||||||
down to zero the code will disable itself
|
down to zero the code will disable itself
|
||||||
because it is not longer reliable.
|
because it is not longer reliable.
|
||||||
|
|
||||||
dma-api/num_free_entries
|
dma-api/num_free_entries The current number of free dma_debug_entries
|
||||||
The current number of free dma_debug_entries
|
|
||||||
in the allocator.
|
in the allocator.
|
||||||
|
|
||||||
dma-api/driver-filter
|
dma-api/driver-filter You can write a name of a driver into this file
|
||||||
You can write a name of a driver into this file
|
|
||||||
to limit the debug output to requests from that
|
to limit the debug output to requests from that
|
||||||
particular driver. Write an empty string to
|
particular driver. Write an empty string to
|
||||||
that file to disable the filter and see
|
that file to disable the filter and see
|
||||||
all errors again.
|
all errors again.
|
||||||
|
=============================== ===============================================
|
||||||
|
|
||||||
If you have this code compiled into your kernel it will be enabled by default.
|
If you have this code compiled into your kernel it will be enabled by default.
|
||||||
If you want to boot without the bookkeeping anyway you can provide
|
If you want to boot without the bookkeeping anyway you can provide
|
||||||
|
@ -692,7 +768,10 @@ of preallocated entries is defined per architecture. If it is too low for you
|
||||||
boot with 'dma_debug_entries=<your_desired_number>' to overwrite the
|
boot with 'dma_debug_entries=<your_desired_number>' to overwrite the
|
||||||
architectural default.
|
architectural default.
|
||||||
|
|
||||||
void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
|
::
|
||||||
|
|
||||||
|
void
|
||||||
|
debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
|
||||||
|
|
||||||
dma-debug interface debug_dma_mapping_error() to debug drivers that fail
|
dma-debug interface debug_dma_mapping_error() to debug drivers that fail
|
||||||
to check DMA mapping errors on addresses returned by dma_map_single() and
|
to check DMA mapping errors on addresses returned by dma_map_single() and
|
||||||
|
@ -702,4 +781,3 @@ the driver. When driver does unmap, debug_dma_unmap() checks the flag and if
|
||||||
this flag is still set, prints warning message that includes call trace that
|
this flag is still set, prints warning message that includes call trace that
|
||||||
leads up to the unmap. This interface can be called from dma_mapping_error()
|
leads up to the unmap. This interface can be called from dma_mapping_error()
|
||||||
routines to enable DMA mapping error check debugging.
|
routines to enable DMA mapping error check debugging.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue