diff options
| -rw-r--r-- | lib/dma-debug.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/lib/dma-debug.c b/lib/dma-debug.c index dba02f138bd3..6022eb4a0cd0 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c | |||
| @@ -29,6 +29,8 @@ | |||
| 29 | #include <linux/list.h> | 29 | #include <linux/list.h> |
| 30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
| 31 | 31 | ||
| 32 | #include <asm/sections.h> | ||
| 33 | |||
| 32 | #define HASH_SIZE 1024ULL | 34 | #define HASH_SIZE 1024ULL |
| 33 | #define HASH_FN_SHIFT 13 | 35 | #define HASH_FN_SHIFT 13 |
| 34 | #define HASH_FN_MASK (HASH_SIZE - 1) | 36 | #define HASH_FN_MASK (HASH_SIZE - 1) |
| @@ -549,6 +551,24 @@ static void check_for_stack(struct device *dev, void *addr) | |||
| 549 | "stack [addr=%p]\n", addr); | 551 | "stack [addr=%p]\n", addr); |
| 550 | } | 552 | } |
| 551 | 553 | ||
| 554 | static inline bool overlap(void *addr, u64 size, void *start, void *end) | ||
| 555 | { | ||
| 556 | void *addr2 = (char *)addr + size; | ||
| 557 | |||
| 558 | return ((addr >= start && addr < end) || | ||
| 559 | (addr2 >= start && addr2 < end) || | ||
| 560 | ((addr < start) && (addr2 >= end))); | ||
| 561 | } | ||
| 562 | |||
| 563 | static void check_for_illegal_area(struct device *dev, void *addr, u64 size) | ||
| 564 | { | ||
| 565 | if (overlap(addr, size, _text, _etext) || | ||
| 566 | overlap(addr, size, __start_rodata, __end_rodata)) | ||
| 567 | err_printk(dev, NULL, "DMA-API: device driver maps " | ||
| 568 | "memory from kernel text or rodata " | ||
| 569 | "[addr=%p] [size=%llu]\n", addr, size); | ||
| 570 | } | ||
| 571 | |||
| 552 | static void check_sync(struct device *dev, dma_addr_t addr, | 572 | static void check_sync(struct device *dev, dma_addr_t addr, |
| 553 | u64 size, u64 offset, int direction, bool to_cpu) | 573 | u64 size, u64 offset, int direction, bool to_cpu) |
| 554 | { | 574 | { |
| @@ -645,8 +665,11 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset, | |||
| 645 | entry->direction = direction; | 665 | entry->direction = direction; |
| 646 | 666 | ||
| 647 | if (map_single) { | 667 | if (map_single) { |
| 668 | void *addr = ((char *)page_address(page)) + offset; | ||
| 669 | |||
| 648 | entry->type = dma_debug_single; | 670 | entry->type = dma_debug_single; |
| 649 | check_for_stack(dev, page_address(page) + offset); | 671 | check_for_stack(dev, addr); |
| 672 | check_for_illegal_area(dev, addr, size); | ||
| 650 | } | 673 | } |
| 651 | 674 | ||
| 652 | add_dma_entry(entry); | 675 | add_dma_entry(entry); |
| @@ -699,6 +722,7 @@ void debug_dma_map_sg(struct device *dev, struct scatterlist *sg, | |||
| 699 | entry->sg_mapped_ents = mapped_ents; | 722 | entry->sg_mapped_ents = mapped_ents; |
| 700 | 723 | ||
| 701 | check_for_stack(dev, sg_virt(s)); | 724 | check_for_stack(dev, sg_virt(s)); |
| 725 | check_for_illegal_area(dev, sg_virt(s), s->length); | ||
| 702 | 726 | ||
| 703 | add_dma_entry(entry); | 727 | add_dma_entry(entry); |
| 704 | } | 728 | } |
