Skip to content

Commit e9e81d8

Browse files
rleonmszyprow
authored andcommitted
dma-debug: refactor to use physical addresses for page mapping
Convert the DMA debug infrastructure from page-based to physical address-based mapping as a preparation to rely on physical address for DMA mapping routines. The refactoring renames debug_dma_map_page() to debug_dma_map_phys() and changes its signature to accept a phys_addr_t parameter instead of struct page and offset. Similarly, debug_dma_unmap_page() becomes debug_dma_unmap_phys(). A new dma_debug_phy type is introduced to distinguish physical address mappings from other debug entry types. All callers throughout the codebase are updated to pass physical addresses directly, eliminating the need for page-to-physical conversion in the debug layer. This refactoring eliminates the need to convert between page pointers and physical addresses in the debug layer, making the code more efficient and consistent with the DMA mapping API's physical address focus. Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Signed-off-by: Leon Romanovsky <leonro@nvidia.com> [mszyprow: added a fixup] Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Link: https://lore.kernel.org/r/56d1a6769b68dfcbf8b26a75a7329aeb8e3c3b6a.1757423202.git.leonro@nvidia.com Link: https://lore.kernel.org/all/20250910052618.GH341237@unreal/
1 parent c288d65 commit e9e81d8

5 files changed

Lines changed: 35 additions & 35 deletions

File tree

Documentation/core-api/dma-api.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -761,7 +761,7 @@ example warning message may look like this::
761761
[<ffffffff80235177>] find_busiest_group+0x207/0x8a0
762762
[<ffffffff8064784f>] _spin_lock_irqsave+0x1f/0x50
763763
[<ffffffff803c7ea3>] check_unmap+0x203/0x490
764-
[<ffffffff803c8259>] debug_dma_unmap_page+0x49/0x50
764+
[<ffffffff803c8259>] debug_dma_unmap_phys+0x49/0x50
765765
[<ffffffff80485f26>] nv_tx_done_optimized+0xc6/0x2c0
766766
[<ffffffff80486c13>] nv_nic_irq_optimized+0x73/0x2b0
767767
[<ffffffff8026df84>] handle_IRQ_event+0x34/0x70
@@ -855,7 +855,7 @@ that a driver may be leaking mappings.
855855
dma-debug interface debug_dma_mapping_error() to debug drivers that fail
856856
to check DMA mapping errors on addresses returned by dma_map_single() and
857857
dma_map_page() interfaces. This interface clears a flag set by
858-
debug_dma_map_page() to indicate that dma_mapping_error() has been called by
858+
debug_dma_map_phys() to indicate that dma_mapping_error() has been called by
859859
the driver. When driver does unmap, debug_dma_unmap() checks the flag and if
860860
this flag is still set, prints warning message that includes call trace that
861861
leads up to the unmap. This interface can be called from dma_mapping_error()

include/linux/page-flags.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,7 @@ FOLIO_FLAG(dropbehind, FOLIO_HEAD_PAGE)
618618
#else
619619
PAGEFLAG_FALSE(HighMem, highmem)
620620
#endif
621+
#define PhysHighMem(__p) (PageHighMem(phys_to_page(__p)))
621622

622623
/* Does kmap_local_folio() only allow access to one page of the folio? */
623624
#ifdef CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP

kernel/dma/debug.c

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ enum {
4040
dma_debug_coherent,
4141
dma_debug_resource,
4242
dma_debug_noncoherent,
43+
dma_debug_phy,
4344
};
4445

