diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2007-12-19 21:51:30 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2007-12-19 21:51:30 +0000 |
commit | aa8faebc6ff9cd54054ba36125aeddf8fdf61692 (patch) | |
tree | ca3058dc4bff30f798e6c1164b9a9292023a88aa /sys/arch/aviion/dev | |
parent | 4cdfd5155109e087574b3d4d13323efcdce6d3ac (diff) |
Allocate memory for the onboard le interface using uvm functions, instead of
stealing pages in pmap_bootstrap. While there, use up to four times more
memory for these buffers if the machine has enough physical memory.
Diffstat (limited to 'sys/arch/aviion/dev')
-rw-r--r-- | sys/arch/aviion/dev/if_le_syscon.c | 80 |
1 files changed, 63 insertions, 17 deletions
diff --git a/sys/arch/aviion/dev/if_le_syscon.c b/sys/arch/aviion/dev/if_le_syscon.c index 404dff6ff90..e49f34bc1fe 100644 --- a/sys/arch/aviion/dev/if_le_syscon.c +++ b/sys/arch/aviion/dev/if_le_syscon.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_le_syscon.c,v 1.2 2006/05/21 12:22:02 miod Exp $ */ +/* $OpenBSD: if_le_syscon.c,v 1.3 2007/12/19 21:51:29 miod Exp $ */ /*- * Copyright (c) 1996 The NetBSD Foundation, Inc. @@ -43,6 +43,8 @@ #include <sys/socket.h> #include <sys/device.h> +#include <uvm/uvm.h> + #include <net/if.h> #ifdef INET @@ -117,35 +119,79 @@ le_syscon_rdcsr(sc, port) int le_syscon_match(parent, cf, aux) - struct device *parent; - void *cf, *aux; + struct device *parent; + void *cf, *aux; { - return (1); + if (avtyp != AV_400) + return (0); + + return (1); } void le_syscon_attach(parent, self, aux) - struct device *parent, *self; - void *aux; + struct device *parent, *self; + void *aux; { struct le_softc *lesc = (struct le_softc *)self; struct am7990_softc *sc = &lesc->sc_am7990; - struct confargs *ca = aux; - extern void *etherbuf; - extern size_t etherlen; + struct confargs *ca = aux; + u_int etherpages; + struct pglist pglist; + vm_page_t pg; + int rc; + paddr_t pa; + vaddr_t va; + + /* + * Allocate contiguous pages in the first 16MB to use as buffers. + */ + if (physmem >= atop(32 * 1024 * 1024)) + etherpages = 64; + else if (physmem >= atop(16 * 1024 * 1024)) + etherpages = 32; + else + etherpages = 16; + for (;;) { + TAILQ_INIT(&pglist); + rc = uvm_pglistalloc(ptoa(etherpages), 0, 1 << 24, + 0, 0, &pglist, 1, 0); + if (rc == 0) + break; + + etherpages >>= 1; + if (etherpages == 2) { + printf(": no available memory, kernel is too large\n"); + return; + } + } - if (etherbuf == NULL) { - printf(": no available memory, kernel is too large\n"); + va = uvm_km_valloc(kernel_map, ptoa(etherpages)); + if (va == NULL) { + printf(": could not map descriptor memory\n"); + uvm_pglistfree(&pglist); return; } - lesc->sc_r1 = (struct av_lereg *)ca->ca_paddr; + pa = VM_PAGE_TO_PHYS(TAILQ_FIRST(&pglist)); + + sc->sc_mem = (void *)va; + sc->sc_addr = (u_long)pa & 0x00ffffff; + sc->sc_memsize = ptoa(etherpages); + + TAILQ_FOREACH(pg, &pglist, pageq) { + pmap_enter(pmap_kernel(), va, pa, + UVM_PROT_RW, UVM_PROT_RW | PMAP_WIRED); + va += PAGE_SIZE; + pa += PAGE_SIZE; + } + pmap_cache_ctrl(pmap_kernel(), (vaddr_t)sc->sc_mem, + (vaddr_t)sc->sc_mem + sc->sc_memsize, CACHE_INH); + pmap_update(pmap_kernel()); + + lesc->sc_r1 = (struct av_lereg *)ca->ca_paddr; - sc->sc_mem = (void *)etherbuf; - etherbuf = NULL; - sc->sc_conf3 = LE_C3_BSWP; - sc->sc_addr = (u_long)sc->sc_mem & 0x00ffffff; - sc->sc_memsize = etherlen; + sc->sc_conf3 = LE_C3_BSWP; myetheraddr(sc->sc_arpcom.ac_enaddr); |