[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: Christoph Hellwig <hch@lst.de> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
parent
318facbee0
commit
8eb6c6e3b9
4 changed files with 13 additions and 9 deletions
|
@ -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,
|
||||||
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,8 +572,8 @@ 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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
|
|
Loading…
Add table
Reference in a new issue