diff options
-rw-r--r-- | include/linux/dma-debug.h | 14 | ||||
-rw-r--r-- | lib/dma-debug.c | 66 |
2 files changed, 80 insertions, 0 deletions
diff --git a/include/linux/dma-debug.h b/include/linux/dma-debug.h index ce4ace707c7b..345d5387a30d 100644 --- a/include/linux/dma-debug.h +++ b/include/linux/dma-debug.h | |||
@@ -20,6 +20,20 @@ | |||
20 | #ifndef __DMA_DEBUG_H | 20 | #ifndef __DMA_DEBUG_H |
21 | #define __DMA_DEBUG_H | 21 | #define __DMA_DEBUG_H |
22 | 22 | ||
23 | #include <linux/types.h> | ||
24 | |||
23 | struct device; | 25 | struct device; |
24 | 26 | ||
27 | #ifdef CONFIG_DMA_API_DEBUG | ||
28 | |||
29 | extern void dma_debug_init(u32 num_entries); | ||
30 | |||
31 | #else /* CONFIG_DMA_API_DEBUG */ | ||
32 | |||
33 | static inline void dma_debug_init(u32 num_entries) | ||
34 | { | ||
35 | } | ||
36 | |||
37 | #endif /* CONFIG_DMA_API_DEBUG */ | ||
38 | |||
25 | #endif /* __DMA_DEBUG_H */ | 39 | #endif /* __DMA_DEBUG_H */ |
diff --git a/lib/dma-debug.c b/lib/dma-debug.c index b60914669656..5b50bb31f7c6 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
22 | #include <linux/types.h> | 22 | #include <linux/types.h> |
23 | #include <linux/list.h> | 23 | #include <linux/list.h> |
24 | #include <linux/slab.h> | ||
24 | 25 | ||
25 | #define HASH_SIZE 1024ULL | 26 | #define HASH_SIZE 1024ULL |
26 | #define HASH_FN_SHIFT 13 | 27 | #define HASH_FN_SHIFT 13 |
@@ -198,3 +199,68 @@ static void dma_entry_free(struct dma_debug_entry *entry) | |||
198 | spin_unlock_irqrestore(&free_entries_lock, flags); | 199 | spin_unlock_irqrestore(&free_entries_lock, flags); |
199 | } | 200 | } |
200 | 201 | ||
202 | /* | ||
203 | * DMA-API debugging init code | ||
204 | * | ||
205 | * The init code does two things: | ||
206 | * 1. Initialize core data structures | ||
207 | * 2. Preallocate a given number of dma_debug_entry structs | ||
208 | */ | ||
209 | |||
210 | static int prealloc_memory(u32 num_entries) | ||
211 | { | ||
212 | struct dma_debug_entry *entry, *next_entry; | ||
213 | int i; | ||
214 | |||
215 | for (i = 0; i < num_entries; ++i) { | ||
216 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | ||
217 | if (!entry) | ||
218 | goto out_err; | ||
219 | |||
220 | list_add_tail(&entry->list, &free_entries); | ||
221 | } | ||
222 | |||
223 | num_free_entries = num_entries; | ||
224 | min_free_entries = num_entries; | ||
225 | |||
226 | printk(KERN_INFO "DMA-API: preallocated %d debug entries\n", | ||
227 | num_entries); | ||
228 | |||
229 | return 0; | ||
230 | |||
231 | out_err: | ||
232 | |||
233 | list_for_each_entry_safe(entry, next_entry, &free_entries, list) { | ||
234 | list_del(&entry->list); | ||
235 | kfree(entry); | ||
236 | } | ||
237 | |||
238 | return -ENOMEM; | ||
239 | } | ||
240 | |||
241 | /* | ||
242 | * Let the architectures decide how many entries should be preallocated. | ||
243 | */ | ||
244 | void dma_debug_init(u32 num_entries) | ||
245 | { | ||
246 | int i; | ||
247 | |||
248 | if (global_disable) | ||
249 | return; | ||
250 | |||
251 | for (i = 0; i < HASH_SIZE; ++i) { | ||
252 | INIT_LIST_HEAD(&dma_entry_hash[i].list); | ||
253 | dma_entry_hash[i].lock = SPIN_LOCK_UNLOCKED; | ||
254 | } | ||
255 | |||
256 | if (prealloc_memory(num_entries) != 0) { | ||
257 | printk(KERN_ERR "DMA-API: debugging out of memory error " | ||
258 | "- disabled\n"); | ||
259 | global_disable = true; | ||
260 | |||
261 | return; | ||
262 | } | ||
263 | |||
264 | printk(KERN_INFO "DMA-API: debugging enabled by kernel config\n"); | ||
265 | } | ||
266 | |||