Module Name: src Committed By: matt Date: Wed Jul 18 18:51:59 UTC 2012
Modified Files: src/sys/arch/powerpc/booke: booke_machdep.c Log Message: If allocating lots of VA space for an io device, try to 'reserve' the space so that the TLB might be able to create a large TLB entry to map it all. To generate a diff of this commit: cvs rdiff -u -r1.14 -r1.15 src/sys/arch/powerpc/booke/booke_machdep.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/powerpc/booke/booke_machdep.c diff -u src/sys/arch/powerpc/booke/booke_machdep.c:1.14 src/sys/arch/powerpc/booke/booke_machdep.c:1.15 --- src/sys/arch/powerpc/booke/booke_machdep.c:1.14 Thu Jun 30 00:52:58 2011 +++ src/sys/arch/powerpc/booke/booke_machdep.c Wed Jul 18 18:51:59 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: booke_machdep.c,v 1.14 2011/06/30 00:52:58 matt Exp $ */ +/* $NetBSD: booke_machdep.c,v 1.15 2012/07/18 18:51:59 matt Exp $ */ /*- * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc. * All rights reserved. @@ -38,7 +38,7 @@ #define _POWERPC_BUS_DMA_PRIVATE #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: booke_machdep.c,v 1.14 2011/06/30 00:52:58 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: booke_machdep.c,v 1.15 2012/07/18 18:51:59 matt Exp $"); #include "opt_modular.h" @@ -329,13 +329,45 @@ mapiodev(paddr_t pa, psize_t len, bool p panic("mapiodev: no TLB entry reserved for %llx+%llx", (long long)pa, (long long)len); + const paddr_t orig_pa = pa; + const psize_t orig_len = len; + vsize_t align = 0; pa = trunc_page(pa); len = round_page(off + len); - vaddr_t va = uvm_km_alloc(kernel_map, len, 0, UVM_KMF_VAONLY); + /* + * If we are allocating a large amount (>= 1MB) try to get an + * aligned VA region for it so try to do a large mapping for it. + */ + if ((len & (len - 1)) == 0 && len >= 0x100000) + align = len; + + vaddr_t va = uvm_km_alloc(kernel_map, len, align, UVM_KMF_VAONLY); + if (va == 0 && align > 0) { + /* + * Large aligned request failed. Let's just get anything. + */ + align = 0; + va = uvm_km_alloc(kernel_map, len, align, UVM_KMF_VAONLY); + } if (va == 0) return NULL; + if (align) { + /* + * Now try to map that via one big TLB entry. + */ + pt_entry_t pte = pte_make_kenter_pa(pa, NULL, + VM_PROT_READ|VM_PROT_WRITE, + prefetchable ? 0 : PMAP_NOCACHE); + if (!tlb_ioreserve(va, len, pte)) { + void * const p0 = tlb_mapiodev(orig_pa, orig_len, + prefetchable); + KASSERT(p0 != NULL); + return p0; + } + } + for (va += len, pa += len; len > 0; len -= PAGE_SIZE) { va -= PAGE_SIZE; pa -= PAGE_SIZE;