Skip to content

Commit de7cf91

Browse files
author
Christoph Hellwig
committed
dma-mapping: add new {alloc,free}_noncoherent dma_map_ops methods
This will allow IOMMU drivers to allocate non-contigous memory and return a vmapped virtual address. Signed-off-by: Christoph Hellwig <hch@lst.de>
1 parent efa70f2 commit de7cf91

2 files changed

Lines changed: 32 additions & 6 deletions

File tree

include/linux/dma-mapping.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ struct dma_map_ops {
7474
gfp_t gfp);
7575
void (*free_pages)(struct device *dev, size_t size, struct page *vaddr,
7676
dma_addr_t dma_handle, enum dma_data_direction dir);
77+
void* (*alloc_noncoherent)(struct device *dev, size_t size,
78+
dma_addr_t *dma_handle, enum dma_data_direction dir,
79+
gfp_t gfp);
80+
void (*free_noncoherent)(struct device *dev, size_t size, void *vaddr,
81+
dma_addr_t dma_handle, enum dma_data_direction dir);
7782
int (*mmap)(struct device *, struct vm_area_struct *,
7883
void *, dma_addr_t, size_t,
7984
unsigned long attrs);

kernel/dma/mapping.c

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -513,19 +513,40 @@ EXPORT_SYMBOL_GPL(dma_free_pages);
513513
void *dma_alloc_noncoherent(struct device *dev, size_t size,
514514
dma_addr_t *dma_handle, enum dma_data_direction dir, gfp_t gfp)
515515
{
516-
struct page *page;
516+
const struct dma_map_ops *ops = get_dma_ops(dev);
517+
void *vaddr;
517518

518-
page = dma_alloc_pages(dev, size, dma_handle, dir, gfp);
519-
if (!page)
520-
return NULL;
521-
return page_address(page);
519+
if (!ops || !ops->alloc_noncoherent) {
520+
struct page *page;
521+
522+
page = dma_alloc_pages(dev, size, dma_handle, dir, gfp);
523+
if (!page)
524+
return NULL;
525+
return page_address(page);
526+
}
527+
528+
size = PAGE_ALIGN(size);
529+
vaddr = ops->alloc_noncoherent(dev, size, dma_handle, dir, gfp);
530+
if (vaddr)
531+
debug_dma_map_page(dev, virt_to_page(vaddr), 0, size, dir,
532+
*dma_handle);
533+
return vaddr;
522534
}
523535
EXPORT_SYMBOL_GPL(dma_alloc_noncoherent);
524536

525537
void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
526538
dma_addr_t dma_handle, enum dma_data_direction dir)
527539
{
528-
dma_free_pages(dev, size, virt_to_page(vaddr), dma_handle, dir);
540+
const struct dma_map_ops *ops = get_dma_ops(dev);
541+
542+
if (!ops || !ops->free_noncoherent) {
543+
dma_free_pages(dev, size, virt_to_page(vaddr), dma_handle, dir);
544+
return;
545+
}
546+
547+
size = PAGE_ALIGN(size);
548+
debug_dma_unmap_page(dev, dma_handle, size, dir);
549+
ops->free_noncoherent(dev, size, vaddr, dma_handle, dir);
529550
}
530551
EXPORT_SYMBOL_GPL(dma_free_noncoherent);
531552

0 commit comments

Comments
 (0)