summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/iommu.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-04-24 08:37:29 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-24 08:37:29 -0700
commite270b51df657011983241ec61a1fc7de186e16cd (patch)
tree3397be4cbf31676ca6ebb187903e8cfc2218f223 /arch/sparc64/kernel/iommu.c
parent8fa82790fb9dfe57aeafc8de6b6a5c1df63efa06 (diff)
parent227739bf4c110bbd02d0c0f13b272c32de406e4c (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6: (23 commits) sparc: sunzilog uart order [SPARC64]: Detect trap frames in stack backtraces. [SPARC64]: %l6 trap return handling no longer necessary. [SPARC64]: Use trap type stored in pt_regs to handle syscall restart. [SPARC64]: Store magic cookie and trap type in pt_regs. [SPARC64]: PROM debug console can be CON_ANYTIME. sparc64: cleanup after SunOS/Solaris binary emulation removal sparc: cleanup after SunOS binary emulation removal [SPARC64]: Add NUMA support. [SPARC64]: Allocate TSB node-local. [SPARC64]: NUMA device infrastructure. [SPARC64]: Kill pci_iommu_table_init() declaration. [SPARC64]: Once we have the boot cmdline, call parse_early_param() [SPARC64]: Remove unused asm-sparc64/numnodes.h [SPARC64]: Decrease SECTION_SIZE_BITS to 30. [SPARC64]: Initialize MDESC earlier and use lmb_alloc() [SPARC64]: Use lmb_alloc() for PROM device tree. [SPARC64]: Call real_setup_per_cpu_areas() earlier and use lmb_alloc(). [SPARC64]: Fully use LMB information in bootmem_init(). [SPARC64]: Start using LMB information in bootmem_init(). ...
Diffstat (limited to 'arch/sparc64/kernel/iommu.c')
-rw-r--r--arch/sparc64/kernel/iommu.c33
1 files changed, 21 insertions, 12 deletions
diff --git a/arch/sparc64/kernel/iommu.c b/arch/sparc64/kernel/iommu.c
index 756fa24eeef..2a37a6ca2a1 100644
--- a/arch/sparc64/kernel/iommu.c
+++ b/arch/sparc64/kernel/iommu.c
@@ -173,9 +173,11 @@ void iommu_range_free(struct iommu *iommu, dma_addr_t dma_addr, unsigned long np
}
int iommu_table_init(struct iommu *iommu, int tsbsize,
- u32 dma_offset, u32 dma_addr_mask)
+ u32 dma_offset, u32 dma_addr_mask,
+ int numa_node)
{
- unsigned long i, tsbbase, order, sz, num_tsb_entries;
+ unsigned long i, order, sz, num_tsb_entries;
+ struct page *page;
num_tsb_entries = tsbsize / sizeof(iopte_t);
@@ -188,11 +190,12 @@ int iommu_table_init(struct iommu *iommu, int tsbsize,
/* Allocate and initialize the free area map. */
sz = num_tsb_entries / 8;
sz = (sz + 7UL) & ~7UL;
- iommu->arena.map = kzalloc(sz, GFP_KERNEL);
+ iommu->arena.map = kmalloc_node(sz, GFP_KERNEL, numa_node);
if (!iommu->arena.map) {
printk(KERN_ERR "IOMMU: Error, kmalloc(arena.map) failed.\n");
return -ENOMEM;
}
+ memset(iommu->arena.map, 0, sz);
iommu->arena.limit = num_tsb_entries;
if (tlb_type != hypervisor)
@@ -201,21 +204,23 @@ int iommu_table_init(struct iommu *iommu, int tsbsize,
/* Allocate and initialize the dummy page which we
* set inactive IO PTEs to point to.
*/
- iommu->dummy_page = get_zeroed_page(GFP_KERNEL);
- if (!iommu->dummy_page) {
+ page = alloc_pages_node(numa_node, GFP_KERNEL, 0);
+ if (!page) {
printk(KERN_ERR "IOMMU: Error, gfp(dummy_page) failed.\n");
goto out_free_map;
}
+ iommu->dummy_page = (unsigned long) page_address(page);
+ memset((void *)iommu->dummy_page, 0, PAGE_SIZE);
iommu->dummy_page_pa = (unsigned long) __pa(iommu->dummy_page);
/* Now allocate and setup the IOMMU page table itself. */
order = get_order(tsbsize);
- tsbbase = __get_free_pages(GFP_KERNEL, order);
- if (!tsbbase) {
+ page = alloc_pages_node(numa_node, GFP_KERNEL, order);
+ if (!page) {
printk(KERN_ERR "IOMMU: Error, gfp(tsb) failed.\n");
goto out_free_dummy_page;
}
- iommu->page_table = (iopte_t *)tsbbase;
+ iommu->page_table = (iopte_t *)page_address(page);
for (i = 0; i < num_tsb_entries; i++)
iopte_make_dummy(iommu, &iommu->page_table[i]);
@@ -276,20 +281,24 @@ static inline void iommu_free_ctx(struct iommu *iommu, int ctx)
static void *dma_4u_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_addrp, gfp_t gfp)
{
+ unsigned long flags, order, first_page;
struct iommu *iommu;
+ struct page *page;
+ int npages, nid;
iopte_t *iopte;
- unsigned long flags, order, first_page;
void *ret;
- int npages;
size = IO_PAGE_ALIGN(size);
order = get_order(size);
if (order >= 10)
return NULL;
- first_page = __get_free_pages(gfp, order);
- if (first_page == 0UL)
+ nid = dev->archdata.numa_node;
+ page = alloc_pages_node(nid, gfp, order);
+ if (unlikely(!page))
return NULL;
+
+ first_page = (unsigned long) page_address(page);
memset((char *)first_page, 0, PAGE_SIZE << order);
iommu = dev->archdata.iommu;