* substitute the safe buffer for the unsafe one.
  * (basically move the buffer from an unsafe area to a safe one)
  */
-dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+dma_addr_t __dma_map_single(struct device *dev, void *ptr, size_t size,
                enum dma_data_direction dir)
 {
        dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
 
        return map_single(dev, ptr, size, dir);
 }
-EXPORT_SYMBOL(dma_map_single);
+EXPORT_SYMBOL(__dma_map_single);
 
 /*
  * see if a mapped address was really a "safe" buffer and if so, copy
  * the safe buffer.  (basically return things back to the way they
  * should be)
  */
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+void __dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
                enum dma_data_direction dir)
 {
        dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
 
        unmap_single(dev, dma_addr, size, dir);
 }
-EXPORT_SYMBOL(dma_unmap_single);
+EXPORT_SYMBOL(__dma_unmap_single);
 
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
+dma_addr_t __dma_map_page(struct device *dev, struct page *page,
                unsigned long offset, size_t size, enum dma_data_direction dir)
 {
        dev_dbg(dev, "%s(page=%p,off=%#lx,size=%zx,dir=%x)\n",
 
        return map_single(dev, page_address(page) + offset, size, dir);
 }
-EXPORT_SYMBOL(dma_map_page);
+EXPORT_SYMBOL(__dma_map_page);
 
 /*
  * see if a mapped address was really a "safe" buffer and if so, copy
  * the safe buffer.  (basically return things back to the way they
  * should be)
  */
-void dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
+void __dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size,
                enum dma_data_direction dir)
 {
        dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
 
        unmap_single(dev, dma_addr, size, dir);
 }
-EXPORT_SYMBOL(dma_unmap_page);
+EXPORT_SYMBOL(__dma_unmap_page);
 
 int dmabounce_sync_for_cpu(struct device *dev, dma_addr_t addr,
                unsigned long off, size_t sz, enum dma_data_direction dir)
 
 
 #include <linux/mm_types.h>
 #include <linux/scatterlist.h>
+#include <linux/dma-debug.h>
 
 #include <asm-generic/dma-coherent.h>
 #include <asm/memory.h>
 /*
  * The DMA API, implemented by dmabounce.c.  See below for descriptions.
  */
