aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Woodhouse <dwmw2@infradead.org>2009-01-19 10:52:39 -0500
committerJoerg Roedel <joerg.roedel@amd.com>2009-03-17 07:56:48 -0400
commit6c132d1bcdc716e898b4092bb1abc696505c37e7 (patch)
tree4000e2c7a7d87a80b1d70a29f4ed74227f1a826d
parent187f9c3f05373df4f7cbae2e656450acdbba7558 (diff)
dma-debug: print stacktrace of mapping path on unmap error
Impact: saves stacktrace of a dma mapping and prints it if there is an error Signed-off-by: David Woodhouse <dwmw2@infradead.org> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
-rw-r--r--lib/dma-debug.c52
1 files changed, 38 insertions, 14 deletions
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 91ed1dfdbaac..dba02f138bd3 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -19,6 +19,7 @@
19 19
20#include <linux/scatterlist.h> 20#include <linux/scatterlist.h>
21#include <linux/dma-mapping.h> 21#include <linux/dma-mapping.h>
22#include <linux/stacktrace.h>
22#include <linux/dma-debug.h> 23#include <linux/dma-debug.h>
23#include <linux/spinlock.h> 24#include <linux/spinlock.h>
24#include <linux/debugfs.h> 25#include <linux/debugfs.h>
@@ -39,6 +40,8 @@ enum {
39 dma_debug_coherent, 40 dma_debug_coherent,
40}; 41};
41 42
43#define DMA_DEBUG_STACKTRACE_ENTRIES 5
44
42struct dma_debug_entry { 45struct dma_debug_entry {
43 struct list_head list; 46 struct list_head list;
44 struct device *dev; 47 struct device *dev;
@@ -49,6 +52,10 @@ struct dma_debug_entry {
49 int direction; 52 int direction;
50 int sg_call_ents; 53 int sg_call_ents;
51 int sg_mapped_ents; 54 int sg_mapped_ents;
55#ifdef CONFIG_STACKTRACE
56 struct stack_trace stacktrace;
57 unsigned long st_entries[DMA_DEBUG_STACKTRACE_ENTRIES];
58#endif
52}; 59};
53 60
54struct hash_bucket { 61struct hash_bucket {
@@ -108,12 +115,23 @@ static const char *dir2name[4] = { "DMA_BIDIRECTIONAL", "DMA_TO_DEVICE",
108 * system log than the user configured. This variable is 115 * system log than the user configured. This variable is
109 * writeable via debugfs. 116 * writeable via debugfs.
110 */ 117 */
111#define err_printk(dev, format, arg...) do { \ 118static inline void dump_entry_trace(struct dma_debug_entry *entry)
119{
120#ifdef CONFIG_STACKTRACE
121 if (entry) {
122 printk(KERN_WARNING "Mapped at:\n");
123 print_stack_trace(&entry->stacktrace, 0);
124 }
125#endif
126}
127
128#define err_printk(dev, entry, format, arg...) do { \
112 error_count += 1; \ 129 error_count += 1; \
113 if (show_all_errors || show_num_errors > 0) { \ 130 if (show_all_errors || show_num_errors > 0) { \
114 WARN(1, "%s %s: " format, \ 131 WARN(1, "%s %s: " format, \
115 dev_driver_string(dev), \ 132 dev_driver_string(dev), \
116 dev_name(dev) , ## arg); \ 133 dev_name(dev) , ## arg); \
134 dump_entry_trace(entry); \
117 } \ 135 } \
118 if (!show_all_errors && show_num_errors > 0) \ 136 if (!show_all_errors && show_num_errors > 0) \
119 show_num_errors -= 1; \ 137 show_num_errors -= 1; \
@@ -260,6 +278,12 @@ static struct dma_debug_entry *dma_entry_alloc(void)
260 list_del(&entry->list); 278 list_del(&entry->list);
261 memset(entry, 0, sizeof(*entry)); 279 memset(entry, 0, sizeof(*entry));
262 280
281#ifdef CONFIG_STACKTRACE
282 entry->stacktrace.max_entries = DMA_DEBUG_STACKTRACE_ENTRIES;
283 entry->stacktrace.entries = entry->st_entries;
284 entry->stacktrace.skip = 2;
285 save_stack_trace(&entry->stacktrace);
286#endif
263 num_free_entries -= 1; 287 num_free_entries -= 1;
264 if (num_free_entries < min_free_entries) 288 if (num_free_entries < min_free_entries)
265 min_free_entries = num_free_entries; 289 min_free_entries = num_free_entries;
@@ -457,7 +481,7 @@ static void check_unmap(struct dma_debug_entry *ref)
457 entry = hash_bucket_find(bucket, ref); 481 entry = hash_bucket_find(bucket, ref);
458 482
459 if (!entry) { 483 if (!entry) {
460 err_printk(ref->dev, "DMA-API: device driver tries " 484 err_printk(ref->dev, NULL, "DMA-API: device driver tries "
461 "to free DMA memory it has not allocated " 485 "to free DMA memory it has not allocated "
462 "[device address=0x%016llx] [size=%llu bytes]\n", 486 "[device address=0x%016llx] [size=%llu bytes]\n",
463 ref->dev_addr, ref->size); 487 ref->dev_addr, ref->size);
@@ -465,7 +489,7 @@ static void check_unmap(struct dma_debug_entry *ref)
465 } 489 }
466 490
467 if (ref->size != entry->size) { 491 if (ref->size != entry->size) {
468 err_printk(ref->dev, "DMA-API: device driver frees " 492 err_printk(ref->dev, entry, "DMA-API: device driver frees "
469 "DMA memory with different size " 493 "DMA memory with different size "
470 "[device address=0x%016llx] [map size=%llu bytes] " 494 "[device address=0x%016llx] [map size=%llu bytes] "
471 "[unmap size=%llu bytes]\n", 495 "[unmap size=%llu bytes]\n",
@@ -473,7 +497,7 @@ static void check_unmap(struct dma_debug_entry *ref)
473 } 497 }
474 498
475 if (ref->type != entry->type) { 499 if (ref->type != entry->type) {
476 err_printk(ref->dev, "DMA-API: device driver frees " 500 err_printk(ref->dev, entry, "DMA-API: device driver frees "
477 "DMA memory with wrong function " 501 "DMA memory with wrong function "
478 "[device address=0x%016llx] [size=%llu bytes] " 502 "[device address=0x%016llx] [size=%llu bytes] "
479 "[mapped as %s] [unmapped as %s]\n", 503 "[mapped as %s] [unmapped as %s]\n",
@@ -481,7 +505,7 @@ static void check_unmap(struct dma_debug_entry *ref)
481 type2name[entry->type], type2name[ref->type]); 505 type2name[entry->type], type2name[ref->type]);
482 } else if ((entry->type == dma_debug_coherent) && 506 } else if ((entry->type == dma_debug_coherent) &&
483 (ref->paddr != entry->paddr)) { 507 (ref->paddr != entry->paddr)) {
484 err_printk(ref->dev, "DMA-API: device driver frees " 508 err_printk(ref->dev, entry, "DMA-API: device driver frees "
485 "DMA memory with different CPU address " 509 "DMA memory with different CPU address "
486 "[device address=0x%016llx] [size=%llu bytes] " 510 "[device address=0x%016llx] [size=%llu bytes] "
487 "[cpu alloc address=%p] [cpu free address=%p]", 511 "[cpu alloc address=%p] [cpu free address=%p]",
@@ -491,7 +515,7 @@ static void check_unmap(struct dma_debug_entry *ref)
491 515
492 if (ref->sg_call_ents && ref->type == dma_debug_sg && 516 if (ref->sg_call_ents && ref->type == dma_debug_sg &&
493 ref->sg_call_ents != entry->sg_call_ents) { 517 ref->sg_call_ents != entry->sg_call_ents) {
494 err_printk(ref->dev, "DMA-API: device driver frees " 518 err_printk(ref->dev, entry, "DMA-API: device driver frees "
495 "DMA sg list with different entry count " 519 "DMA sg list with different entry count "
496 "[map count=%d] [unmap count=%d]\n", 520 "[map count=%d] [unmap count=%d]\n",
497 entry->sg_call_ents, ref->sg_call_ents); 521 entry->sg_call_ents, ref->sg_call_ents);
@@ -502,7 +526,7 @@ static void check_unmap(struct dma_debug_entry *ref)
502 * DMA API don't handle this properly, so check for it here 526 * DMA API don't handle this properly, so check for it here
503 */ 527 */
504 if (ref->direction != entry->direction) { 528 if (ref->direction != entry->direction) {
505 err_printk(ref->dev, "DMA-API: device driver frees " 529 err_printk(ref->dev, entry, "DMA-API: device driver frees "
506 "DMA memory with different direction " 530 "DMA memory with different direction "
507 "[device address=0x%016llx] [size=%llu bytes] " 531 "[device address=0x%016llx] [size=%llu bytes] "
508 "[mapped with %s] [unmapped with %s]\n", 532 "[mapped with %s] [unmapped with %s]\n",
@@ -521,8 +545,8 @@ out:
521static void check_for_stack(struct device *dev, void *addr) 545static void check_for_stack(struct device *dev, void *addr)
522{ 546{
523 if (object_is_on_stack(addr)) 547 if (object_is_on_stack(addr))
524 err_printk(dev, "DMA-API: device driver maps memory from stack" 548 err_printk(dev, NULL, "DMA-API: device driver maps memory from"
525 " [addr=%p]\n", addr); 549 "stack [addr=%p]\n", addr);
526} 550}
527 551
528static void check_sync(struct device *dev, dma_addr_t addr, 552static void check_sync(struct device *dev, dma_addr_t addr,
@@ -543,7 +567,7 @@ static void check_sync(struct device *dev, dma_addr_t addr,
543 entry = hash_bucket_find(bucket, &ref); 567 entry = hash_bucket_find(bucket, &ref);
544 568
545 if (!entry) { 569 if (!entry) {
546 err_printk(dev, "DMA-API: device driver tries " 570 err_printk(dev, NULL, "DMA-API: device driver tries "
547 "to sync DMA memory it has not allocated " 571 "to sync DMA memory it has not allocated "
548 "[device address=0x%016llx] [size=%llu bytes]\n", 572 "[device address=0x%016llx] [size=%llu bytes]\n",
549 addr, size); 573 addr, size);
@@ -551,7 +575,7 @@ static void check_sync(struct device *dev, dma_addr_t addr,
551 } 575 }
552 576
553 if ((offset + size) > entry->size) { 577 if ((offset + size) > entry->size) {
554 err_printk(dev, "DMA-API: device driver syncs" 578 err_printk(dev, entry, "DMA-API: device driver syncs"
555 " DMA memory outside allocated range " 579 " DMA memory outside allocated range "
556 "[device address=0x%016llx] " 580 "[device address=0x%016llx] "
557 "[allocation size=%llu bytes] [sync offset=%llu] " 581 "[allocation size=%llu bytes] [sync offset=%llu] "
@@ -560,7 +584,7 @@ static void check_sync(struct device *dev, dma_addr_t addr,
560 } 584 }
561 585
562 if (direction != entry->direction) { 586 if (direction != entry->direction) {
563 err_printk(dev, "DMA-API: device driver syncs " 587 err_printk(dev, entry, "DMA-API: device driver syncs "
564 "DMA memory with different direction " 588 "DMA memory with different direction "
565 "[device address=0x%016llx] [size=%llu bytes] " 589 "[device address=0x%016llx] [size=%llu bytes] "
566 "[mapped with %s] [synced with %s]\n", 590 "[mapped with %s] [synced with %s]\n",
@@ -574,7 +598,7 @@ static void check_sync(struct device *dev, dma_addr_t addr,
574 598
575 if (to_cpu && !(entry->direction == DMA_FROM_DEVICE) && 599 if (to_cpu && !(entry->direction == DMA_FROM_DEVICE) &&
576 !(direction == DMA_TO_DEVICE)) 600 !(direction == DMA_TO_DEVICE))
577 err_printk(dev, "DMA-API: device driver syncs " 601 err_printk(dev, entry, "DMA-API: device driver syncs "
578 "device read-only DMA memory for cpu " 602 "device read-only DMA memory for cpu "
579 "[device address=0x%016llx] [size=%llu bytes] " 603 "[device address=0x%016llx] [size=%llu bytes] "
580 "[mapped with %s] [synced with %s]\n", 604 "[mapped with %s] [synced with %s]\n",
@@ -584,7 +608,7 @@ static void check_sync(struct device *dev, dma_addr_t addr,
584 608
585 if (!to_cpu && !(entry->direction == DMA_TO_DEVICE) && 609 if (!to_cpu && !(entry->direction == DMA_TO_DEVICE) &&
586 !(direction == DMA_FROM_DEVICE)) 610 !(direction == DMA_FROM_DEVICE))
587 err_printk(dev, "DMA-API: device driver syncs " 611 err_printk(dev, entry, "DMA-API: device driver syncs "
588 "device write-only DMA memory to device " 612 "device write-only DMA memory to device "
589 "[device address=0x%016llx] [size=%llu bytes] " 613 "[device address=0x%016llx] [size=%llu bytes] "
590 "[mapped with %s] [synced with %s]\n", 614 "[mapped with %s] [synced with %s]\n",