aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dma-debug.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2014-02-07 14:27:30 -0500
committerH. Peter Anvin <hpa@linux.intel.com>2014-02-07 14:27:30 -0500
commita3b072cd180c12e8fe0ece9487b9065808327640 (patch)
tree62b982041be84748852d77cdf6ca5639ef40858f /lib/dma-debug.c
parent75a1ba5b2c529db60ca49626bcaf0bddf4548438 (diff)
parent081cd62a010f97b5bc1d2b0cd123c5abc692b68a (diff)
Merge tag 'efi-urgent' into x86/urgent
* Avoid WARN_ON() when mapping BGRT on Baytrail (EFI 32-bit). Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'lib/dma-debug.c')
-rw-r--r--lib/dma-debug.c197
1 files changed, 184 insertions, 13 deletions
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index d87a17a819d0..2defd1308b04 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -53,11 +53,26 @@ enum map_err_types {
53 53
54#define DMA_DEBUG_STACKTRACE_ENTRIES 5 54#define DMA_DEBUG_STACKTRACE_ENTRIES 5
55 55
56/**
57 * struct dma_debug_entry - track a dma_map* or dma_alloc_coherent mapping
58 * @list: node on pre-allocated free_entries list
59 * @dev: 'dev' argument to dma_map_{page|single|sg} or dma_alloc_coherent
60 * @type: single, page, sg, coherent
61 * @pfn: page frame of the start address
62 * @offset: offset of mapping relative to pfn
63 * @size: length of the mapping
64 * @direction: enum dma_data_direction
65 * @sg_call_ents: 'nents' from dma_map_sg
66 * @sg_mapped_ents: 'mapped_ents' from dma_map_sg
67 * @map_err_type: track whether dma_mapping_error() was checked
68 * @stacktrace: support backtraces when a violation is detected
69 */
56struct dma_debug_entry { 70struct dma_debug_entry {
57 struct list_head list; 71 struct list_head list;
58 struct device *dev; 72 struct device *dev;
59 int type; 73 int type;
60 phys_addr_t paddr; 74 unsigned long pfn;
75 size_t offset;
61 u64 dev_addr; 76 u64 dev_addr;
62 u64 size; 77 u64 size;
63 int direction; 78 int direction;
@@ -372,6 +387,11 @@ static void hash_bucket_del(struct dma_debug_entry *entry)
372 list_del(&entry->list); 387 list_del(&entry->list);
373} 388}
374 389
390static unsigned long long phys_addr(struct dma_debug_entry *entry)
391{
392 return page_to_phys(pfn_to_page(entry->pfn)) + entry->offset;
393}
394
375/* 395/*
376 * Dump mapping entries for debugging purposes 396 * Dump mapping entries for debugging purposes
377 */ 397 */
@@ -389,9 +409,9 @@ void debug_dma_dump_mappings(struct device *dev)
389 list_for_each_entry(entry, &bucket->list, list) { 409 list_for_each_entry(entry, &bucket->list, list) {
390 if (!dev || dev == entry->dev) { 410 if (!dev || dev == entry->dev) {
391 dev_info(entry->dev, 411 dev_info(entry->dev,
392 "%s idx %d P=%Lx D=%Lx L=%Lx %s %s\n", 412 "%s idx %d P=%Lx N=%lx D=%Lx L=%Lx %s %s\n",
393 type2name[entry->type], idx, 413 type2name[entry->type], idx,
394 (unsigned long long)entry->paddr, 414 phys_addr(entry), entry->pfn,
395 entry->dev_addr, entry->size, 415 entry->dev_addr, entry->size,
396 dir2name[entry->direction], 416 dir2name[entry->direction],
397 maperr2str[entry->map_err_type]); 417 maperr2str[entry->map_err_type]);
@@ -404,6 +424,137 @@ void debug_dma_dump_mappings(struct device *dev)
404EXPORT_SYMBOL(debug_dma_dump_mappings); 424EXPORT_SYMBOL(debug_dma_dump_mappings);
405 425
406/* 426/*
427 * For each page mapped (initial page in the case of
428 * dma_alloc_coherent/dma_map_{single|page}, or each page in a
429 * scatterlist) insert into this tree using the pfn as the key. At
430 * dma_unmap_{single|sg|page} or dma_free_coherent delete the entry. If
431 * the pfn already exists at insertion time add a tag as a reference
432 * count for the overlapping mappings. For now, the overlap tracking
433 * just ensures that 'unmaps' balance 'maps' before marking the pfn
434 * idle, but we should also be flagging overlaps as an API violation.
435 *
436 * Memory usage is mostly constrained by the maximum number of available
437 * dma-debug entries in that we need a free dma_debug_entry before
438 * inserting into the tree. In the case of dma_map_{single|page} and
439 * dma_alloc_coherent there is only one dma_debug_entry and one pfn to
440 * track per event. dma_map_sg(), on the other hand,
441 * consumes a single dma_debug_entry, but inserts 'nents' entries into
442 * the tree.
443 *
444 * At any time debug_dma_assert_idle() can be called to trigger a
445 * warning if the given page is in the active set.
446 */
447static RADIX_TREE(dma_active_pfn, GFP_NOWAIT);
448static DEFINE_SPINLOCK(radix_lock);
449#define ACTIVE_PFN_MAX_OVERLAP ((1 << RADIX_TREE_MAX_TAGS) - 1)
450
451static int active_pfn_read_overlap(unsigned long pfn)
452{
453 int overlap = 0, i;
454
455 for (i = RADIX_TREE_MAX_TAGS - 1; i >= 0; i--)
456 if (radix_tree_tag_get(&dma_active_pfn, pfn, i))
457 overlap |= 1 << i;
458 return overlap;
459}
460
461static int active_pfn_set_overlap(unsigned long pfn, int overlap)
462{
463 int i;
464
465 if (overlap > ACTIVE_PFN_MAX_OVERLAP || overlap < 0)
466 return overlap;
467
468 for (i = RADIX_TREE_MAX_TAGS - 1; i >= 0; i--)
469 if (overlap & 1 << i)
470 radix_tree_tag_set(&dma_active_pfn, pfn, i);
471 else
472 radix_tree_tag_clear(&dma_active_pfn, pfn, i);
473
474 return overlap;
475}
476
477static void active_pfn_inc_overlap(unsigned long pfn)
478{
479 int overlap = active_pfn_read_overlap(pfn);
480
481 overlap = active_pfn_set_overlap(pfn, ++overlap);
482
483 /* If we overflowed the overlap counter then we're potentially
484 * leaking dma-mappings. Otherwise, if maps and unmaps are
485 * balanced then this overflow may cause false negatives in
486 * debug_dma_assert_idle() as the pfn may be marked idle
487 * prematurely.
488 */
489 WARN_ONCE(overlap > ACTIVE_PFN_MAX_OVERLAP,
490 "DMA-API: exceeded %d overlapping mappings of pfn %lx\n",
491 ACTIVE_PFN_MAX_OVERLAP, pfn);
492}
493
494static int active_pfn_dec_overlap(unsigned long pfn)
495{
496 int overlap = active_pfn_read_overlap(pfn);
497
498 return active_pfn_set_overlap(pfn, --overlap);
499}
500
501static int active_pfn_insert(struct dma_debug_entry *entry)
502{
503 unsigned long flags;
504 int rc;
505
506 spin_lock_irqsave(&radix_lock, flags);
507 rc = radix_tree_insert(&dma_active_pfn, entry->pfn, entry);
508 if (rc == -EEXIST)
509 active_pfn_inc_overlap(entry->pfn);
510 spin_unlock_irqrestore(&radix_lock, flags);
511
512 return rc;
513}
514
515static void active_pfn_remove(struct dma_debug_entry *entry)
516{
517 unsigned long flags;
518
519 spin_lock_irqsave(&radix_lock, flags);
520 /* since we are counting overlaps the final put of the
521 * entry->pfn will occur when the overlap count is 0.
522 * active_pfn_dec_overlap() returns -1 in that case
523 */
524 if (active_pfn_dec_overlap(entry->pfn) < 0)
525 radix_tree_delete(&dma_active_pfn, entry->pfn);
526 spin_unlock_irqrestore(&radix_lock, flags);
527}
528
529/**
530 * debug_dma_assert_idle() - assert that a page is not undergoing dma
531 * @page: page to lookup in the dma_active_pfn tree
532 *
533 * Place a call to this routine in cases where the cpu touching the page
534 * before the dma completes (page is dma_unmapped) will lead to data
535 * corruption.
536 */
537void debug_dma_assert_idle(struct page *page)
538{
539 unsigned long flags;
540 struct dma_debug_entry *entry;
541
542 if (!page)
543 return;
544
545 spin_lock_irqsave(&radix_lock, flags);
546 entry = radix_tree_lookup(&dma_active_pfn, page_to_pfn(page));
547 spin_unlock_irqrestore(&radix_lock, flags);
548
549 if (!entry)
550 return;
551
552 err_printk(entry->dev, entry,
553 "DMA-API: cpu touching an active dma mapped page "
554 "[pfn=0x%lx]\n", entry->pfn);
555}
556
557/*
407 * Wrapper function for adding an entry to the hash. 558 * Wrapper function for adding an entry to the hash.
408 * This function takes care of locking itself. 559 * This function takes care of locking itself.
409 */ 560 */
@@ -411,10 +562,21 @@ static void add_dma_entry(struct dma_debug_entry *entry)
411{ 562{
412 struct hash_bucket *bucket; 563 struct hash_bucket *bucket;
413 unsigned long flags; 564 unsigned long flags;
565 int rc;
414 566
415 bucket = get_hash_bucket(entry, &flags); 567 bucket = get_hash_bucket(entry, &flags);
416 hash_bucket_add(bucket, entry); 568 hash_bucket_add(bucket, entry);
417 put_hash_bucket(bucket, &flags); 569 put_hash_bucket(bucket, &flags);
570
571 rc = active_pfn_insert(entry);
572 if (rc == -ENOMEM) {
573 pr_err("DMA-API: pfn tracking ENOMEM, dma-debug disabled\n");
574 global_disable = true;
575 }
576
577 /* TODO: report -EEXIST errors here as overlapping mappings are
578 * not supported by the DMA API
579 */
418} 580}
419 581
420static struct dma_debug_entry *__dma_entry_alloc(void) 582static struct dma_debug_entry *__dma_entry_alloc(void)
@@ -469,6 +631,8 @@ static void dma_entry_free(struct dma_debug_entry *entry)
469{ 631{
470 unsigned long flags; 632 unsigned long flags;
471 633
634 active_pfn_remove(entry);
635
472 /* 636 /*
473 * add to beginning of the list - this way the entries are 637 * add to beginning of the list - this way the entries are
474 * more likely cache hot when they are reallocated. 638 * more likely cache hot when they are reallocated.
@@ -895,15 +1059,15 @@ static void check_unmap(struct dma_debug_entry *ref)
895 ref->dev_addr, ref->size, 1059 ref->dev_addr, ref->size,
896 type2name[entry->type], type2name[ref->type]); 1060 type2name[entry->type], type2name[ref->type]);
897 } else if ((entry->type == dma_debug_coherent) && 1061 } else if ((entry->type == dma_debug_coherent) &&
898 (ref->paddr != entry->paddr)) { 1062 (phys_addr(ref) != phys_addr(entry))) {
899 err_printk(ref->dev, entry, "DMA-API: device driver frees " 1063 err_printk(ref->dev, entry, "DMA-API: device driver frees "
900 "DMA memory with different CPU address " 1064 "DMA memory with different CPU address "
901 "[device address=0x%016llx] [size=%llu bytes] " 1065 "[device address=0x%016llx] [size=%llu bytes] "
902 "[cpu alloc address=0x%016llx] " 1066 "[cpu alloc address=0x%016llx] "
903 "[cpu free address=0x%016llx]", 1067 "[cpu free address=0x%016llx]",
904 ref->dev_addr, ref->size, 1068 ref->dev_addr, ref->size,
905 (unsigned long long)entry->paddr, 1069 phys_addr(entry),
906 (unsigned long long)ref->paddr); 1070 phys_addr(ref));
907 } 1071 }
908 1072
909 if (ref->sg_call_ents && ref->type == dma_debug_sg && 1073 if (ref->sg_call_ents && ref->type == dma_debug_sg &&
@@ -1052,7 +1216,8 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
1052 1216
1053 entry->dev = dev; 1217 entry->dev = dev;
1054 entry->type = dma_debug_page; 1218 entry->type = dma_debug_page;
1055 entry->paddr = page_to_phys(page) + offset; 1219 entry->pfn = page_to_pfn(page);
1220 entry->offset = offset,
1056 entry->dev_addr = dma_addr; 1221 entry->dev_addr = dma_addr;
1057 entry->size = size; 1222 entry->size = size;
1058 entry->direction = direction; 1223 entry->direction = direction;
@@ -1148,7 +1313,8 @@ void debug_dma_map_sg(struct device *dev, struct scatterlist *sg,
1148 1313
1149 entry->type = dma_debug_sg; 1314 entry->type = dma_debug_sg;
1150 entry->dev = dev; 1315 entry->dev = dev;
1151 entry->paddr = sg_phys(s); 1316 entry->pfn = page_to_pfn(sg_page(s));
1317 entry->offset = s->offset,
1152 entry->size = sg_dma_len(s); 1318 entry->size = sg_dma_len(s);
1153 entry->dev_addr = sg_dma_address(s); 1319 entry->dev_addr = sg_dma_address(s);
1154 entry->direction = direction; 1320 entry->direction = direction;
@@ -1198,7 +1364,8 @@ void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
1198 struct dma_debug_entry ref = { 1364 struct dma_debug_entry ref = {
1199 .type = dma_debug_sg, 1365 .type = dma_debug_sg,
1200 .dev = dev, 1366 .dev = dev,
1201 .paddr = sg_phys(s), 1367 .pfn = page_to_pfn(sg_page(s)),
1368 .offset = s->offset,
1202 .dev_addr = sg_dma_address(s), 1369 .dev_addr = sg_dma_address(s),
1203 .size = sg_dma_len(s), 1370 .size = sg_dma_len(s),
1204 .direction = dir, 1371 .direction = dir,
@@ -1233,7 +1400,8 @@ void debug_dma_alloc_coherent(struct device *dev, size_t size,
1233 1400
1234 entry->type = dma_debug_coherent; 1401 entry->type = dma_debug_coherent;
1235 entry->dev = dev; 1402 entry->dev = dev;
1236 entry->paddr = virt_to_phys(virt); 1403 entry->pfn = page_to_pfn(virt_to_page(virt));
1404 entry->offset = (size_t) virt & PAGE_MASK;
1237 entry->size = size; 1405 entry->size = size;
1238 entry->dev_addr = dma_addr; 1406 entry->dev_addr = dma_addr;
1239 entry->direction = DMA_BIDIRECTIONAL; 1407 entry->direction = DMA_BIDIRECTIONAL;
@@ -1248,7 +1416,8 @@ void debug_dma_free_coherent(struct device *dev, size_t size,
1248 struct dma_debug_entry ref = { 1416 struct dma_debug_entry ref = {
1249 .type = dma_debug_coherent, 1417 .type = dma_debug_coherent,
1250 .dev = dev, 1418 .dev = dev,
1251 .paddr = virt_to_phys(virt), 1419 .pfn = page_to_pfn(virt_to_page(virt)),
1420 .offset = (size_t) virt & PAGE_MASK,
1252 .dev_addr = addr, 1421 .dev_addr = addr,
1253 .size = size, 1422 .size = size,
1254 .direction = DMA_BIDIRECTIONAL, 1423 .direction = DMA_BIDIRECTIONAL,
@@ -1356,7 +1525,8 @@ void debug_dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
1356 struct dma_debug_entry ref = { 1525 struct dma_debug_entry ref = {
1357 .type = dma_debug_sg, 1526 .type = dma_debug_sg,
1358 .dev = dev, 1527 .dev = dev,
1359 .paddr = sg_phys(s), 1528 .pfn = page_to_pfn(sg_page(s)),
1529 .offset = s->offset,
1360 .dev_addr = sg_dma_address(s), 1530 .dev_addr = sg_dma_address(s),
1361 .size = sg_dma_len(s), 1531 .size = sg_dma_len(s),
1362 .direction = direction, 1532 .direction = direction,
@@ -1388,7 +1558,8 @@ void debug_dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
1388 struct dma_debug_entry ref = { 1558 struct dma_debug_entry ref = {
1389 .type = dma_debug_sg, 1559 .type = dma_debug_sg,
1390 .dev = dev, 1560 .dev = dev,
1391 .paddr = sg_phys(s), 1561 .pfn = page_to_pfn(sg_page(s)),
1562 .offset = s->offset,
1392 .dev_addr = sg_dma_address(s), 1563 .dev_addr = sg_dma_address(s),
1393 .size = sg_dma_len(s), 1564 .size = sg_dma_len(s),
1394 .direction = direction, 1565 .direction = direction,