-extern dma_addr_t dma_map_single(struct device *, void *, size_t,
+extern dma_addr_t __dma_map_single(struct device *, void *, size_t,
                enum dma_data_direction);
-extern void dma_unmap_single(struct device *, dma_addr_t, size_t,
+extern void __dma_unmap_single(struct device *, dma_addr_t, size_t,
                enum dma_data_direction);
-extern dma_addr_t dma_map_page(struct device *, struct page *,
+extern dma_addr_t __dma_map_page(struct device *, struct page *,
                unsigned long, size_t, enum dma_data_direction);
-extern void dma_unmap_page(struct device *, dma_addr_t, size_t,
+extern void __dma_unmap_page(struct device *, dma_addr_t, size_t,
                enum dma_data_direction);
 
 /*
 }
 
 
+static inline dma_addr_t __dma_map_single(struct device *dev, void *cpu_addr,
+               size_t size, enum dma_data_direction dir)
+{
+       __dma_single_cpu_to_dev(cpu_addr, size, dir);
+       return virt_to_dma(dev, cpu_addr);
+}
+
+static inline dma_addr_t __dma_map_page(struct device *dev, struct page *page,
+            unsigned long offset, size_t size, enum dma_data_direction dir)
+{
+       __dma_page_cpu_to_dev(page, offset, size, dir);
+       return pfn_to_dma(dev, page_to_pfn(page)) + offset;
+}
+
+static inline void __dma_unmap_single(struct device *dev, dma_addr_t handle,
+               size_t size, enum dma_data_direction dir)
+{
+       __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
+}
+
+static inline void __dma_unmap_page(struct device *dev, dma_addr_t handle,
+               size_t size, enum dma_data_direction dir)
+{
+       __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
+               handle & ~PAGE_MASK, size, dir);
+}
+#endif /* CONFIG_DMABOUNCE */
+
 /**
  * dma_map_single - map a single buffer for streaming DMA
  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
 static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
                size_t size, enum dma_data_direction dir)
 {
+       dma_addr_t addr;
+
        BUG_ON(!valid_dma_direction(dir));
 
-       __dma_single_cpu_to_dev(cpu_addr, size, dir);
+       addr = __dma_map_single(dev, cpu_addr, size, dir);
+       debug_dma_map_page(dev, virt_to_page(cpu_addr),
+                       (unsigned long)cpu_addr & ~PAGE_MASK, size,
+                       dir, addr, true);
 
-       return virt_to_dma(dev, cpu_addr);
+       return addr;
 }
 
 /**
 static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
             unsigned long offset, size_t size, enum dma_data_direction dir)
 {
+       dma_addr_t addr;
+
        BUG_ON(!valid_dma_direction(dir));
 
-       __dma_page_cpu_to_dev(page, offset, size, dir);
+       addr = __dma_map_page(dev, page, offset, size, dir);
+       debug_dma_map_page(dev, page, offset, size, dir, addr, false);
 
-       return pfn_to_dma(dev, page_to_pfn(page)) + offset;
+       return addr;
 }
 
 /**
 static inline void dma_unmap_single(struct device *dev, dma_addr_t handle,
                size_t size, enum dma_data_direction dir)
 {
-       __dma_single_dev_to_cpu(dma_to_virt(dev, handle), size, dir);
+       debug_dma_unmap_page(dev, handle, size, dir, true);
+       __dma_unmap_single(dev, handle, size, dir);
 }
 
 /**
 static inline void dma_unmap_page(struct device *dev, dma_addr_t handle,
                size_t size, enum dma_data_direction dir)
 {
-       __dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
-               handle & ~PAGE_MASK, size, dir);
+       debug_dma_unmap_page(dev, handle, size, dir, false);
+       __dma_unmap_page(dev, handle, size, dir);
 }
-#endif /* CONFIG_DMABOUNCE */
 
 /**
  * dma_sync_single_range_for_cpu
 {
        BUG_ON(!valid_dma_direction(dir));
 
+       debug_dma_sync_single_for_cpu(dev, handle + offset, size, dir);
+
        if (!dmabounce_sync_for_cpu(dev, handle, offset, size, dir))
                return;
 
 {
        BUG_ON(!valid_dma_direction(dir));
 
+       debug_dma_sync_single_for_device(dev, handle + offset, size, dir);
+
        if (!dmabounce_sync_for_device(dev, handle, offset, size, dir))
                return;
 
 
        struct scatterlist *s;
        int i, j;
 
+       BUG_ON(!valid_dma_direction(dir));
+
        for_each_sg(sg, s, nents, i) {
-               s->dma_address = dma_map_page(dev, sg_page(s), s->offset,
+               s->dma_address = __dma_map_page(dev, sg_page(s), s->offset,
                                                s->length, dir);
                if (dma_mapping_error(dev, s->dma_address))
                        goto bad_mapping;
        }
+       debug_dma_map_sg(dev, sg, nents, nents, dir);
        return nents;
 
  bad_mapping:
        for_each_sg(sg, s, i, j)
-               dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
+               __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
        return 0;
 }
 EXPORT_SYMBOL(dma_map_sg);
        struct scatterlist *s;
        int i;
 
+       debug_dma_unmap_sg(dev, sg, nents, dir);
+
        for_each_sg(sg, s, nents, i)
-               dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
+               __dma_unmap_page(dev, sg_dma_address(s), sg_dma_len(s), dir);
 }
 EXPORT_SYMBOL(dma_unmap_sg);
 
                __dma_page_dev_to_cpu(sg_page(s), s->offset,
                                      s->length, dir);
        }
+
+       debug_dma_sync_sg_for_cpu(dev, sg, nents, dir);
 }
 EXPORT_SYMBOL(dma_sync_sg_for_cpu);
 
                __dma_page_cpu_to_dev(sg_page(s), s->offset,
                                      s->length, dir);
        }
+
+       debug_dma_sync_sg_for_device(dev, sg, nents, dir);
 }
 EXPORT_SYMBOL(dma_sync_sg_for_device);
+
+#define PREALLOC_DMA_DEBUG_ENTRIES     4096
+
+static int __init dma_debug_do_init(void)
+{
+       dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+       return 0;
+}
+fs_initcall(dma_debug_do_init);