4546
enum map_err_types {
@@ -143,6 +144,7 @@ static const char *type2name[] = {
143144
[dma_debug_coherent] = "coherent",
144145
[dma_debug_resource] = "resource",
145146
[dma_debug_noncoherent] = "noncoherent",
147+
[dma_debug_phy] = "phy",
146148
};
147149

148150
static const char *dir2name[] = {
@@ -1054,28 +1056,29 @@ static void check_unmap(struct dma_debug_entry *ref)
10541056
dma_entry_free(entry);
10551057
}
10561058

1057-
static void check_for_stack(struct device *dev,
1058-
struct page *page, size_t offset)
1059+
static void check_for_stack(struct device *dev, phys_addr_t phys)
10591060
{
10601061
void *addr;
10611062
struct vm_struct *stack_vm_area = task_stack_vm_area(current);
10621063

10631064
if (!stack_vm_area) {
10641065
/* Stack is direct-mapped. */
1065-
if (PageHighMem(page))
1066+
if (PhysHighMem(phys))
10661067
return;
1067-
addr = page_address(page) + offset;
1068+
addr = phys_to_virt(phys);
10681069
if (object_is_on_stack(addr))
10691070
err_printk(dev, NULL, "device driver maps memory from stack [addr=%p]\n", addr);
10701071
} else {
10711072
/* Stack is vmalloced. */
10721073
int i;
10731074

10741075
for (i = 0; i < stack_vm_area->nr_pages; i++) {
1075-
if (page != stack_vm_area->pages[i])
1076+
if (__phys_to_pfn(phys) !=
1077+
page_to_pfn(stack_vm_area->pages[i]))
10761078
continue;
10771079

1078-
addr = (u8 *)current->stack + i * PAGE_SIZE + offset;
1080+
addr = (u8 *)current->stack + i * PAGE_SIZE +
1081+
(phys % PAGE_SIZE);
10791082
err_printk(dev, NULL, "device driver maps memory from stack [probable addr=%p]\n", addr);
10801083
break;
10811084
}
@@ -1204,9 +1207,8 @@ void debug_dma_map_single(struct device *dev, const void *addr,
12041207
}
12051208
EXPORT_SYMBOL(debug_dma_map_single);
12061209

1207-
void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
1208-
size_t size, int direction, dma_addr_t dma_addr,
1209-
unsigned long attrs)
1210+
void debug_dma_map_phys(struct device *dev, phys_addr_t phys, size_t size,
1211+
int direction, dma_addr_t dma_addr, unsigned long attrs)
12101212
{
12111213
struct dma_debug_entry *entry;
12121214

@@ -1221,19 +1223,18 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
12211223
return;
12221224

12231225
entry->dev = dev;
1224-
entry->type = dma_debug_single;
1225-
entry->paddr = page_to_phys(page) + offset;
1226+
entry->type = dma_debug_phy;
1227+
entry->paddr = phys;
12261228
entry->dev_addr = dma_addr;
12271229
entry->size = size;
12281230
entry->direction = direction;
12291231
entry->map_err_type = MAP_ERR_NOT_CHECKED;
12301232

1231-
check_for_stack(dev, page, offset);
1233+
if (!(attrs & DMA_ATTR_MMIO)) {
1234+
check_for_stack(dev, phys);
12321235

1233-
if (!PageHighMem(page)) {
1234-
void *addr = page_address(page) + offset;
1235-
1236-
check_for_illegal_area(dev, addr, size);
1236+
if (!PhysHighMem(phys))
1237+
check_for_illegal_area(dev, phys_to_virt(phys), size);
12371238
}
12381239

12391240
add_dma_entry(entry, attrs);
@@ -1277,11 +1278,11 @@ void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
12771278
}
12781279
EXPORT_SYMBOL(debug_dma_mapping_error);
12791280

1280-
void debug_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
1281+
void debug_dma_unmap_phys(struct device *dev, dma_addr_t dma_addr,
12811282
size_t size, int direction)
12821283
{
12831284
struct dma_debug_entry ref = {
1284-
.type = dma_debug_single,
1285+
.type = dma_debug_phy,
12851286
.dev = dev,
12861287
.dev_addr = dma_addr,
12871288
.size = size,
@@ -1305,7 +1306,7 @@ void debug_dma_map_sg(struct device *dev, struct scatterlist *sg,
13051306
return;
13061307

13071308
for_each_sg(sg, s, nents, i) {
1308-
check_for_stack(dev, sg_page(s), s->offset);
1309+
check_for_stack(dev, sg_phys(s));
13091310
if (!PageHighMem(sg_page(s)))
13101311
check_for_illegal_area(dev, sg_virt(s), s->length);
13111312
}

kernel/dma/debug.h

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@
99
#define _KERNEL_DMA_DEBUG_H
1010

1111
#ifdef CONFIG_DMA_API_DEBUG
12-
extern void debug_dma_map_page(struct device *dev, struct page *page,
13-
size_t offset, size_t size,
14-
int direction, dma_addr_t dma_addr,
12+
extern void debug_dma_map_phys(struct device *dev, phys_addr_t phys,
13+
size_t size, int direction, dma_addr_t dma_addr,
1514
unsigned long attrs);
1615

17-
extern void debug_dma_unmap_page(struct device *dev, dma_addr_t addr,
16+
extern void debug_dma_unmap_phys(struct device *dev, dma_addr_t addr,
1817
size_t size, int direction);
1918

2019
extern void debug_dma_map_sg(struct device *dev, struct scatterlist *sg,
@@ -62,14 +61,13 @@ extern void debug_dma_free_pages(struct device *dev, struct page *page,
6261
size_t size, int direction,
6362
dma_addr_t dma_addr);
6463
#else /* CONFIG_DMA_API_DEBUG */
65-
static inline void debug_dma_map_page(struct device *dev, struct page *page,
66-
size_t offset, size_t size,
67-
int direction, dma_addr_t dma_addr,
68-
unsigned long attrs)
64+
static inline void debug_dma_map_phys(struct device *dev, phys_addr_t phys,
65+
size_t size, int direction,
66+
dma_addr_t dma_addr, unsigned long attrs)
6967
{
7068
}
7169

72-
static inline void debug_dma_unmap_page(struct device *dev, dma_addr_t addr,
70+
static inline void debug_dma_unmap_phys(struct device *dev, dma_addr_t addr,
7371
size_t size, int direction)
7472
{
7573
}

kernel/dma/mapping.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ dma_addr_t dma_map_page_attrs(struct device *dev, struct page *page,
157157
unsigned long attrs)
158158
{
159159
const struct dma_map_ops *ops = get_dma_ops(dev);
160+
phys_addr_t phys = page_to_phys(page) + offset;
160161
dma_addr_t addr;
161162

162163
BUG_ON(!valid_dma_direction(dir));
@@ -165,16 +166,15 @@ dma_addr_t dma_map_page_attrs(struct device *dev, struct page *page,
165166
return DMA_MAPPING_ERROR;
166167

167168
if (dma_map_direct(dev, ops) ||
168-
arch_dma_map_page_direct(dev, page_to_phys(page) + offset + size))
169+
arch_dma_map_page_direct(dev, phys + size))
169170
addr = dma_direct_map_page(dev, page, offset, size, dir, attrs);
170171
else if (use_dma_iommu(dev))
171172
addr = iommu_dma_map_page(dev, page, offset, size, dir, attrs);
172173
else
173174
addr = ops->map_page(dev, page, offset, size, dir, attrs);
174175
kmsan_handle_dma(page, offset, size, dir);
175-
trace_dma_map_page(dev, page_to_phys(page) + offset, addr, size, dir,
176-
attrs);
177-
debug_dma_map_page(dev, page, offset, size, dir, addr, attrs);
176+
trace_dma_map_page(dev, phys, addr, size, dir, attrs);
177+
debug_dma_map_phys(dev, phys, size, dir, addr, attrs);
178178

179179
return addr;
180180
}
@@ -194,7 +194,7 @@ void dma_unmap_page_attrs(struct device *dev, dma_addr_t addr, size_t size,
194194
else
195195
ops->unmap_page(dev, addr, size, dir, attrs);
196196
trace_dma_unmap_page(dev, addr, size, dir, attrs);
197-
debug_dma_unmap_page(dev, addr, size, dir);
197+
debug_dma_unmap_phys(dev, addr, size, dir);
198198
}
199199
EXPORT_SYMBOL(dma_unmap_page_attrs);
200200

0 commit comments

Comments
 (0)