public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
To: Shuah Khan <shuah.khan@hp.com>
Cc: mtk.manpages@gmail.com, Dan Carpenter <dan.carpenter@oracle.com>,
	rob@landley.net, joerg.roedel@amd.com,
	Andrew Morton <akpm@linux-foundation.org>,
	devel@linuxdriverproject.org, linux-kernel@vger.kernel.org,
	linux-doc@vger.kernel.org, shuahkhan@gmail.com
Subject: Re: [PATCH v2] Documentation DMA-API-HOWTO.txt Add dma mapping error check usage examples
Date: Fri, 19 Oct 2012 12:57:23 -0400	[thread overview]
Message-ID: <20121019165723.GQ26830@phenom.dumpdata.com> (raw)
In-Reply-To: <1350590458.2680.44.camel@lorien2>

On Thu, Oct 18, 2012 at 02:00:58PM -0600, Shuah Khan wrote:
> Enhance the document to discuss the importance of dma mapping error checks
> after dma_map_single() and dma_map_page() calls. Also added usage examples
> that include unmap examples in error paths when dma mapping error is returned.
> Includes correct and incorrect usages to high light some common mistakes in
> error paths especially when dma mapping fails when more than one dma mapping
> call is made.
> 
> Signed-off-by: Shuah Khan <shuah.khan@hp.com>

Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> ---
>  Documentation/DMA-API-HOWTO.txt |  126 +++++++++++++++++++++++++++++++++++++++
>  1 file changed, 126 insertions(+)
> 
> diff --git a/Documentation/DMA-API-HOWTO.txt b/Documentation/DMA-API-HOWTO.txt
> index a0b6250..4a4fb29 100644
> --- a/Documentation/DMA-API-HOWTO.txt
> +++ b/Documentation/DMA-API-HOWTO.txt
> @@ -468,11 +468,46 @@ To map a single region, you do:
>  	size_t size = buffer->len;
>  
>  	dma_handle = dma_map_single(dev, addr, size, direction);
> +	if (dma_mapping_error(dma_handle)) {
> +		/*
> +		 * reduce current DMA mapping usage,
> +		 * delay and try again later or
> +		 * reset driver.
> +		 */
> +		goto map_error_handling;
> +	}
>  
>  and to unmap it:
>  
>  	dma_unmap_single(dev, dma_handle, size, direction);
>  
> +You should call dma_mapping_error() as dma_map_single() could fail and return
> +error. Not all dma implementations support dma_mapping_error() interface.
> +However, it is a good practice to call dma_mapping_error() interface, which
> +will invoke the generic mapping error check interface. Doing so will ensure
> +that the mapping code will work correctly on all dma implementations without
> +any dependency on the specifics of the underlying implementation. Using the
> +returned address without checking for errors could result in failures ranging
> +from panics to silent data corruption. Couple of example of incorrect ways to
> +check for errors that make assumptions about the underlying dma implementation
> +are as follows and these are applicable to dma_map_page() as well.
> +
> +Incorrect example 1:
> +	dma_addr_t dma_handle;
> +
> +	dma_handle = dma_map_single(dev, addr, size, direction);
> +	if ((dma_handle & 0xffff != 0) || (dma_handle >= 0x1000000)) {
> +		goto map_error;
> +	}
> +
> +Incorrect example 2:
> +	dma_addr_t dma_handle;
> +
> +	dma_handle = dma_map_single(dev, addr, size, direction);
> +	if (dma_handle == DMA_ERROR_CODE) {
> +		goto map_error;
> +	}
> +
>  You should call dma_unmap_single when the DMA activity is finished, e.g.
>  from the interrupt which told you that the DMA transfer is done.
>  
> @@ -489,6 +524,14 @@ Specifically:
>  	size_t size = buffer->len;
>  
>  	dma_handle = dma_map_page(dev, page, offset, size, direction);
> +	if (dma_mapping_error(dma_handle)) {
> +		/*
> +		 * reduce current DMA mapping usage,
> +		 * delay and try again later or
> +		 * reset driver.
> +		 */
> +		goto map_error_handling;
> +	}
>  
>  	...
>  
> @@ -496,6 +539,12 @@ Specifically:
>  
>  Here, "offset" means byte offset within the given page.
>  
> +You should call dma_mapping_error() as dma_map_page() could fail and return
> +error as outlined under the dma_map_single() discussion.
> +
> +You should call dma_unmap_page when the DMA activity is finished, e.g.
> +from the interrupt which told you that the DMA transfer is done.
> +
>  With scatterlists, you map a region gathered from several regions by:
>  
>  	int i, count = dma_map_sg(dev, sglist, nents, direction);
> @@ -578,6 +627,14 @@ to use the dma_sync_*() interfaces.
>  		dma_addr_t mapping;
>  
>  		mapping = dma_map_single(cp->dev, buffer, len, DMA_FROM_DEVICE);
> +		if (dma_mapping_error(dma_handle)) {
> +			/*
> +			 * reduce current DMA mapping usage,
> +			 * delay and try again later or
> +			 * reset driver.
> +			 */
> +			goto map_error_handling;
> +		}
>  
>  		cp->rx_buf = buffer;
>  		cp->rx_len = len;
> @@ -658,6 +715,75 @@ failure can be determined by:
>  		 * delay and try again later or
>  		 * reset driver.
>  		 */
> +		goto map_error_handling;
> +	}
> +
> +- unmap pages that are already mapped, when mapping error occurs in the middle
> +  of a multiple page mapping attempt. These example are applicable to
> +  dma_map_page() as well.
> +
> +Example 1:
> +	dma_addr_t dma_handle1;
> +	dma_addr_t dma_handle2;
> +
> +	dma_handle1 = dma_map_single(dev, addr, size, direction);
> +	if (dma_mapping_error(dev, dma_handle1)) {
> +		/*
> +		 * reduce current DMA mapping usage,
> +		 * delay and try again later or
> +		 * reset driver.
> +		 */
> +		goto map_error_handling1;
> +	}
> +	dma_handle2 = dma_map_single(dev, addr, size, direction);
> +	if (dma_mapping_error(dev, dma_handle2)) {
> +		/*
> +		 * reduce current DMA mapping usage,
> +		 * delay and try again later or
> +		 * reset driver.
> +		 */
> +		goto map_error_handling2;
> +	}
> +
> +	...
> +
> +	map_error_handling2:
> +		dma_unmap_single(dma_handle1);
> +	map_error_handling1:
> +
> +Example 2: (if buffers are allocated a loop, unmap all mapped buffers when
> +	    mapping error is detected in the middle)
> +
> +	dma_addr_t dma_addr;
> +	dma_addr_t array[DMA_BUFFERS];
> +	int save_index = 0;
> +
> +	for (i = 0; i < DMA_BUFFERS; i++) {
> +
> +		...
> +
> +		dma_addr = dma_map_single(dev, addr, size, direction);
> +		if (dma_mapping_error(dev, dma_addr)) {
> +			/*
> +			 * reduce current DMA mapping usage,
> +			 * delay and try again later or
> +			 * reset driver.
> +			 */
> +			goto map_error_handling;
> +		}
> +		array[i].dma_addr = dma_addr;
> +		save_index++;
> +	}
> +
> +	...
> +
> +	map_error_handling:
> +
> +	for (i = 0; i < save_index; i++) {
> +
> +		...
> +
> +		dma_unmap_single(array[i].dma_addr);
>  	}
>  
>  Networking drivers must call dev_kfree_skb to free the socket buffer
> -- 
> 1.7.9.5
> 
> 

  parent reply	other threads:[~2012-10-19 17:09 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-10-14 15:54 [PATCH] Documentation DMA-API-HOWTO.txt Add dma mapping error check usage examples Shuah Khan
2012-10-18  9:47 ` Dan Carpenter
2012-10-18 10:13   ` Michael Kerrisk (man-pages)
2012-10-18 14:30     ` Shuah Khan
2012-10-18 20:00     ` [PATCH v2] " Shuah Khan
2012-10-18 21:32       ` Jesper Juhl
2012-10-19 16:57       ` Konrad Rzeszutek Wilk [this message]
2012-10-24 15:09       ` Joerg Roedel

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20121019165723.GQ26830@phenom.dumpdata.com \
    --to=konrad.wilk@oracle.com \
    --cc=akpm@linux-foundation.org \
    --cc=dan.carpenter@oracle.com \
    --cc=devel@linuxdriverproject.org \
    --cc=joerg.roedel@amd.com \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mtk.manpages@gmail.com \
    --cc=rob@landley.net \
    --cc=shuah.khan@hp.com \
    --cc=shuahkhan@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox