aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/dma-debug.h14
-rw-r--r--lib/dma-debug.c66
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
23struct device; 25struct device;
24 26
27#ifdef CONFIG_DMA_API_DEBUG
28
29extern void dma_debug_init(u32 num_entries);
30
31#else /* CONFIG_DMA_API_DEBUG */
32
33static 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
210static 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
231out_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 */
244void 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