aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dma-debug.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dma-debug.c')
-rw-r--r--lib/dma-debug.c66
1 files changed, 57 insertions, 9 deletions
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index d84beb994f36..5e396accd3d0 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -45,6 +45,12 @@ enum {
45 dma_debug_coherent, 45 dma_debug_coherent,
46}; 46};
47 47
48enum map_err_types {
49 MAP_ERR_CHECK_NOT_APPLICABLE,
50 MAP_ERR_NOT_CHECKED,
51 MAP_ERR_CHECKED,
52};
53
48#define DMA_DEBUG_STACKTRACE_ENTRIES 5 54#define DMA_DEBUG_STACKTRACE_ENTRIES 5
49 55
50struct dma_debug_entry { 56struct dma_debug_entry {
@@ -57,6 +63,7 @@ struct dma_debug_entry {
57 int direction; 63 int direction;
58 int sg_call_ents; 64 int sg_call_ents;
59 int sg_mapped_ents; 65 int sg_mapped_ents;
66 enum map_err_types map_err_type;
60#ifdef CONFIG_STACKTRACE 67#ifdef CONFIG_STACKTRACE
61 struct stack_trace stacktrace; 68 struct stack_trace stacktrace;
62 unsigned long st_entries[DMA_DEBUG_STACKTRACE_ENTRIES]; 69 unsigned long st_entries[DMA_DEBUG_STACKTRACE_ENTRIES];
@@ -114,6 +121,12 @@ static struct device_driver *current_driver __read_mostly;
114 121
115static DEFINE_RWLOCK(driver_name_lock); 122static DEFINE_RWLOCK(driver_name_lock);
116 123
124static const char *const maperr2str[] = {
125 [MAP_ERR_CHECK_NOT_APPLICABLE] = "dma map error check not applicable",
126 [MAP_ERR_NOT_CHECKED] = "dma map error not checked",
127 [MAP_ERR_CHECKED] = "dma map error checked",
128};
129
117static const char *type2name[4] = { "single", "page", 130static const char *type2name[4] = { "single", "page",
118 "scather-gather", "coherent" }; 131 "scather-gather", "coherent" };
119 132
@@ -376,11 +389,12 @@ void debug_dma_dump_mappings(struct device *dev)
376 list_for_each_entry(entry, &bucket->list, list) { 389 list_for_each_entry(entry, &bucket->list, list) {
377 if (!dev || dev == entry->dev) { 390 if (!dev || dev == entry->dev) {
378 dev_info(entry->dev, 391 dev_info(entry->dev,
379 "%s idx %d P=%Lx D=%Lx L=%Lx %s\n", 392 "%s idx %d P=%Lx D=%Lx L=%Lx %s %s\n",
380 type2name[entry->type], idx, 393 type2name[entry->type], idx,
381 (unsigned long long)entry->paddr, 394 (unsigned long long)entry->paddr,
382 entry->dev_addr, entry->size, 395 entry->dev_addr, entry->size,
383 dir2name[entry->direction]); 396 dir2name[entry->direction],
397 maperr2str[entry->map_err_type]);
384 } 398 }
385 } 399 }
386 400
@@ -844,16 +858,16 @@ static void check_unmap(struct dma_debug_entry *ref)
844 struct hash_bucket *bucket; 858 struct hash_bucket *bucket;
845 unsigned long flags; 859 unsigned long flags;
846 860
847 if (dma_mapping_error(ref->dev, ref->dev_addr)) {
848 err_printk(ref->dev, NULL, "DMA-API: device driver tries "
849 "to free an invalid DMA memory address\n");
850 return;
851 }
852
853 bucket = get_hash_bucket(ref, &flags); 861 bucket = get_hash_bucket(ref, &flags);
854 entry = bucket_find_exact(bucket, ref); 862 entry = bucket_find_exact(bucket, ref);
855 863
856 if (!entry) { 864 if (!entry) {
865 if (dma_mapping_error(ref->dev, ref->dev_addr)) {
866 err_printk(ref->dev, NULL,
867 "DMA-API: device driver tries "
868 "to free an invalid DMA memory address\n");
869 return;
870 }
857 err_printk(ref->dev, NULL, "DMA-API: device driver tries " 871 err_printk(ref->dev, NULL, "DMA-API: device driver tries "
858 "to free DMA memory it has not allocated " 872 "to free DMA memory it has not allocated "
859 "[device address=0x%016llx] [size=%llu bytes]\n", 873 "[device address=0x%016llx] [size=%llu bytes]\n",
@@ -910,6 +924,15 @@ static void check_unmap(struct dma_debug_entry *ref)
910 dir2name[ref->direction]); 924 dir2name[ref->direction]);
911 } 925 }
912 926
927 if (entry->map_err_type == MAP_ERR_NOT_CHECKED) {
928 err_printk(ref->dev, entry,
929 "DMA-API: device driver failed to check map error"
930 "[device address=0x%016llx] [size=%llu bytes] "
931 "[mapped as %s]",
932 ref->dev_addr, ref->size,
933 type2name[entry->type]);
934 }
935
913 hash_bucket_del(entry); 936 hash_bucket_del(entry);
914 dma_entry_free(entry); 937 dma_entry_free(entry);
915 938
@@ -1017,7 +1040,7 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
1017 if (unlikely(global_disable)) 1040 if (unlikely(global_disable))
1018 return; 1041 return;
1019 1042
1020 if (unlikely(dma_mapping_error(dev, dma_addr))) 1043 if (dma_mapping_error(dev, dma_addr))
1021 return; 1044 return;
1022 1045
1023 entry = dma_entry_alloc(); 1046 entry = dma_entry_alloc();
@@ -1030,6 +1053,7 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
1030 entry->dev_addr = dma_addr; 1053 entry->dev_addr = dma_addr;
1031 entry->size = size; 1054 entry->size = size;
1032 entry->direction = direction; 1055 entry->direction = direction;
1056 entry->map_err_type = MAP_ERR_NOT_CHECKED;
1033 1057
1034 if (map_single) 1058 if (map_single)
1035 entry->type = dma_debug_single; 1059 entry->type = dma_debug_single;
@@ -1045,6 +1069,30 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
1045} 1069}
1046EXPORT_SYMBOL(debug_dma_map_page); 1070EXPORT_SYMBOL(debug_dma_map_page);
1047 1071
1072void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
1073{
1074 struct dma_debug_entry ref;
1075 struct dma_debug_entry *entry;
1076 struct hash_bucket *bucket;
1077 unsigned long flags;
1078
1079 if (unlikely(global_disable))
1080 return;
1081
1082 ref.dev = dev;
1083 ref.dev_addr = dma_addr;
1084 bucket = get_hash_bucket(&ref, &flags);
1085 entry = bucket_find_exact(bucket, &ref);
1086
1087 if (!entry)
1088 goto out;
1089
1090 entry->map_err_type = MAP_ERR_CHECKED;
1091out:
1092 put_hash_bucket(bucket, &flags);
1093}
1094EXPORT_SYMBOL(debug_dma_mapping_error);
1095
1048void debug_dma_unmap_page(struct device *dev, dma_addr_t addr, 1096void debug_dma_unmap_page(struct device *dev, dma_addr_t addr,
1049 size_t size, int direction, bool map_single) 1097 size_t size, int direction, bool map_single)
1050{ 1098{