Skip to content

Commit f732619

Browse files
rleonmszyprow
authored andcommitted
dma-mapping: export new dma_*map_phys() interface
Introduce new DMA mapping functions dma_map_phys() and dma_unmap_phys() that operate directly on physical addresses instead of page+offset parameters. This provides a more efficient interface for drivers that already have physical addresses available. The new functions are implemented as the primary mapping layer, with the existing dma_map_page_attrs()/dma_map_resource() and dma_unmap_page_attrs()/dma_unmap_resource() functions converted to simple wrappers around the phys-based implementations. In case dma_map_page_attrs(), the struct page is converted to physical address with help of page_to_phys() function and dma_map_resource() provides physical address as is together with addition of DMA_ATTR_MMIO attribute. The old page-based API is preserved in mapping.c to ensure that existing code won't be affected by changing EXPORT_SYMBOL to EXPORT_SYMBOL_GPL variant for dma_*map_phys(). Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Reviewed-by: Keith Busch <kbusch@kernel.org> Signed-off-by: Leon Romanovsky <leonro@nvidia.com> Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Link: https://lore.kernel.org/r/54cc52af91777906bbe4a386113437ba0bcfba9c.1757423202.git.leonro@nvidia.com
1 parent bf0ecb3 commit f732619

File tree

9 files changed

+50
-134
lines changed

9 files changed

+50
-134
lines changed

drivers/iommu/dma-iommu.c

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,20 +1556,6 @@ void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
15561556
__iommu_dma_unmap(dev, start, end - start);
15571557
}
15581558

1559-
dma_addr_t iommu_dma_map_resource(struct device *dev, phys_addr_t phys,
1560-
size_t size, enum dma_data_direction dir, unsigned long attrs)
1561-
{
1562-
return __iommu_dma_map(dev, phys, size,
1563-
dma_info_to_prot(dir, false, attrs) | IOMMU_MMIO,
1564-
dma_get_mask(dev));
1565-
}
1566-
1567-
void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
1568-
size_t size, enum dma_data_direction dir, unsigned long attrs)
1569-
{
1570-
__iommu_dma_unmap(dev, handle, size);
1571-
}
1572-
15731559
static void __iommu_dma_free(struct device *dev, size_t size, void *cpu_addr)
15741560
{
15751561
size_t alloc_size = PAGE_ALIGN(size);

include/linux/dma-direct.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,5 @@ void dma_direct_free_pages(struct device *dev, size_t size,
149149
struct page *page, dma_addr_t dma_addr,
150150
enum dma_data_direction dir);
151151
int dma_direct_supported(struct device *dev, u64 mask);
152-
dma_addr_t dma_direct_map_resource(struct device *dev, phys_addr_t paddr,
153-
size_t size, enum dma_data_direction dir, unsigned long attrs);
154152

155153
#endif /* _LINUX_DMA_DIRECT_H */

include/linux/dma-mapping.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ dma_addr_t dma_map_page_attrs(struct device *dev, struct page *page,
138138
unsigned long attrs);
139139
void dma_unmap_page_attrs(struct device *dev, dma_addr_t addr, size_t size,
140140
enum dma_data_direction dir, unsigned long attrs);
141+
dma_addr_t dma_map_phys(struct device *dev, phys_addr_t phys, size_t size,
142+
enum dma_data_direction dir, unsigned long attrs);
143+
void dma_unmap_phys(struct device *dev, dma_addr_t addr, size_t size,
144+
enum dma_data_direction dir, unsigned long attrs);
141145
unsigned int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
142146
int nents, enum dma_data_direction dir, unsigned long attrs);
143147
void dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg,
@@ -192,6 +196,15 @@ static inline void dma_unmap_page_attrs(struct device *dev, dma_addr_t addr,
192196
size_t size, enum dma_data_direction dir, unsigned long attrs)
193197
{
194198
}
199+
static inline dma_addr_t dma_map_phys(struct device *dev, phys_addr_t phys,
200+
size_t size, enum dma_data_direction dir, unsigned long attrs)
201+
{
202+
return DMA_MAPPING_ERROR;
203+
}
204+
static inline void dma_unmap_phys(struct device *dev, dma_addr_t addr,
205+
size_t size, enum dma_data_direction dir, unsigned long attrs)
206+
{
207+
}
195208
static inline unsigned int dma_map_sg_attrs(struct device *dev,
196209
struct scatterlist *sg, int nents, enum dma_data_direction dir,
197210
unsigned long attrs)

