diff options
author | Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se> | 2016-08-10 07:22:15 -0400 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2016-09-26 12:46:41 -0400 |
commit | 0e74b34dfc3318bf4c7e51349d453d49fb8e9e16 (patch) | |
tree | b70ed304ada0970420008f7131e043bc75c8ae6d | |
parent | ba409b31b3d37b52dda4eefcde04f5837c7ee4aa (diff) |
dma-debug: add support for resource mappings
A MMIO mapped resource can not be represented by a struct page so a new
debug type is needed to handle this. This patch add such type and
functionality to add/remove entries and how to translate them to a
physical address.
Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r-- | include/linux/dma-debug.h | 19 | ||||
-rw-r--r-- | lib/dma-debug.c | 52 |
2 files changed, 69 insertions, 2 deletions
diff --git a/include/linux/dma-debug.h b/include/linux/dma-debug.h index fe8cb610deac..c7d844f09c3a 100644 --- a/include/linux/dma-debug.h +++ b/include/linux/dma-debug.h | |||
@@ -56,6 +56,13 @@ extern void debug_dma_alloc_coherent(struct device *dev, size_t size, | |||
56 | extern void debug_dma_free_coherent(struct device *dev, size_t size, | 56 | extern void debug_dma_free_coherent(struct device *dev, size_t size, |
57 | void *virt, dma_addr_t addr); | 57 | void *virt, dma_addr_t addr); |
58 | 58 | ||
59 | extern void debug_dma_map_resource(struct device *dev, phys_addr_t addr, | ||
60 | size_t size, int direction, | ||
61 | dma_addr_t dma_addr); | ||
62 | |||
63 | extern void debug_dma_unmap_resource(struct device *dev, dma_addr_t dma_addr, | ||
64 | size_t size, int direction); | ||
65 | |||
59 | extern void debug_dma_sync_single_for_cpu(struct device *dev, | 66 | extern void debug_dma_sync_single_for_cpu(struct device *dev, |
60 | dma_addr_t dma_handle, size_t size, | 67 | dma_addr_t dma_handle, size_t size, |
61 | int direction); | 68 | int direction); |
@@ -141,6 +148,18 @@ static inline void debug_dma_free_coherent(struct device *dev, size_t size, | |||
141 | { | 148 | { |
142 | } | 149 | } |
143 | 150 | ||
151 | static inline void debug_dma_map_resource(struct device *dev, phys_addr_t addr, | ||
152 | size_t size, int direction, | ||
153 | dma_addr_t dma_addr) | ||
154 | { | ||
155 | } | ||
156 | |||
157 | static inline void debug_dma_unmap_resource(struct device *dev, | ||
158 | dma_addr_t dma_addr, size_t size, | ||
159 | int direction) | ||
160 | { | ||
161 | } | ||
162 | |||
144 | static inline void debug_dma_sync_single_for_cpu(struct device *dev, | 163 | static inline void debug_dma_sync_single_for_cpu(struct device *dev, |
145 | dma_addr_t dma_handle, | 164 | dma_addr_t dma_handle, |
146 | size_t size, int direction) | 165 | size_t size, int direction) |
diff --git a/lib/dma-debug.c b/lib/dma-debug.c index fcfa1939ac41..2ba086b0d3e7 100644 --- a/lib/dma-debug.c +++ b/lib/dma-debug.c | |||
@@ -43,6 +43,7 @@ enum { | |||
43 | dma_debug_page, | 43 | dma_debug_page, |
44 | dma_debug_sg, | 44 | dma_debug_sg, |
45 | dma_debug_coherent, | 45 | dma_debug_coherent, |
46 | dma_debug_resource, | ||
46 | }; | 47 | }; |
47 | 48 | ||
48 | enum map_err_types { | 49 | enum map_err_types { |
@@ -150,8 +151,9 @@ static const char *const maperr2str[] = { | |||
150 | [MAP_ERR_CHECKED] = "dma map error checked", | 151 | [MAP_ERR_CHECKED] = "dma map error checked", |
151 | }; | 152 | }; |
152 | 153 | ||
153 | static const char *type2name[4] = { "single", "page", | 154 | static const char *type2name[5] = { "single", "page", |
154 | "scather-gather", "coherent" }; | 155 | "scather-gather", "coherent", |
156 | "resource" }; | ||
155 | 157 | ||
156 | static const char *dir2name[4] = { "DMA_BIDIRECTIONAL", "DMA_TO_DEVICE", | 158 | static const char *dir2name[4] = { "DMA_BIDIRECTIONAL", "DMA_TO_DEVICE", |
157 | "DMA_FROM_DEVICE", "DMA_NONE" }; | 159 | "DMA_FROM_DEVICE", "DMA_NONE" }; |
@@ -399,6 +401,9 @@ static void hash_bucket_del(struct dma_debug_entry *entry) | |||
399 | 401 | ||
400 | static unsigned long long phys_addr(struct dma_debug_entry *entry) | 402 | static unsigned long long phys_addr(struct dma_debug_entry *entry) |
401 | { | 403 | { |
404 | if (entry->type == dma_debug_resource) | ||
405 | return __pfn_to_phys(entry->pfn) + entry->offset; | ||
406 | |||
402 | return page_to_phys(pfn_to_page(entry->pfn)) + entry->offset; | 407 | return page_to_phys(pfn_to_page(entry->pfn)) + entry->offset; |
403 | } | 408 | } |
404 | 409 | ||
@@ -1495,6 +1500,49 @@ void debug_dma_free_coherent(struct device *dev, size_t size, | |||
1495 | } | 1500 | } |
1496 | EXPORT_SYMBOL(debug_dma_free_coherent); | 1501 | EXPORT_SYMBOL(debug_dma_free_coherent); |
1497 | 1502 | ||
1503 | void debug_dma_map_resource(struct device *dev, phys_addr_t addr, size_t size, | ||
1504 | int direction, dma_addr_t dma_addr) | ||
1505 | { | ||
1506 | struct dma_debug_entry *entry; | ||
1507 | |||
1508 | if (unlikely(dma_debug_disabled())) | ||
1509 | return; | ||
1510 | |||
1511 | entry = dma_entry_alloc(); | ||
1512 | if (!entry) | ||
1513 | return; | ||
1514 | |||
1515 | entry->type = dma_debug_resource; | ||
1516 | entry->dev = dev; | ||
1517 | entry->pfn = __phys_to_pfn(addr); | ||
1518 | entry->offset = offset_in_page(addr); | ||
1519 | entry->size = size; | ||
1520 | entry->dev_addr = dma_addr; | ||
1521 | entry->direction = direction; | ||
1522 | entry->map_err_type = MAP_ERR_NOT_CHECKED; | ||
1523 | |||
1524 | add_dma_entry(entry); | ||
1525 | } | ||
1526 | EXPORT_SYMBOL(debug_dma_map_resource); | ||
1527 | |||
1528 | void debug_dma_unmap_resource(struct device *dev, dma_addr_t dma_addr, | ||
1529 | size_t size, int direction) | ||
1530 | { | ||
1531 | struct dma_debug_entry ref = { | ||
1532 | .type = dma_debug_resource, | ||
1533 | .dev = dev, | ||
1534 | .dev_addr = dma_addr, | ||
1535 | .size = size, | ||
1536 | .direction = direction, | ||
1537 | }; | ||
1538 | |||
1539 | if (unlikely(dma_debug_disabled())) | ||
1540 | return; | ||
1541 | |||
1542 | check_unmap(&ref); | ||
1543 | } | ||
1544 | EXPORT_SYMBOL(debug_dma_unmap_resource); | ||
1545 | |||
1498 | void debug_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, | 1546 | void debug_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, |
1499 | size_t size, int direction) | 1547 | size_t size, int direction) |
1500 | { | 1548 | { |