@@ -474,11 +474,11 @@ static int active_pfn_set_overlap(unsigned long pfn, int overlap)
return overlap;
}
-static void active_pfn_inc_overlap(unsigned long pfn)
+static void active_pfn_inc_overlap(struct dma_debug_entry *ent)
{
- int overlap = active_pfn_read_overlap(pfn);
+ int overlap = active_pfn_read_overlap(ent->pfn);
- overlap = active_pfn_set_overlap(pfn, ++overlap);
+ overlap = active_pfn_set_overlap(ent->pfn, ++overlap);
/* If we overflowed the overlap counter then we're potentially
* leaking dma-mappings. Otherwise, if maps and unmaps are
@@ -486,15 +486,43 @@ static void active_pfn_inc_overlap(unsigned long pfn)
* debug_dma_assert_idle() as the pfn may be marked idle
* prematurely.
*/
+
WARN_ONCE(overlap > ACTIVE_PFN_MAX_OVERLAP,
"DMA-API: exceeded %d overlapping mappings of pfn %lx\n",
- ACTIVE_PFN_MAX_OVERLAP, pfn);
+ ACTIVE_PFN_MAX_OVERLAP, ent->pfn);
+
+ if(overlap > ACTIVE_PFN_MAX_OVERLAP){
+
+ dev_info(ent->dev, "DMA-API: exceeded %d overlapping mappings of pfn %lx .. start dump\n", ACTIVE_PFN_MAX_OVERLAP, ent->pfn);
+ int idx;
+
+ for (idx = 0; idx < HASH_SIZE; idx++) {
+ struct hash_bucket *bucket = &dma_entry_hash[idx];
+ struct dma_debug_entry *entry;
+ unsigned long flags;
+
+ list_for_each_entry(entry, &bucket->list, list) {
+ if (entry->pfn == ent->pfn) {
+ dev_info(entry->dev, "%s idx %d P=%Lx N=%lx D=%Lx L=%Lx %s %s\n",
+ type2name[entry->type], idx,
+ phys_addr(entry), entry->pfn,
+ entry->dev_addr, entry->size,
+ dir2name[entry->direction],
+ maperr2str[entry->map_err_type]);
+ }
+ }
+ }
+ dev_info(ent->dev, "DMA-API: exceeded %d overlapping mappings of pfn %lx .. end of dump\n", ACTIVE_PFN_MAX_OVERLAP, ent->pfn);
+ }
}
@@ -505,10 +533,10 @@ static int active_pfn_insert(struct dma_debug_entry *entry)
spin_lock_irqsave(&radix_lock, flags);
rc = radix_tree_insert(&dma_active_pfn, entry->pfn, entry);
- if (rc == -EEXIST)
- active_pfn_inc_overlap(entry->pfn);
+ if (rc == -EEXIST){
+ active_pfn_inc_overlap(entry);
+ }
spin_unlock_irqrestore(&radix_lock, flags);
-
return rc;