include/linux/iommu-dma.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,6 @@ size_t iommu_dma_opt_mapping_size(void);
4242
size_t iommu_dma_max_mapping_size(struct device *dev);
4343
void iommu_dma_free(struct device *dev, size_t size, void *cpu_addr,
4444
dma_addr_t handle, unsigned long attrs);
45-
dma_addr_t iommu_dma_map_resource(struct device *dev, phys_addr_t phys,
46-
size_t size, enum dma_data_direction dir, unsigned long attrs);
47-
void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
48-
size_t size, enum dma_data_direction dir, unsigned long attrs);
4945
struct sg_table *iommu_dma_alloc_noncontiguous(struct device *dev, size_t size,
5046
enum dma_data_direction dir, gfp_t gfp, unsigned long attrs);
5147
void iommu_dma_free_noncontiguous(struct device *dev, size_t size,

include/trace/events/dma.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ DEFINE_EVENT(dma_map, name, \
7373
TP_ARGS(dev, phys_addr, dma_addr, size, dir, attrs))
7474

7575
DEFINE_MAP_EVENT(dma_map_phys);
76-
DEFINE_MAP_EVENT(dma_map_resource);
7776

7877
DECLARE_EVENT_CLASS(dma_unmap,
7978
TP_PROTO(struct device *dev, dma_addr_t addr, size_t size,
@@ -111,7 +110,6 @@ DEFINE_EVENT(dma_unmap, name, \
111110
TP_ARGS(dev, addr, size, dir, attrs))
112111

113112
DEFINE_UNMAP_EVENT(dma_unmap_phys);
114-
DEFINE_UNMAP_EVENT(dma_unmap_resource);
115113

116114
DECLARE_EVENT_CLASS(dma_alloc_class,
117115
TP_PROTO(struct device *dev, void *virt_addr, dma_addr_t dma_addr,

kernel/dma/debug.c

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ enum {
3838
dma_debug_single,
3939
dma_debug_sg,
4040
dma_debug_coherent,
41-
dma_debug_resource,
4241
dma_debug_noncoherent,
4342
dma_debug_phy,
4443
};
@@ -142,7 +141,6 @@ static const char *type2name[] = {
142141
[dma_debug_single] = "single",
143142
[dma_debug_sg] = "scatter-gather",
144143
[dma_debug_coherent] = "coherent",
145-
[dma_debug_resource] = "resource",
146144
[dma_debug_noncoherent] = "noncoherent",
147145
[dma_debug_phy] = "phy",
148146
};
@@ -1446,47 +1444,6 @@ void debug_dma_free_coherent(struct device *dev, size_t size,
14461444
check_unmap(&ref);
14471445
}
14481446

1449-
void debug_dma_map_resource(struct device *dev, phys_addr_t addr, size_t size,
1450-
int direction, dma_addr_t dma_addr,
1451-
unsigned long attrs)
1452-
{
1453-
struct dma_debug_entry *entry;
1454-
1455-
if (unlikely(dma_debug_disabled()))
1456-
return;
1457-
1458-
entry = dma_entry_alloc();
1459-
if (!entry)
1460-
return;
1461-
1462-
entry->type = dma_debug_resource;
1463-
entry->dev = dev;
1464-
entry->paddr = addr;
1465-
entry->size = size;
1466-
entry->dev_addr = dma_addr;
1467-
entry->direction = direction;
1468-
entry->map_err_type = MAP_ERR_NOT_CHECKED;
1469-
1470-
add_dma_entry(entry, attrs);
1471-
}
1472-
1473-
void debug_dma_unmap_resource(struct device *dev, dma_addr_t dma_addr,
1474-
size_t size, int direction)
1475-
{
1476-
struct dma_debug_entry ref = {
1477-
.type = dma_debug_resource,
1478-
.dev = dev,
1479-
.dev_addr = dma_addr,
1480-
.size = size,
1481-
.direction = direction,
1482-
};
1483-
1484-
if (unlikely(dma_debug_disabled()))
1485-
return;
1486-
1487-
check_unmap(&ref);
1488-
}
1489-
14901447
void debug_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
14911448
size_t size, int direction)
14921449
{

kernel/dma/debug.h

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,6 @@ extern void debug_dma_alloc_coherent(struct device *dev, size_t size,
3030
extern void debug_dma_free_coherent(struct device *dev, size_t size,
3131
void *virt, dma_addr_t addr);
3232

33-
extern void debug_dma_map_resource(struct device *dev, phys_addr_t addr,
34-
size_t size, int direction,
35-
dma_addr_t dma_addr,
36-
unsigned long attrs);
37-
38-
extern void debug_dma_unmap_resource(struct device *dev, dma_addr_t dma_addr,
39-
size_t size, int direction);
40-
4133
extern void debug_dma_sync_single_for_cpu(struct device *dev,
4234
dma_addr_t dma_handle, size_t size,
4335
int direction);
@@ -95,19 +87,6 @@ static inline void debug_dma_free_coherent(struct device *dev, size_t size,
9587
{
9688
}
9789

98-
static inline void debug_dma_map_resource(struct device *dev, phys_addr_t addr,
99-
size_t size, int direction,
100-
dma_addr_t dma_addr,
101-
unsigned long attrs)
102-
{
103-
}
104-
105-
static inline void debug_dma_unmap_resource(struct device *dev,
106-
dma_addr_t dma_addr, size_t size,
107-
int direction)
108-
{
109-
}
110-
11190
static inline void debug_dma_sync_single_for_cpu(struct device *dev,
11291
dma_addr_t dma_handle,
11392
size_t size, int direction)

kernel/dma/direct.c

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -497,22 +497,6 @@ int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl, int nents,
497497
return ret;
498498
}
499499

500-
dma_addr_t dma_direct_map_resource(struct device *dev, phys_addr_t paddr,
501-
size_t size, enum dma_data_direction dir, unsigned long attrs)
502-
{
503-
dma_addr_t dma_addr = paddr;
504-
505-
if (unlikely(!dma_capable(dev, dma_addr, size, false))) {
506-
dev_err_once(dev,
507-
"DMA addr %pad+%zu overflow (mask %llx, bus limit %llx).\n",
508-
&dma_addr, size, *dev->dma_mask, dev->bus_dma_limit);
509-
WARN_ON_ONCE(1);
510-
return DMA_MAPPING_ERROR;
511-
}
512-
513-
return dma_addr;
514-
}
515-
516500
int dma_direct_get_sgtable(struct device *dev, struct sg_table *sgt,
517501
void *cpu_addr, dma_addr_t dma_addr, size_t size,
518502
unsigned long attrs)

kernel/dma/mapping.c

Lines changed: 37 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -152,12 +152,10 @@ static inline bool dma_map_direct(struct device *dev,
152152
return dma_go_direct(dev, *dev->dma_mask, ops);
153153
}
154154

155-
dma_addr_t dma_map_page_attrs(struct device *dev, struct page *page,
156-
size_t offset, size_t size, enum dma_data_direction dir,
157-
unsigned long attrs)
155+
dma_addr_t dma_map_phys(struct device *dev, phys_addr_t phys, size_t size,
156+
enum dma_data_direction dir, unsigned long attrs)
158157
{
159158
const struct dma_map_ops *ops = get_dma_ops(dev);
160-
phys_addr_t phys = page_to_phys(page) + offset;
161159
bool is_mmio = attrs & DMA_ATTR_MMIO;
162160
dma_addr_t addr;
163161

@@ -177,6 +175,9 @@ dma_addr_t dma_map_page_attrs(struct device *dev, struct page *page,
177175

178176
addr = ops->map_resource(dev, phys, size, dir, attrs);
179177
} else {
178+
struct page *page = phys_to_page(phys);
179+
size_t offset = offset_in_page(phys);
180+
180181
/*
181182
* The dma_ops API contract for ops->map_page() requires
182183
* kmappable memory, while ops->map_resource() does not.
@@ -191,9 +192,26 @@ dma_addr_t dma_map_page_attrs(struct device *dev, struct page *page,
191192

192193
return addr;
193194
}
195+
EXPORT_SYMBOL_GPL(dma_map_phys);
196+
197+
dma_addr_t dma_map_page_attrs(struct device *dev, struct page *page,
198+
size_t offset, size_t size, enum dma_data_direction dir,
199+
unsigned long attrs)
200+
{
201+
phys_addr_t phys = page_to_phys(page) + offset;
202+
203+
if (unlikely(attrs & DMA_ATTR_MMIO))
204+
return DMA_MAPPING_ERROR;
205+
206+
if (IS_ENABLED(CONFIG_DMA_API_DEBUG) &&
207+
WARN_ON_ONCE(is_zone_device_page(page)))
208+
return DMA_MAPPING_ERROR;
209+
210+
return dma_map_phys(dev, phys, size, dir, attrs);
211+
}
194212
EXPORT_SYMBOL(dma_map_page_attrs);
195213

196-
void dma_unmap_page_attrs(struct device *dev, dma_addr_t addr, size_t size,
214+
void dma_unmap_phys(struct device *dev, dma_addr_t addr, size_t size,
197215
enum dma_data_direction dir, unsigned long attrs)
198216
{
199217
const struct dma_map_ops *ops = get_dma_ops(dev);
@@ -213,6 +231,16 @@ void dma_unmap_page_attrs(struct device *dev, dma_addr_t addr, size_t size,
213231
trace_dma_unmap_phys(dev, addr, size, dir, attrs);
214232
debug_dma_unmap_phys(dev, addr, size, dir);
215233
}
234+
EXPORT_SYMBOL_GPL(dma_unmap_phys);
235+
236+
void dma_unmap_page_attrs(struct device *dev, dma_addr_t addr, size_t size,
237+
enum dma_data_direction dir, unsigned long attrs)
238+
{
239+
if (unlikely(attrs & DMA_ATTR_MMIO))
240+
return;
241+
242+
dma_unmap_phys(dev, addr, size, dir, attrs);
243+
}
216244
EXPORT_SYMBOL(dma_unmap_page_attrs);
217245

218246
static int __dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
@@ -338,41 +366,18 @@ EXPORT_SYMBOL(dma_unmap_sg_attrs);
338366
dma_addr_t dma_map_resource(struct device *dev, phys_addr_t phys_addr,
339367
size_t size, enum dma_data_direction dir, unsigned long attrs)
340368
{
341-
const struct dma_map_ops *ops = get_dma_ops(dev);
342-
dma_addr_t addr = DMA_MAPPING_ERROR;
343-
344-
BUG_ON(!valid_dma_direction(dir));
345-
346-
if (WARN_ON_ONCE(!dev->dma_mask))
369+
if (IS_ENABLED(CONFIG_DMA_API_DEBUG) &&
370+
WARN_ON_ONCE(pfn_valid(PHYS_PFN(phys_addr))))
347371
return DMA_MAPPING_ERROR;
348372

349-
if (dma_map_direct(dev, ops))
350-
addr = dma_direct_map_resource(dev, phys_addr, size, dir, attrs);
351-
else if (use_dma_iommu(dev))
352-
addr = iommu_dma_map_resource(dev, phys_addr, size, dir, attrs);
353-
else if (ops->map_resource)
354-
addr = ops->map_resource(dev, phys_addr, size, dir, attrs);
355-
356-
trace_dma_map_resource(dev, phys_addr, addr, size, dir, attrs);
357-
debug_dma_map_resource(dev, phys_addr, size, dir, addr, attrs);
358-
return addr;
373+
return dma_map_phys(dev, phys_addr, size, dir, attrs | DMA_ATTR_MMIO);
359374
}
360375
EXPORT_SYMBOL(dma_map_resource);
361376

362377
void dma_unmap_resource(struct device *dev, dma_addr_t addr, size_t size,
363378
enum dma_data_direction dir, unsigned long attrs)
364379
{
365-
const struct dma_map_ops *ops = get_dma_ops(dev);
366-
367-
BUG_ON(!valid_dma_direction(dir));
368-
if (dma_map_direct(dev, ops))
369-
; /* nothing to do: uncached and no swiotlb */
370-
else if (use_dma_iommu(dev))
371-
iommu_dma_unmap_resource(dev, addr, size, dir, attrs);
372-
else if (ops->unmap_resource)
373-
ops->unmap_resource(dev, addr, size, dir, attrs);
374-
trace_dma_unmap_resource(dev, addr, size, dir, attrs);
375-
debug_dma_unmap_resource(dev, addr, size, dir);
380+
dma_unmap_phys(dev, addr, size, dir, attrs | DMA_ATTR_MMIO);
376381
}
377382
EXPORT_SYMBOL(dma_unmap_resource);
378383

0 commit comments

Comments
 (0)