]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Add dma_error() and pci_dma_error()
authorAndrew Morton <akpm@osdl.org>
Thu, 18 Mar 2004 22:59:12 +0000 (14:59 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Thu, 18 Mar 2004 22:59:12 +0000 (14:59 -0800)
From: Anton Blanchard <anton@samba.org>

Introduce dma_error() and pci_dma_error() which are used to detect failures
in pci_map_single.

Documentation/DMA-API.txt
Documentation/DMA-mapping.txt
include/asm-generic/dma-mapping.h
include/asm-generic/pci-dma-compat.h
include/asm-i386/dma-mapping.h

index dfb3b5654af03cb329344c17ade5c3f9d187e5ff..2b730516113dfcf74fe3b9920e6d08db6edfbfa0 100644 (file)
@@ -278,6 +278,18 @@ and <size> parameters are provided to do partial page mapping, it is
 recommended that you never use these unless you really know what the
 cache width is.
 
+int
+dma_error(dma_addr_t dma_addr)
+
+int
+pci_dma_error(dma_addr_t dma_addr)
+
+In some circumstances dma_map_single and dma_map_page will fail to create
+a mapping. A driver can check for these errors by testing the returned
+dma address with dma_error(). A non zero return value means the mapping
+could not be created and the driver should take appropriate action (eg
+reduce current DMA mapping usage or delay and try again later).
+
 int
 dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
           enum dma_data_direction direction)
@@ -292,6 +304,15 @@ than <nents> passed in if the block layer determines that some
 elements of the scatter/gather list are physically adjacent and thus
 may be mapped with a single entry).
 
+Please note that the sg cannot be mapped again if it has been mapped once.
+The mapping process is allowed to destroy information in the sg.
+
+As with the other mapping interfaces, dma_map_sg can fail. When it
+does, 0 is returned and a driver must take appropriate action. It is
+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
+corrupting the filesystem.
+
 void
 dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
             enum dma_data_direction direction)
index 9860788eb99c55cb72311575252d98b7ce8773fd..a77c940893c65021278339e319c17cd763ef5ecf 100644 (file)
@@ -519,7 +519,7 @@ consecutive sglist entries can be merged into one provided the first one
 ends and the second one starts on a page boundary - in fact this is a huge
 advantage for cards which either cannot do scatter-gather or have very
 limited number of scatter-gather entries) and returns the actual number
-of sg entries it mapped them to.
+of sg entries it mapped them to. On failure 0 is returned.
 
 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
@@ -842,6 +842,27 @@ to "Closing".
 
 2) More to come...
 
+                       Handling Errors
+
+DMA address space is limited on some architectures and an allocation
+failure can be determined by:
+
+- checking if pci_alloc_consistent returns NULL or pci_map_sg returns 0
+
+- checking the returned dma_addr_t of pci_map_single and pci_map_page
+  by using pci_dma_error():
+
+       dma_addr_t dma_handle;
+
+       dma_handle = pci_map_single(dev, addr, size, direction);
+       if (pci_dma_error(dma_handle)) {
+               /*
+                * reduce current DMA mapping usage,
+                * delay and try again later or
+                * reset driver.
+                */
+       }
+
                           Closing
 
 This document, and the API itself, would not be in it's current
index bcf3118f6d98c147c485e34adad3b7a913d2da8d..0079c79815bfb23525b4f7df1325d905634b75c9 100644 (file)
@@ -140,6 +140,12 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
        pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, nelems, (int)direction);
 }
 
+static inline int
+dma_error(dma_addr_t dma_addr)
+{
+       return pci_dma_error(dma_addr);
+}
+
 /* Now for the API extensions over the pci_ one */
 
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
index c911dd01db159f10bada2008aa9518babe7249a1..24e2fbec55dde15ee5a2b1f7a3fb70a7220d6fd5 100644 (file)
@@ -98,4 +98,10 @@ pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg,
        dma_sync_sg_for_device(hwdev == NULL ? NULL : &hwdev->dev, sg, nelems, (enum dma_data_direction)direction);
 }
 
+static inline int
+pci_dma_error(dma_addr_t dma_addr)
+{
+       return dma_error(dma_addr);
+}
+
 #endif
index 711937233fb37efa5eebcda318cb6d38dd7c1409..bf6388b246e982ab439d967ce9fe703b71d05792 100644 (file)
@@ -110,6 +110,12 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
        flush_write_buffers();
 }
 
+static inline int
+dma_error(dma_addr_t dma_addr)
+{
+       return 0;
+}
+
 static inline int
 dma_supported(struct device *dev, u64 mask)
 {