diff options
Diffstat (limited to 'lib/dma-debug.c')
-rw-r--r-- | lib/dma-debug.c | 54 |
1 files changed, 29 insertions, 25 deletions
diff --git a/lib/dma-debug.c b/lib/dma-debug.c index 3b93129a968c..58a9f9fc609a 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c | |||
@@ -156,9 +156,13 @@ static bool driver_filter(struct device *dev) | |||
156 | return true; | 156 | return true; |
157 | 157 | ||
158 | /* driver filter on and initialized */ | 158 | /* driver filter on and initialized */ |
159 | if (current_driver && dev->driver == current_driver) | 159 | if (current_driver && dev && dev->driver == current_driver) |
160 | return true; | 160 | return true; |
161 | 161 | ||
162 | /* driver filter on, but we can't filter on a NULL device... */ | ||
163 | if (!dev) | ||
164 | return false; | ||
165 | |||
162 | if (current_driver || !current_driver_name[0]) | 166 | if (current_driver || !current_driver_name[0]) |
163 | return false; | 167 | return false; |
164 | 168 | ||
@@ -183,17 +187,17 @@ static bool driver_filter(struct device *dev) | |||
183 | return ret; | 187 | return ret; |
184 | } | 188 | } |
185 | 189 | ||
186 | #define err_printk(dev, entry, format, arg...) do { \ | 190 | #define err_printk(dev, entry, format, arg...) do { \ |
187 | error_count += 1; \ | 191 | error_count += 1; \ |
188 | if (driver_filter(dev) && \ | 192 | if (driver_filter(dev) && \ |
189 | (show_all_errors || show_num_errors > 0)) { \ | 193 | (show_all_errors || show_num_errors > 0)) { \ |
190 | WARN(1, "%s %s: " format, \ | 194 | WARN(1, "%s %s: " format, \ |
191 | dev_driver_string(dev), \ | 195 | dev ? dev_driver_string(dev) : "NULL", \ |
192 | dev_name(dev) , ## arg); \ | 196 | dev ? dev_name(dev) : "NULL", ## arg); \ |
193 | dump_entry_trace(entry); \ | 197 | dump_entry_trace(entry); \ |
194 | } \ | 198 | } \ |
195 | if (!show_all_errors && show_num_errors > 0) \ | 199 | if (!show_all_errors && show_num_errors > 0) \ |
196 | show_num_errors -= 1; \ | 200 | show_num_errors -= 1; \ |
197 | } while (0); | 201 | } while (0); |
198 | 202 | ||
199 | /* | 203 | /* |
@@ -716,7 +720,7 @@ void dma_debug_init(u32 num_entries) | |||
716 | 720 | ||
717 | for (i = 0; i < HASH_SIZE; ++i) { | 721 | for (i = 0; i < HASH_SIZE; ++i) { |
718 | INIT_LIST_HEAD(&dma_entry_hash[i].list); | 722 | INIT_LIST_HEAD(&dma_entry_hash[i].list); |
719 | dma_entry_hash[i].lock = SPIN_LOCK_UNLOCKED; | 723 | spin_lock_init(&dma_entry_hash[i].lock); |
720 | } | 724 | } |
721 | 725 | ||
722 | if (dma_debug_fs_init() != 0) { | 726 | if (dma_debug_fs_init() != 0) { |
@@ -856,22 +860,21 @@ static void check_for_stack(struct device *dev, void *addr) | |||
856 | "stack [addr=%p]\n", addr); | 860 | "stack [addr=%p]\n", addr); |
857 | } | 861 | } |
858 | 862 | ||
859 | static inline bool overlap(void *addr, u64 size, void *start, void *end) | 863 | static inline bool overlap(void *addr, unsigned long len, void *start, void *end) |
860 | { | 864 | { |
861 | void *addr2 = (char *)addr + size; | 865 | unsigned long a1 = (unsigned long)addr; |
866 | unsigned long b1 = a1 + len; | ||
867 | unsigned long a2 = (unsigned long)start; | ||
868 | unsigned long b2 = (unsigned long)end; | ||
862 | 869 | ||
863 | return ((addr >= start && addr < end) || | 870 | return !(b1 <= a2 || a1 >= b2); |
864 | (addr2 >= start && addr2 < end) || | ||
865 | ((addr < start) && (addr2 >= end))); | ||
866 | } | 871 | } |
867 | 872 | ||
868 | static void check_for_illegal_area(struct device *dev, void *addr, u64 size) | 873 | static void check_for_illegal_area(struct device *dev, void *addr, unsigned long len) |
869 | { | 874 | { |
870 | if (overlap(addr, size, _text, _etext) || | 875 | if (overlap(addr, len, _text, _etext) || |
871 | overlap(addr, size, __start_rodata, __end_rodata)) | 876 | overlap(addr, len, __start_rodata, __end_rodata)) |
872 | err_printk(dev, NULL, "DMA-API: device driver maps " | 877 | err_printk(dev, NULL, "DMA-API: device driver maps memory from kernel text or rodata [addr=%p] [len=%lu]\n", addr, len); |
873 | "memory from kernel text or rodata " | ||
874 | "[addr=%p] [size=%llu]\n", addr, size); | ||
875 | } | 878 | } |
876 | 879 | ||
877 | static void check_sync(struct device *dev, | 880 | static void check_sync(struct device *dev, |
@@ -969,7 +972,8 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset, | |||
969 | entry->type = dma_debug_single; | 972 | entry->type = dma_debug_single; |
970 | 973 | ||
971 | if (!PageHighMem(page)) { | 974 | if (!PageHighMem(page)) { |
972 | void *addr = ((char *)page_address(page)) + offset; | 975 | void *addr = page_address(page) + offset; |
976 | |||
973 | check_for_stack(dev, addr); | 977 | check_for_stack(dev, addr); |
974 | check_for_illegal_area(dev, addr, size); | 978 | check_for_illegal_area(dev, addr, size); |
975 | } | 979 | } |