Commit de7cf917 authored by Christoph Hellwig's avatar Christoph Hellwig
Browse files

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: default avatarChristoph Hellwig <hch@lst.de>
parent efa70f2f
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -74,6 +74,11 @@ struct dma_map_ops {
			gfp_t gfp);
	void (*free_pages)(struct device *dev, size_t size, struct page *vaddr,
			dma_addr_t dma_handle, enum dma_data_direction dir);
	void* (*alloc_noncoherent)(struct device *dev, size_t size,
			dma_addr_t *dma_handle, enum dma_data_direction dir,
			gfp_t gfp);
	void (*free_noncoherent)(struct device *dev, size_t size, void *vaddr,
			dma_addr_t dma_handle, enum dma_data_direction dir);
	int (*mmap)(struct device *, struct vm_area_struct *,
			  void *, dma_addr_t, size_t,
			  unsigned long attrs);
+27 −6
Original line number Diff line number Diff line
@@ -513,6 +513,10 @@ EXPORT_SYMBOL_GPL(dma_free_pages);
void *dma_alloc_noncoherent(struct device *dev, size_t size,
		dma_addr_t *dma_handle, enum dma_data_direction dir, gfp_t gfp)
{
	const struct dma_map_ops *ops = get_dma_ops(dev);
	void *vaddr;

	if (!ops || !ops->alloc_noncoherent) {
		struct page *page;

		page = dma_alloc_pages(dev, size, dma_handle, dir, gfp);
@@ -520,12 +524,29 @@ void *dma_alloc_noncoherent(struct device *dev, size_t size,
			return NULL;
		return page_address(page);
	}

	size = PAGE_ALIGN(size);
	vaddr = ops->alloc_noncoherent(dev, size, dma_handle, dir, gfp);
	if (vaddr)
		debug_dma_map_page(dev, virt_to_page(vaddr), 0, size, dir,
				   *dma_handle);
	return vaddr;
}
EXPORT_SYMBOL_GPL(dma_alloc_noncoherent);

void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr,
		dma_addr_t dma_handle, enum dma_data_direction dir)
{
	const struct dma_map_ops *ops = get_dma_ops(dev);

	if (!ops || !ops->free_noncoherent) {
		dma_free_pages(dev, size, virt_to_page(vaddr), dma_handle, dir);
		return;
	}

	size = PAGE_ALIGN(size);
	debug_dma_unmap_page(dev, dma_handle, size, dir);
	ops->free_noncoherent(dev, size, vaddr, dma_handle, dir);
}
EXPORT_SYMBOL_GPL(dma_free_noncoherent);