power: max17048: display correct status at boot-up
[linux-3.10.git] / Documentation / DMA-API-HOWTO.txt
index a38ddad..14129f1 100644 (file)
@@ -468,11 +468,47 @@ 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. A couple of examples 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 +525,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 +540,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 +628,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;
@@ -613,13 +671,13 @@ to use the dma_sync_*() interfaces.
                                pass_to_upper_layers(cp->rx_buf);
                                make_and_setup_new_rx_buf(cp);
                        } else {
-                               /* Just sync the buffer and give it back
-                                * to the card.
+                               /* CPU should not write to
+                                * DMA_FROM_DEVICE-mapped area,
+                                * so dma_sync_single_for_device() is
+                                * not needed here. It would be required
+                                * for DMA_BIDIRECTIONAL mapping if
+                                * the memory was modified.
                                 */
-                               dma_sync_single_for_device(&cp->dev,
-                                                          cp->rx_dma,
-                                                          cp->rx_len,
-                                                          DMA_FROM_DEVICE);
                                give_rx_buf_to_card(cp);
                        }
                }
@@ -639,6 +697,105 @@ is planned to completely remove virt_to_bus() and bus_to_virt() as
 they are entirely deprecated.  Some ports already do not provide these
 as it is impossible to correctly support them.
 
+                       Handling Errors
+
+DMA address space is limited on some architectures and an allocation
+failure can be determined by:
+
+- checking if dma_alloc_coherent returns NULL or dma_map_sg returns 0
+
+- checking the returned dma_addr_t of dma_map_single and dma_map_page
+  by using dma_mapping_error():
+
+       dma_addr_t dma_handle;
+
+       dma_handle = dma_map_single(dev, addr, size, direction);
+       if (dma_mapping_error(dev, dma_handle)) {
+               /*
+                * reduce current DMA mapping usage,
+                * 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 in 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
+and return NETDEV_TX_OK if the DMA mapping fails on the transmit hook
+(ndo_start_xmit). This means that the socket buffer is just dropped in
+the failure case.
+
+SCSI drivers must return SCSI_MLQUEUE_HOST_BUSY if the DMA mapping
+fails in the queuecommand hook. This means that the SCSI subsystem
+passes the command to the driver again later.
+
                Optimizing Unmap State Space Consumption
 
 On many platforms, dma_unmap_{single,page}() is simply a nop.
@@ -703,51 +860,35 @@ to "Closing".
 
 1) Struct scatterlist requirements.
 
-   Struct scatterlist must contain, at a minimum, the following
-   members:
-
-       struct page *page;
-       unsigned int offset;
-       unsigned int length;
-
-   The base address is specified by a "page+offset" pair.
-
-   Previous versions of struct scatterlist contained a "void *address"
-   field that was sometimes used instead of page+offset.  As of Linux
-   2.5., page+offset is always used, and the "address" field has been
-   deleted.
-
-2) More to come...
-
-                       Handling Errors
-
-DMA address space is limited on some architectures and an allocation
-failure can be determined by:
-
-- checking if dma_alloc_coherent returns NULL or dma_map_sg returns 0
-
-- checking the returned dma_addr_t of dma_map_single and dma_map_page
-  by using dma_mapping_error():
-
-       dma_addr_t dma_handle;
-
-       dma_handle = dma_map_single(dev, addr, size, direction);
-       if (dma_mapping_error(dev, dma_handle)) {
-               /*
-                * reduce current DMA mapping usage,
-                * delay and try again later or
-                * reset driver.
-                */
-       }
-
-Networking drivers must call dev_kfree_skb to free the socket buffer
-and return NETDEV_TX_OK if the DMA mapping fails on the transmit hook
-(ndo_start_xmit). This means that the socket buffer is just dropped in
-the failure case.
-
-SCSI drivers must return SCSI_MLQUEUE_HOST_BUSY if the DMA mapping
-fails in the queuecommand hook. This means that the SCSI subsystem
-passes the command to the driver again later.
+   Don't invent the architecture specific struct scatterlist; just use
+   <asm-generic/scatterlist.h>. You need to enable
+   CONFIG_NEED_SG_DMA_LENGTH if the architecture supports IOMMUs
+   (including software IOMMU).
+
+2) ARCH_DMA_MINALIGN
+
+   Architectures must ensure that kmalloc'ed buffer is
+   DMA-safe. Drivers and subsystems depend on it. If an architecture
+   isn't fully DMA-coherent (i.e. hardware doesn't ensure that data in
+   the CPU cache is identical to data in main memory),
+   ARCH_DMA_MINALIGN must be set so that the memory allocator
+   makes sure that kmalloc'ed buffer doesn't share a cache line with
+   the others. See arch/arm/include/asm/cache.h as an example.
+
+   Note that ARCH_DMA_MINALIGN is about DMA memory alignment
+   constraints. You don't need to worry about the architecture data
+   alignment constraints (e.g. the alignment constraints about 64-bit
+   objects).
+
+3) Supporting multiple types of IOMMUs
+
+   If your architecture needs to support multiple types of IOMMUs, you
+   can use include/linux/asm-generic/dma-mapping-common.h. It's a
+   library to support the DMA API with multiple types of IOMMUs. Lots
+   of architectures (x86, powerpc, sh, alpha, ia64, microblaze and
+   sparc) use it. Choose one to see how it can be used. If you need to
+   support multiple types of IOMMUs in a single system, the example of
+   x86 or powerpc helps.
 
                           Closing