aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2009-04-09 13:36:54 -0400
committerPaul Mundt <lethal@linux-sh.org>2009-04-09 13:36:54 -0400
commitf802d969b6a89d3f9b67ef879179824d53420ebe (patch)
tree73748811278c85817b59240d63e610c8a9565132
parentb35346fd25f3c8c0b6afeb778f8c4f41c5703c84 (diff)
sh: Add support for DMA API debugging.
This wires up support for the generic DMA API debugging. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r--arch/sh/Kconfig1
-rw-r--r--arch/sh/include/asm/dma-mapping.h36
-rw-r--r--arch/sh/include/asm/scatterlist.h11
-rw-r--r--arch/sh/mm/consistent.c19
4 files changed, 51 insertions, 16 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 5e4babecf934..45f4a322ce4a 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -14,6 +14,7 @@ config SUPERH
14 select HAVE_GENERIC_DMA_COHERENT 14 select HAVE_GENERIC_DMA_COHERENT
15 select HAVE_IOREMAP_PROT if MMU 15 select HAVE_IOREMAP_PROT if MMU
16 select HAVE_ARCH_TRACEHOOK 16 select HAVE_ARCH_TRACEHOOK
17 select HAVE_DMA_API_DEBUG
17 help 18 help
18 The SuperH is a RISC processor targeted for use in embedded systems 19 The SuperH is a RISC processor targeted for use in embedded systems
19 and consumer electronics; it was also used in the Sega Dreamcast 20 and consumer electronics; it was also used in the Sega Dreamcast
diff --git a/arch/sh/include/asm/dma-mapping.h b/arch/sh/include/asm/dma-mapping.h
index 627315ecdb52..ea9d4f41c9d2 100644
--- a/arch/sh/include/asm/dma-mapping.h
+++ b/arch/sh/include/asm/dma-mapping.h
@@ -3,6 +3,7 @@
3 3
4#include <linux/mm.h> 4#include <linux/mm.h>
5#include <linux/scatterlist.h> 5#include <linux/scatterlist.h>
6#include <linux/dma-debug.h>
6#include <asm/cacheflush.h> 7#include <asm/cacheflush.h>
7#include <asm/io.h> 8#include <asm/io.h>
8#include <asm-generic/dma-coherent.h> 9#include <asm-generic/dma-coherent.h>
@@ -38,16 +39,26 @@ static inline dma_addr_t dma_map_single(struct device *dev,
38 void *ptr, size_t size, 39 void *ptr, size_t size,
39 enum dma_data_direction dir) 40 enum dma_data_direction dir)
40{ 41{
42 dma_addr_t addr = virt_to_phys(ptr);
43
41#if defined(CONFIG_PCI) && !defined(CONFIG_SH_PCIDMA_NONCOHERENT) 44#if defined(CONFIG_PCI) && !defined(CONFIG_SH_PCIDMA_NONCOHERENT)
42 if (dev->bus == &pci_bus_type) 45 if (dev->bus == &pci_bus_type)
43 return virt_to_phys(ptr); 46 return addr;
44#endif 47#endif
45 dma_cache_sync(dev, ptr, size, dir); 48 dma_cache_sync(dev, ptr, size, dir);
46 49
47 return virt_to_phys(ptr); 50 debug_dma_map_page(dev, virt_to_page(ptr),
51 (unsigned long)ptr & ~PAGE_MASK, size,
52 dir, addr, true);
53
54 return addr;
48} 55}
49 56
50#define dma_unmap_single(dev, addr, size, dir) do { } while (0) 57static inline void dma_unmap_single(struct device *dev, dma_addr_t addr,
58 size_t size, enum dma_data_direction dir)
59{
60 debug_dma_unmap_page(dev, addr, size, dir, true);
61}
51 62
52static inline int dma_map_sg(struct device *dev, struct scatterlist *sg, 63static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
53 int nents, enum dma_data_direction dir) 64 int nents, enum dma_data_direction dir)
@@ -59,12 +70,19 @@ static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
59 dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir); 70 dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir);
60#endif 71#endif
61 sg[i].dma_address = sg_phys(&sg[i]); 72 sg[i].dma_address = sg_phys(&sg[i]);
73 sg[i].dma_length = sg[i].length;
62 } 74 }
63 75
76 debug_dma_map_sg(dev, sg, nents, i, dir);
77
64 return nents; 78 return nents;
65} 79}
66 80
67#define dma_unmap_sg(dev, sg, nents, dir) do { } while (0) 81static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
82 int nents, enum dma_data_direction dir)
83{
84 debug_dma_unmap_sg(dev, sg, nents, dir);
85}
68 86
69static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, 87static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
70 unsigned long offset, size_t size, 88 unsigned long offset, size_t size,
@@ -111,6 +129,7 @@ static inline void dma_sync_sg(struct device *dev, struct scatterlist *sg,
111 dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir); 129 dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir);
112#endif 130#endif
113 sg[i].dma_address = sg_phys(&sg[i]); 131 sg[i].dma_address = sg_phys(&sg[i]);
132 sg[i].dma_length = sg[i].length;
114 } 133 }
115} 134}
116 135
@@ -119,6 +138,7 @@ static inline void dma_sync_single_for_cpu(struct device *dev,
119 enum dma_data_direction dir) 138 enum dma_data_direction dir)
120{ 139{
121 dma_sync_single(dev, dma_handle, size, dir); 140 dma_sync_single(dev, dma_handle, size, dir);
141 debug_dma_sync_single_for_cpu(dev, dma_handle, size, dir);
122} 142}
123 143
124static inline void dma_sync_single_for_device(struct device *dev, 144static inline void dma_sync_single_for_device(struct device *dev,
@@ -127,6 +147,7 @@ static inline void dma_sync_single_for_device(struct device *dev,
127 enum dma_data_direction dir) 147 enum dma_data_direction dir)
128{ 148{
129 dma_sync_single(dev, dma_handle, size, dir); 149 dma_sync_single(dev, dma_handle, size, dir);
150 debug_dma_sync_single_for_device(dev, dma_handle, size, dir);
130} 151}
131 152
132static inline void dma_sync_single_range_for_cpu(struct device *dev, 153static inline void dma_sync_single_range_for_cpu(struct device *dev,
@@ -136,6 +157,8 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev,
136 enum dma_data_direction direction) 157 enum dma_data_direction direction)
137{ 158{
138 dma_sync_single_for_cpu(dev, dma_handle+offset, size, direction); 159 dma_sync_single_for_cpu(dev, dma_handle+offset, size, direction);
160 debug_dma_sync_single_range_for_cpu(dev, dma_handle,
161 offset, size, direction);
139} 162}
140 163
141static inline void dma_sync_single_range_for_device(struct device *dev, 164static inline void dma_sync_single_range_for_device(struct device *dev,
@@ -145,6 +168,8 @@ static inline void dma_sync_single_range_for_device(struct device *dev,
145 enum dma_data_direction direction) 168 enum dma_data_direction direction)
146{ 169{
147 dma_sync_single_for_device(dev, dma_handle+offset, size, direction); 170 dma_sync_single_for_device(dev, dma_handle+offset, size, direction);
171 debug_dma_sync_single_range_for_device(dev, dma_handle,
172 offset, size, direction);
148} 173}
149 174
150 175
@@ -153,6 +178,7 @@ static inline void dma_sync_sg_for_cpu(struct device *dev,
153 enum dma_data_direction dir) 178 enum dma_data_direction dir)
154{ 179{
155 dma_sync_sg(dev, sg, nelems, dir); 180 dma_sync_sg(dev, sg, nelems, dir);
181 debug_dma_sync_sg_for_cpu(dev, sg, nelems, dir);
156} 182}
157 183
158static inline void dma_sync_sg_for_device(struct device *dev, 184static inline void dma_sync_sg_for_device(struct device *dev,
@@ -160,9 +186,9 @@ static inline void dma_sync_sg_for_device(struct device *dev,
160 enum dma_data_direction dir) 186 enum dma_data_direction dir)
161{ 187{
162 dma_sync_sg(dev, sg, nelems, dir); 188 dma_sync_sg(dev, sg, nelems, dir);
189 debug_dma_sync_sg_for_device(dev, sg, nelems, dir);
163} 190}
164 191
165
166static inline int dma_get_cache_alignment(void) 192static inline int dma_get_cache_alignment(void)
167{ 193{
168 /* 194 /*
diff --git a/arch/sh/include/asm/scatterlist.h b/arch/sh/include/asm/scatterlist.h
index 2084d0373693..c693d268a413 100644
--- a/arch/sh/include/asm/scatterlist.h
+++ b/arch/sh/include/asm/scatterlist.h
@@ -5,12 +5,13 @@
5 5
6struct scatterlist { 6struct scatterlist {
7#ifdef CONFIG_DEBUG_SG 7#ifdef CONFIG_DEBUG_SG
8 unsigned long sg_magic; 8 unsigned long sg_magic;
9#endif 9#endif
10 unsigned long page_link; 10 unsigned long page_link;
11 unsigned int offset;/* for highmem, page offset */ 11 unsigned int offset; /* for highmem, page offset */
12 dma_addr_t dma_address; 12 unsigned int length;
13 unsigned int length; 13 dma_addr_t dma_address;
14 unsigned int dma_length;
14}; 15};
15 16
16#define ISA_DMA_THRESHOLD PHYS_ADDR_MASK 17#define ISA_DMA_THRESHOLD PHYS_ADDR_MASK
diff --git a/arch/sh/mm/consistent.c b/arch/sh/mm/consistent.c
index edcd5fbf9651..8c9ee855328a 100644
--- a/arch/sh/mm/consistent.c
+++ b/arch/sh/mm/consistent.c
@@ -12,6 +12,7 @@
12#include <linux/mm.h> 12#include <linux/mm.h>
13#include <linux/platform_device.h> 13#include <linux/platform_device.h>
14#include <linux/dma-mapping.h> 14#include <linux/dma-mapping.h>
15#include <linux/dma-debug.h>
15#include <asm/cacheflush.h> 16#include <asm/cacheflush.h>
16#include <asm/addrspace.h> 17#include <asm/addrspace.h>
17#include <asm/io.h> 18#include <asm/io.h>
@@ -45,6 +46,9 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
45 split_page(pfn_to_page(virt_to_phys(ret) >> PAGE_SHIFT), order); 46 split_page(pfn_to_page(virt_to_phys(ret) >> PAGE_SHIFT), order);
46 47
47 *dma_handle = virt_to_phys(ret); 48 *dma_handle = virt_to_phys(ret);
49
50 debug_dma_alloc_coherent(dev, size, *dma_handle, ret_nocache);
51
48 return ret_nocache; 52 return ret_nocache;
49} 53}
50EXPORT_SYMBOL(dma_alloc_coherent); 54EXPORT_SYMBOL(dma_alloc_coherent);
@@ -56,12 +60,15 @@ void dma_free_coherent(struct device *dev, size_t size,
56 unsigned long pfn = dma_handle >> PAGE_SHIFT; 60 unsigned long pfn = dma_handle >> PAGE_SHIFT;
57 int k; 61 int k;
58 62
59 if (!dma_release_from_coherent(dev, order, vaddr)) { 63 WARN_ON(irqs_disabled()); /* for portability */
60 WARN_ON(irqs_disabled()); /* for portability */ 64
61 for (k = 0; k < (1 << order); k++) 65 if (dma_release_from_coherent(dev, order, vaddr))
62 __free_pages(pfn_to_page(pfn + k), 0); 66 return;
63 iounmap(vaddr); 67
64 } 68 debug_dma_free_coherent(dev, size, vaddr, dma_handle);
69 for (k = 0; k < (1 << order); k++)
70 __free_pages(pfn_to_page(pfn + k), 0);
71 iounmap(vaddr);
65} 72}
66EXPORT_SYMBOL(dma_free_coherent); 73EXPORT_SYMBOL(dma_free_coherent);
67 74