aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2006-06-06 10:11:35 -0400
committerPaul Mackerras <paulus@samba.org>2006-06-09 07:24:01 -0400
commit8eb6c6e3b9c8bfed3d75536ab142d7694627c2e5 (patch)
tree7dd9c4146f60e88ca1fc8ebe976e1b7a3ae6ea2c
parent318facbee05417fb432603a8309a10cdb942a87b (diff)
[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>
-rw-r--r--arch/powerpc/kernel/iommu.c14
-rw-r--r--arch/powerpc/kernel/pci_iommu.c3
-rw-r--r--arch/powerpc/kernel/vio.c2
-rw-r--r--include/asm-powerpc/iommu.h3
4 files changed, 13 insertions, 9 deletions
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index 4eba60a32890..cbb794556d02 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -536,11 +536,12 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle,
536 * to the dma address (mapping) of the first page. 536 * to the dma address (mapping) of the first page.
537 */ 537 */
538void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, 538void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
539 dma_addr_t *dma_handle, unsigned long mask, gfp_t flag) 539 dma_addr_t *dma_handle, unsigned long mask, gfp_t flag, int node)
540{ 540{
541 void *ret = NULL; 541 void *ret = NULL;
542 dma_addr_t mapping; 542 dma_addr_t mapping;
543 unsigned int npages, order; 543 unsigned int npages, order;
544 struct page *page;
544 545
545 size = PAGE_ALIGN(size); 546 size = PAGE_ALIGN(size);
546 npages = size >> PAGE_SHIFT; 547 npages = size >> PAGE_SHIFT;
@@ -560,9 +561,10 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
560 return NULL; 561 return NULL;
561 562
562 /* Alloc enough pages (and possibly more) */ 563 /* Alloc enough pages (and possibly more) */
563 ret = (void *)__get_free_pages(flag, order); 564 page = alloc_pages_node(flag, order, node);
564 if (!ret) 565 if (!page)
565 return NULL; 566 return NULL;
567 ret = page_address(page);
566 memset(ret, 0, size); 568 memset(ret, 0, size);
567 569
568 /* Set up tces to cover the allocated range */ 570 /* Set up tces to cover the allocated range */
@@ -570,9 +572,9 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
570 mask >> PAGE_SHIFT, order); 572 mask >> PAGE_SHIFT, order);
571 if (mapping == DMA_ERROR_CODE) { 573 if (mapping == DMA_ERROR_CODE) {
572 free_pages((unsigned long)ret, order); 574 free_pages((unsigned long)ret, order);
573 ret = NULL; 575 return NULL;
574 } else 576 }
575 *dma_handle = mapping; 577 *dma_handle = mapping;
576 return ret; 578 return ret;
577} 579}
578 580
diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c
index 48aa82d01624..7fb4cca021be 100644
--- a/arch/powerpc/kernel/pci_iommu.c
+++ b/arch/powerpc/kernel/pci_iommu.c
@@ -86,7 +86,8 @@ static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size,
86 dma_addr_t *dma_handle, gfp_t flag) 86 dma_addr_t *dma_handle, gfp_t flag)
87{ 87{
88 return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle, 88 return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle,
89 device_to_mask(hwdev), flag); 89 device_to_mask(hwdev), flag,
90 pcibus_to_node(to_pci_dev(hwdev)->bus));
90} 91}
91 92
92static void pci_iommu_free_coherent(struct device *hwdev, size_t size, 93static void pci_iommu_free_coherent(struct device *hwdev, size_t size,
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index fe92727aca30..e746686d48b8 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -394,7 +394,7 @@ static void *vio_alloc_coherent(struct device *dev, size_t size,
394 dma_addr_t *dma_handle, gfp_t flag) 394 dma_addr_t *dma_handle, gfp_t flag)
395{ 395{
396 return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size, 396 return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size,
397 dma_handle, ~0ul, flag); 397 dma_handle, ~0ul, flag, -1);
398} 398}
399 399
400static void vio_free_coherent(struct device *dev, size_t size, 400static void vio_free_coherent(struct device *dev, size_t size,
diff --git a/include/asm-powerpc/iommu.h b/include/asm-powerpc/iommu.h
index 18ca29e9105a..9065f6c972a4 100644
--- a/include/asm-powerpc/iommu.h
+++ b/include/asm-powerpc/iommu.h
@@ -76,7 +76,8 @@ extern void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
76 int nelems, enum dma_data_direction direction); 76 int nelems, enum dma_data_direction direction);
77 77
78extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, 78extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size,
79 dma_addr_t *dma_handle, unsigned long mask, gfp_t flag); 79 dma_addr_t *dma_handle, unsigned long mask,
80 gfp_t flag, int node);
80extern void iommu_free_coherent(struct iommu_table *tbl, size_t size, 81extern void iommu_free_coherent(struct iommu_table *tbl, size_t size,
81 void *vaddr, dma_addr_t dma_handle); 82 void *vaddr, dma_addr_t dma_handle);
82extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, 83extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr,