diff options
-rw-r--r-- | include/linux/dma-debug.h | 7 | ||||
-rw-r--r-- | lib/dma-debug.c | 55 |
2 files changed, 62 insertions, 0 deletions
diff --git a/include/linux/dma-debug.h b/include/linux/dma-debug.h index 46a11c10da04..e851d23e91eb 100644 --- a/include/linux/dma-debug.h +++ b/include/linux/dma-debug.h | |||
@@ -24,9 +24,12 @@ | |||
24 | 24 | ||
25 | struct device; | 25 | struct device; |
26 | struct scatterlist; | 26 | struct scatterlist; |
27 | struct bus_type; | ||
27 | 28 | ||
28 | #ifdef CONFIG_DMA_API_DEBUG | 29 | #ifdef CONFIG_DMA_API_DEBUG |
29 | 30 | ||
31 | extern void dma_debug_add_bus(struct bus_type *bus); | ||
32 | |||
30 | extern void dma_debug_init(u32 num_entries); | 33 | extern void dma_debug_init(u32 num_entries); |
31 | 34 | ||
32 | extern void debug_dma_map_page(struct device *dev, struct page *page, | 35 | extern void debug_dma_map_page(struct device *dev, struct page *page, |
@@ -80,6 +83,10 @@ extern void debug_dma_dump_mappings(struct device *dev); | |||
80 | 83 | ||
81 | #else /* CONFIG_DMA_API_DEBUG */ | 84 | #else /* CONFIG_DMA_API_DEBUG */ |
82 | 85 | ||
86 | void dma_debug_add_bus(struct bus_type *bus) | ||
87 | { | ||
88 | } | ||
89 | |||
83 | static inline void dma_debug_init(u32 num_entries) | 90 | static inline void dma_debug_init(u32 num_entries) |
84 | { | 91 | { |
85 | } | 92 | } |
diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 6022eb4a0cd0..9a350b414a50 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c | |||
@@ -400,6 +400,61 @@ out_err: | |||
400 | return -ENOMEM; | 400 | return -ENOMEM; |
401 | } | 401 | } |
402 | 402 | ||
403 | static int device_dma_allocations(struct device *dev) | ||
404 | { | ||
405 | struct dma_debug_entry *entry; | ||
406 | unsigned long flags; | ||
407 | int count = 0, i; | ||
408 | |||
409 | for (i = 0; i < HASH_SIZE; ++i) { | ||
410 | spin_lock_irqsave(&dma_entry_hash[i].lock, flags); | ||
411 | list_for_each_entry(entry, &dma_entry_hash[i].list, list) { | ||
412 | if (entry->dev == dev) | ||
413 | count += 1; | ||
414 | } | ||
415 | spin_unlock_irqrestore(&dma_entry_hash[i].lock, flags); | ||
416 | } | ||
417 | |||
418 | return count; | ||
419 | } | ||
420 | |||
421 | static int dma_debug_device_change(struct notifier_block *nb, | ||
422 | unsigned long action, void *data) | ||
423 | { | ||
424 | struct device *dev = data; | ||
425 | int count; | ||
426 | |||
427 | |||
428 | switch (action) { | ||
429 | case BUS_NOTIFY_UNBIND_DRIVER: | ||
430 | count = device_dma_allocations(dev); | ||
431 | if (count == 0) | ||
432 | break; | ||
433 | err_printk(dev, NULL, "DMA-API: device driver has pending " | ||
434 | "DMA allocations while released from device " | ||
435 | "[count=%d]\n", count); | ||
436 | break; | ||
437 | default: | ||
438 | break; | ||
439 | } | ||
440 | |||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | void dma_debug_add_bus(struct bus_type *bus) | ||
445 | { | ||
446 | struct notifier_block *nb; | ||
447 | |||
448 | nb = kzalloc(sizeof(struct notifier_block), GFP_KERNEL); | ||
449 | if (nb == NULL) { | ||
450 | printk(KERN_ERR "dma_debug_add_bus: out of memory\n"); | ||
451 | return; | ||
452 | } | ||
453 | |||
454 | nb->notifier_call = dma_debug_device_change; | ||
455 | |||
456 | bus_register_notifier(bus, nb); | ||
457 | } | ||
403 | 458 | ||
404 | /* | 459 | /* |
405 | * Let the architectures decide how many entries should be preallocated. | 460 | * Let the architectures decide how many entries should be preallocated. |