So I split that check up into pre_map and post_map parts but then that
seemed like overkill just to check for this vmalloc problem. Here's the
patch if you're interested. I can make it a little nicer if you think
it's also worthwhile.
---8<----
include/linux/dma-debug.h | 8 ++++++++
include/linux/dma-mapping.h | 3 +++
kernel/dma/debug.c | 24 ++++++++++++++++--------
3 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/include/linux/dma-debug.h b/include/linux/dma-debug.h
index 5aec2ca8a426..3287240a474c 100644
--- a/include/linux/dma-debug.h
+++ b/include/linux/dma-debug.h
@@ -35,6 +35,9 @@ extern int dma_debug_resize_entries(u32 num_entries);
extern void debug_dma_check_vmalloc(struct device *dev, const void *addr,
unsigned long len);
+extern void debug_dma_pre_map_page(struct device *dev, struct page *page,
+ size_t offset, size_t size);
+
extern void debug_dma_map_page(struct device *dev, struct page *page,
size_t offset, size_t size,
int direction, dma_addr_t dma_addr,
@@ -111,6 +114,11 @@ static inline void debug_dma_check_vmalloc(struct device
*dev, const void *addr,
{
}
+static inline void debug_dma_pre_map_page(struct device *dev, struct page *page,
+ size_t offset, size_t size)
+{
+}
+
static inline void debug_dma_map_page(struct device *dev, struct page *page,
size_t offset, size_t size,
int direction, dma_addr_t dma_addr,
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index a0e67fd5433c..4839bbb4fdc7 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -233,6 +233,8 @@ static inline dma_addr_t dma_map_single_attrs(struct device
*dev, void *ptr,
BUG_ON(!valid_dma_direction(dir));
debug_dma_check_vmalloc(dev, ptr, size);
+ debug_dma_pre_map_page(dev, virt_to_page(ptr),
+ offset_in_page(ptr), size);
addr = ops->map_page(dev, virt_to_page(ptr),
offset_in_page(ptr), size,
dir, attrs);
@@ -296,6 +298,7 @@ static inline dma_addr_t dma_map_page_attrs(struct device
*dev,
dma_addr_t addr;
BUG_ON(!valid_dma_direction(dir));
+ debug_dma_pre_map_page(dev, page, offset, size);
addr = ops->map_page(dev, page, offset, size, dir, attrs);
debug_dma_map_page(dev, page, offset, size, dir, addr, false);
diff --git a/kernel/dma/debug.c b/kernel/dma/debug.c
index 7ee7978868d4..dd1ff9f7d783 100644
--- a/kernel/dma/debug.c
+++ b/kernel/dma/debug.c
@@ -1324,6 +1324,22 @@ void debug_dma_check_vmalloc(struct device *dev, const
void *addr,
}
EXPORT_SYMBOL(debug_dma_check_vmalloc);
+void debug_dma_pre_map_page(struct device *dev, struct page *page, size_t offset,
+ size_t size)
+{
+ if (unlikely(dma_debug_disabled()))
+ return;
+
+ check_for_stack(dev, page, offset);
+
+ if (!PageHighMem(page)) {
+ void *addr = page_address(page) + offset;
+
+ check_for_illegal_area(dev, addr, size);
+ }
+}
+EXPORT_SYMBOL(debug_dma_pre_map_page);
+
void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
size_t size, int direction, dma_addr_t dma_addr,
bool map_single)
@@ -1352,14 +1368,6 @@ void debug_dma_map_page(struct device *dev, struct page
*page, size_t offset,
if (map_single)
entry->type = dma_debug_single;
- check_for_stack(dev, page, offset);
-
- if (!PageHighMem(page)) {
- void *addr = page_address(page) + offset;
-
- check_for_illegal_area(dev, addr, size);
- }
-
add_dma_entry(entry);
}
EXPORT_SYMBOL(debug_dma_map_page);