Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8eb6c6e3 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Paul Mackerras
Browse files

[PATCH] powerpc: node-aware dma allocations



Make sure dma_alloc_coherent allocates memory from the local node.  This
is important on Cell where we avoid going through the slow cpu
interconnect.

Note:  I could only test this patch on Cell, it should be verified on
some pseries machine by those that have the hardware.

Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 318facbe
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -536,11 +536,12 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
 * to the dma address (mapping) of the first page.
 */
void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
		dma_addr_t *dma_handle, unsigned long mask, gfp_t flag)
		dma_addr_t *dma_handle, unsigned long mask, gfp_t flag, int node)
{
	void *ret = NULL;
	dma_addr_t mapping;
	unsigned int npages, order;
	struct page *page;

	size = PAGE_ALIGN(size);
	npages = size >> PAGE_SHIFT;
@@ -560,9 +561,10 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
		return NULL;

	/* Alloc enough pages (and possibly more) */
	ret = (void *)__get_free_pages(flag, order);
	if (!ret)
	page = alloc_pages_node(flag, order, node);
	if (!page)
		return NULL;
	ret = page_address(page);
	memset(ret, 0, size);

	/* Set up tces to cover the allocated range */
@@ -570,8 +572,8 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
			      mask >> PAGE_SHIFT, order);
	if (mapping == DMA_ERROR_CODE) {
		free_pages((unsigned long)ret, order);
		ret = NULL;
	} else
		return NULL;
	}
	*dma_handle = mapping;
	return ret;
}
+2 −1
Original line number Diff line number Diff line
@@ -86,7 +86,8 @@ static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
			   dma_addr_t *dma_handle, gfp_t flag)
{
	return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle,
			device_to_mask(hwdev), flag);
			device_to_mask(hwdev), flag,
			pcibus_to_node(to_pci_dev(hwdev)->bus));
}

static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
+1 −1
Original line number Diff line number Diff line
@@ -394,7 +394,7 @@ static void *vio_alloc_coherent(struct device *dev, size_t size,
			   dma_addr_t *dma_handle, gfp_t flag)
{
	return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
			dma_handle, ~0ul, flag);
			dma_handle, ~0ul, flag, -1);
}

static void vio_free_coherent(struct device *dev, size_t size,
+2 −1
Original line number Diff line number Diff line
@@ -76,7 +76,8 @@ extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
		int nelems, enum dma_data_direction direction);

extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
		dma_addr_t *dma_handle, unsigned long mask, gfp_t flag);
		dma_addr_t *dma_handle, unsigned long mask,
		gfp_t flag, int node);
extern void iommu_free_coherent(struct iommu_table *tbl, size_t size,
		void *vaddr, dma_addr_t dma_handle);
extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,