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

[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
...@@ -536,11 +536,12 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle, ...@@ -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. * to the dma address (mapping) of the first page.
*/ */
void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, 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; void *ret = NULL;
dma_addr_t mapping; dma_addr_t mapping;
unsigned int npages, order; unsigned int npages, order;
struct page *page;
size = PAGE_ALIGN(size); size = PAGE_ALIGN(size);
npages = size >> PAGE_SHIFT; npages = size >> PAGE_SHIFT;
...@@ -560,9 +561,10 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, ...@@ -560,9 +561,10 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
return NULL; return NULL;
/* Alloc enough pages (and possibly more) */ /* Alloc enough pages (and possibly more) */
ret = (void *)__get_free_pages(flag, order); page = alloc_pages_node(flag, order, node);
if (!ret) if (!page)
return NULL; return NULL;
ret = page_address(page);
memset(ret, 0, size); memset(ret, 0, size);
/* Set up tces to cover the allocated range */ /* Set up tces to cover the allocated range */
...@@ -570,9 +572,9 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, ...@@ -570,9 +572,9 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
mask >> PAGE_SHIFT, order); mask >> PAGE_SHIFT, order);
if (mapping == DMA_ERROR_CODE) { if (mapping == DMA_ERROR_CODE) {
free_pages((unsigned long)ret, order); free_pages((unsigned long)ret, order);
ret = NULL; return NULL;
} else }
*dma_handle = mapping; *dma_handle = mapping;
return ret; return ret;
} }
......
...@@ -86,7 +86,8 @@ static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size, ...@@ -86,7 +86,8 @@ static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flag) dma_addr_t *dma_handle, gfp_t flag)
{ {
return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle, 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, static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
......
...@@ -394,7 +394,7 @@ static void *vio_alloc_coherent(struct device *dev, size_t size, ...@@ -394,7 +394,7 @@ static void *vio_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag) dma_addr_t *dma_handle, gfp_t flag)
{ {
return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size, 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, static void vio_free_coherent(struct device *dev, size_t size,
......
...@@ -76,7 +76,8 @@ extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, ...@@ -76,7 +76,8 @@ extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
int nelems, enum dma_data_direction direction); int nelems, enum dma_data_direction direction);
extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, 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, extern void iommu_free_coherent(struct iommu_table *tbl, size_t size,
void *vaddr, dma_addr_t dma_handle); void *vaddr, dma_addr_t dma_handle);
extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment