diff options
author | Christoph Hellwig <hch@lst.de> | 2006-06-06 10:11:35 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2006-06-09 07:24:01 -0400 |
commit | 8eb6c6e3b9c8bfed3d75536ab142d7694627c2e5 (patch) | |
tree | 7dd9c4146f60e88ca1fc8ebe976e1b7a3ae6ea2c | |
parent | 318facbee05417fb432603a8309a10cdb942a87b (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.c | 14 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_iommu.c | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/vio.c | 2 | ||||
-rw-r--r-- | include/asm-powerpc/iommu.h | 3 |
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 | */ |
538 | void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, | 538 | void *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 | ||
92 | static void pci_iommu_free_coherent(struct device *hwdev, size_t size, | 93 | static 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 | ||
400 | static void vio_free_coherent(struct device *dev, size_t size, | 400 | static 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 | ||
78 | extern void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, | 78 | extern 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); | ||
80 | extern void iommu_free_coherent(struct iommu_table *tbl, size_t size, | 81 | extern 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); |
82 | extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, | 83 | extern dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, |