diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2006-06-24 13:23:28 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2006-06-24 13:23:28 +0000 |
commit | e9eab0aae49664d0c130f1b60640f862d325d438 (patch) | |
tree | fe7535d02630b5457d712545c4ecaa7ec23bc5e0 | |
parent | 03f621b4ad00ae11a297fdcebfc89315b2320da3 (diff) |
Allocate ethernet buffers as uvm pages, and map them with pmap_enter_cache(),
instead of crossing fingers and expecting malloc() to return aligned and
contiguous memory.
-rw-r--r-- | sys/arch/mac68k/dev/if_mc_obio.c | 106 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/if_mcvar.h | 4 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/if_sn.c | 98 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/if_snvar.h | 18 |
4 files changed, 127 insertions, 99 deletions
diff --git a/sys/arch/mac68k/dev/if_mc_obio.c b/sys/arch/mac68k/dev/if_mc_obio.c index 500bf2bd9d9..dd38e5e2055 100644 --- a/sys/arch/mac68k/dev/if_mc_obio.c +++ b/sys/arch/mac68k/dev/if_mc_obio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_mc_obio.c,v 1.5 2004/12/15 06:48:24 martin Exp $ */ +/* $OpenBSD: if_mc_obio.c,v 1.6 2006/06/24 13:23:27 miod Exp $ */ /* $NetBSD: if_mc_obio.c,v 1.13 2004/03/26 12:15:46 wiz Exp $ */ /*- @@ -38,7 +38,6 @@ #include <sys/param.h> #include <sys/device.h> -#include <sys/malloc.h> #include <sys/socket.h> #include <sys/systm.h> @@ -70,8 +69,6 @@ void mc_reset_rxdma_set(struct mc_softc *, int set); void mc_reset_txdma(struct mc_softc *sc); int mc_obio_getaddr(struct mc_softc *, u_int8_t *); -extern int kvtop(register caddr_t addr); - struct cfattach mc_obio_ca = { sizeof(struct mc_softc), mc_obio_match, mc_obio_attach }; @@ -117,8 +114,10 @@ mc_obio_attach(parent, self, aux) { struct obio_attach_args *oa = (struct obio_attach_args *)aux; struct mc_softc *sc = (void *)self; + struct pglist rxlist, txlist; + vm_page_t pg; + vaddr_t va; u_int8_t myaddr[ETHER_ADDR_LEN]; - int i, noncontig = 0; sc->sc_regt = oa->oa_tag; sc->sc_biucc = XMTSP_64; @@ -134,41 +133,50 @@ mc_obio_attach(parent, self, aux) if (mc_obio_getaddr(sc, myaddr)) { printf(": failed to get MAC address.\n"); - return; + goto out1; } /* allocate memory for transmit buffer and mark it non-cacheable */ - sc->sc_txbuf = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK); - sc->sc_txbuf_phys = kvtop(sc->sc_txbuf); - physaccess (sc->sc_txbuf, (caddr_t)sc->sc_txbuf_phys, PAGE_SIZE, - PG_V | PG_RW | PG_CI); + TAILQ_INIT(&txlist); + if (uvm_pglistalloc(PAGE_SIZE, 0, -PAGE_SIZE, PAGE_SIZE, 0, + &txlist, 1, 0) != 0) { + printf(": could not allocate transmit buffer memory\n"); + goto out1; + } + sc->sc_txbuf = (u_char *)uvm_km_valloc(kernel_map, PAGE_SIZE); + if (sc->sc_txbuf == NULL) { + printf(": could not map transmit buffer memory\n"); + goto out2; + } + pg = TAILQ_FIRST(&txlist); + sc->sc_txbuf_phys = VM_PAGE_TO_PHYS(pg); + pmap_enter_cache(pmap_kernel(), (vaddr_t)sc->sc_txbuf, + sc->sc_txbuf_phys, UVM_PROT_RW, UVM_PROT_RW | PMAP_WIRED, PG_CI); + pmap_update(pmap_kernel()); /* * allocate memory for receive buffer and mark it non-cacheable - * XXX This should use the bus_dma interface, since the buffer - * needs to be physically contiguous. However, it seems that - * at least on my system, malloc() does allocate contiguous - * memory. If it's not, suggest reducing the number of buffers - * to 2, which will fit in one 4K page. */ - sc->sc_rxbuf = malloc(MC_NPAGES * PAGE_SIZE, M_DEVBUF, M_WAITOK); - sc->sc_rxbuf_phys = kvtop(sc->sc_rxbuf); - for (i = 0; i < MC_NPAGES; i++) { - int pa; - - pa = kvtop(sc->sc_rxbuf + PAGE_SIZE*i); - physaccess (sc->sc_rxbuf + PAGE_SIZE*i, (caddr_t)pa, PAGE_SIZE, - PG_V | PG_RW | PG_CI); - if (pa != sc->sc_rxbuf_phys + PAGE_SIZE*i) - noncontig = 1; + TAILQ_INIT(&rxlist); + if (uvm_pglistalloc(MC_NPAGES * PAGE_SIZE, 0, -PAGE_SIZE, PAGE_SIZE, 0, + &rxlist, 1, 0) != 0) { + printf(": could not allocate receive buffer memory\n"); + goto out3; } - - if (noncontig) { - printf("%s: receive DMA buffer not contiguous! " - "Try compiling with \"options MC_RXDMABUFS=2\"\n", - sc->sc_dev.dv_xname); - return; + sc->sc_rxbuf = (u_char *)(va = uvm_km_valloc(kernel_map, + MC_NPAGES * PAGE_SIZE)); + if (sc->sc_rxbuf == NULL) { + printf(": could not map receive buffer memory\n"); + goto out4; + } + pg = TAILQ_FIRST(&rxlist); + sc->sc_rxbuf_phys = VM_PAGE_TO_PHYS(pg); + TAILQ_FOREACH(pg, &rxlist, pageq) { + pmap_enter_cache(pmap_kernel(), va, VM_PAGE_TO_PHYS(pg), + UVM_PROT_RW, UVM_PROT_RW | PMAP_WIRED, PG_CI); + va += PAGE_SIZE; } + pmap_update(pmap_kernel()); sc->sc_bus_init = mc_obio_init; sc->sc_putpacket = mc_obio_put; @@ -202,17 +210,31 @@ mc_obio_attach(parent, self, aux) psc_reg1(PSC_LEV3_IER) = 0x80 | (1 << PSCINTR_ENET); /* mcsetup returns 1 if something fails */ - if (mcsetup(sc, myaddr)) { - /* disable interrupts */ - psc_reg1(PSC_LEV4_IER) = (1 << PSCINTR_ENET_DMA); - psc_reg1(PSC_LEV3_IER) = (1 << PSCINTR_ENET); - /* remove interrupt handlers */ - remove_psc_lev4_intr(PSCINTR_ENET_DMA); - remove_psc_lev3_intr(); - - bus_space_unmap(sc->sc_regt, sc->sc_regh, MC_REGSIZE); - return; - } + if (mcsetup(sc, myaddr) != 0) + goto out5; + + return; + +out5: + /* disable interrupts */ + psc_reg1(PSC_LEV4_IER) = (1 << PSCINTR_ENET_DMA); + psc_reg1(PSC_LEV3_IER) = (1 << PSCINTR_ENET); + /* remove interrupt handlers */ + remove_psc_lev4_intr(PSCINTR_ENET_DMA); + remove_psc_lev3_intr(); + pmap_remove(pmap_kernel(), (vaddr_t)sc->sc_rxbuf, + (vaddr_t)sc->sc_rxbuf + MC_NPAGES * PAGE_SIZE); + pmap_update(pmap_kernel()); +out4: + uvm_pglistfree(&rxlist); +out3: + pmap_remove(pmap_kernel(), (vaddr_t)sc->sc_txbuf, + (vaddr_t)sc->sc_txbuf + PAGE_SIZE); + pmap_update(pmap_kernel()); +out2: + uvm_pglistfree(&txlist); +out1: + bus_space_unmap(sc->sc_regt, sc->sc_regh, MC_REGSIZE); } /* Bus-specific initialization */ diff --git a/sys/arch/mac68k/dev/if_mcvar.h b/sys/arch/mac68k/dev/if_mcvar.h index 876e233f43f..062c8600cee 100644 --- a/sys/arch/mac68k/dev/if_mcvar.h +++ b/sys/arch/mac68k/dev/if_mcvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_mcvar.h,v 1.4 2004/12/15 06:48:24 martin Exp $ */ +/* $OpenBSD: if_mcvar.h,v 1.5 2006/06/24 13:23:27 miod Exp $ */ /* $NetBSD: if_mcvar.h,v 1.8 2004/03/26 12:15:46 wiz Exp $ */ /*- @@ -72,7 +72,7 @@ struct mc_softc { bus_space_handle_t sc_regh; u_char *sc_txbuf, *sc_rxbuf; - int sc_txbuf_phys, sc_rxbuf_phys; + paddr_t sc_txbuf_phys, sc_rxbuf_phys; int sc_tail; int sc_rxset; int sc_txset, sc_txseti; diff --git a/sys/arch/mac68k/dev/if_sn.c b/sys/arch/mac68k/dev/if_sn.c index 5ddf9b36817..275f45fb1a9 100644 --- a/sys/arch/mac68k/dev/if_sn.c +++ b/sys/arch/mac68k/dev/if_sn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_sn.c,v 1.44 2006/04/16 20:37:23 miod Exp $ */ +/* $OpenBSD: if_sn.c,v 1.45 2006/06/24 13:23:27 miod Exp $ */ /* $NetBSD: if_sn.c,v 1.13 1997/04/25 03:40:10 briggs Exp $ */ /* @@ -102,17 +102,44 @@ int snsetup(struct sn_softc *sc, u_int8_t *lladdr) { struct ifnet *ifp = &sc->sc_if; - u_char *p; - u_char *pp; - int i; - int offset; + struct pglist pglist; + vm_page_t pg; + paddr_t phys; + vaddr_t p, pp; + int i, offset, error; /* * XXX if_sn.c is intended to be MI. Should it allocate memory * for its descriptor areas, or expect the MD attach code * to do that? */ - sc->space = malloc((SN_NPAGES + 1) * PAGE_SIZE, M_DEVBUF, M_WAITOK); + TAILQ_INIT(&pglist); + error = uvm_pglistalloc(SN_NPAGES * PAGE_SIZE, 0, -PAGE_SIZE, + PAGE_SIZE, 0, &pglist, 1, 0); + if (error != 0) { + printf(": could not allocate descriptor memory\n"); + return (error); + } + + /* + * Map the pages uncached. + */ + sc->space = uvm_km_valloc(kernel_map, SN_NPAGES * PAGE_SIZE); + if (sc->space == NULL) { + printf(": could not map descriptor memory\n"); + uvm_pglistfree(&pglist); + return (ENOMEM); + } + + phys = VM_PAGE_TO_PHYS(TAILQ_FIRST(&pglist)); + p = pp = sc->space; + TAILQ_FOREACH(pg, &pglist, pageq) { + pmap_enter_cache(pmap_kernel(), p, VM_PAGE_TO_PHYS(pg), + UVM_PROT_RW, UVM_PROT_RW | PMAP_WIRED, PG_CI); + p += PAGE_SIZE; + } + pmap_update(pmap_kernel()); + p = pp; /* * Put the pup in reset mode (sninit() will fix it later), @@ -127,90 +154,71 @@ snsetup(struct sn_softc *sc, u_int8_t *lladdr) NIC_PUT(sc, SNR_ISR, ISR_ALL); wbflush(); - /* - * because the SONIC is basically 16bit device it 'concatenates' - * a higher buffer address to a 16 bit offset--this will cause wrap - * around problems near the end of 64k !! - */ - p = sc->space; - pp = (u_char *)ROUNDUP ((int)p, PAGE_SIZE); - p = pp; - - /* - * Disable caching on the SONIC's data space. - * The pages might not be physically contiguous, so set - * each page individually. - */ - for (i = 0; i < SN_NPAGES; i++) { - physaccess (p, (caddr_t)SONIC_GETDMA(p), PAGE_SIZE, - PG_V | PG_RW | PG_CI); - p += PAGE_SIZE; - } - p = pp; - for (i = 0; i < NRRA; i++) { sc->p_rra[i] = (void *)p; - sc->v_rra[i] = SONIC_GETDMA(p); + sc->v_rra[i] = (p - sc->space) + phys; p += RXRSRC_SIZE(sc); } - sc->v_rea = SONIC_GETDMA(p); + sc->v_rea = (p - sc->space) + phys; - p = (u_char *)SOALIGN(sc, p); + p = SOALIGN(sc, p); sc->p_cda = (void *)(p); - sc->v_cda = SONIC_GETDMA(p); + sc->v_cda = (p - sc->space) + phys; p += CDA_SIZE(sc); - p = (u_char *)SOALIGN(sc, p); + p = SOALIGN(sc, p); for (i = 0; i < NTDA; i++) { struct mtd *mtdp = &sc->mtda[i]; mtdp->mtd_txp = (void *)p; - mtdp->mtd_vtxp = SONIC_GETDMA(p); + mtdp->mtd_vtxp = (p - sc->space) + phys; p += TXP_SIZE(sc); } - p = (u_char *)SOALIGN(sc, p); + p = SOALIGN(sc, p); +#ifdef DIAGNOSTIC if ((p - pp) > PAGE_SIZE) { - printf ("%s: sizeof RRA (%ld) + CDA (%ld) +" + printf (": sizeof RRA (%ld) + CDA (%ld) +" "TDA (%ld) > PAGE_SIZE (%d). Punt!\n", - sc->sc_dev.dv_xname, (ulong)sc->p_cda - (ulong)sc->p_rra[0], (ulong)sc->mtda[0].mtd_txp - (ulong)sc->p_cda, (ulong)p - (ulong)sc->mtda[0].mtd_txp, PAGE_SIZE); - return(1); + return (EINVAL); } +#endif p = pp + PAGE_SIZE; pp = p; sc->sc_nrda = PAGE_SIZE / RXPKT_SIZE(sc); - sc->p_rda = (caddr_t) p; - sc->v_rda = SONIC_GETDMA(p); + sc->p_rda = (caddr_t)p; + sc->v_rda = (p - sc->space) + phys; p = pp + PAGE_SIZE; for (i = 0; i < NRBA; i++) { sc->rbuf[i] = (caddr_t)p; + sc->rbuf_phys[i] = (p - sc->space) + phys; p += PAGE_SIZE; } pp = p; - offset = TXBSIZE; + offset = 0; for (i = 0; i < NTDA; i++) { struct mtd *mtdp = &sc->mtda[i]; - mtdp->mtd_buf = p; - mtdp->mtd_vbuf = SONIC_GETDMA(p); + mtdp->mtd_buf = (caddr_t)p; + mtdp->mtd_vbuf = (p - sc->space) + phys; offset += TXBSIZE; - if (offset < PAGE_SIZE) { + if (offset < PAGE_SIZE - TXBSIZE) { p += TXBSIZE; } else { p = pp + PAGE_SIZE; pp = p; - offset = TXBSIZE; + offset = 0; } } @@ -796,7 +804,7 @@ initialise_rra(struct sn_softc *sc) /* fill up SOME of the rra with buffers */ for (i = 0; i < NRBA; i++) { - v = SONIC_GETDMA(sc->rbuf[i]); + v = sc->rbuf_phys[i]; SWO(bitmode, sc->p_rra[i], RXRSRC_PTRHI, UPPER(v)); SWO(bitmode, sc->p_rra[i], RXRSRC_PTRLO, LOWER(v)); SWO(bitmode, sc->p_rra[i], RXRSRC_WCHI, UPPER(PAGE_SIZE/2)); diff --git a/sys/arch/mac68k/dev/if_snvar.h b/sys/arch/mac68k/dev/if_snvar.h index 90c23200412..b9104b60d7f 100644 --- a/sys/arch/mac68k/dev/if_snvar.h +++ b/sys/arch/mac68k/dev/if_snvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_snvar.h,v 1.13 2005/07/23 23:28:58 martin Exp $ */ +/* $OpenBSD: if_snvar.h,v 1.14 2006/06/24 13:23:27 miod Exp $ */ /* $NetBSD: if_snvar.h,v 1.8 1997/04/25 03:40:09 briggs Exp $ */ /* @@ -44,9 +44,6 @@ ((sc)->sc_reg_map[reg]), \ (val))) -extern int kvtop(caddr_t addr); -#define SONIC_GETDMA(p) (u_int32_t)(kvtop((caddr_t)(p))) - #define SN_REGSIZE SN_NREGS*4 /* mac68k does not have any write buffers to flush... */ @@ -84,13 +81,13 @@ extern int kvtop(caddr_t addr); */ #define TXBSIZE 1536 /* 6*2^8 -- the same size as the 8390 TXBUF */ -#define SN_NPAGES 2 + NRBA + (NTDA/2) +#define SN_NPAGES (2 + NRBA + (NTDA/2)) typedef struct mtd { void *mtd_txp; - u_int32_t mtd_vtxp; + paddr_t mtd_vtxp; caddr_t mtd_buf; - u_int32_t mtd_vbuf; + paddr_t mtd_vbuf; struct mbuf *mtd_mbuf; } mtd_t; @@ -115,16 +112,17 @@ typedef struct sn_softc { int sc_rramark; /* index into p_rra of wp */ void *p_rra[NRRA]; /* RX resource descs */ - u_int32_t v_rra[NRRA]; /* DMA addresses of p_rra */ + paddr_t v_rra[NRRA]; /* DMA addresses of p_rra */ u_int32_t v_rea; /* ptr to the end of the rra space */ int sc_rxmark; /* current hw pos in rda ring */ int sc_rdamark; /* current sw pos in rda ring */ int sc_nrda; /* total number of RDAs */ caddr_t p_rda; - u_int32_t v_rda; + paddr_t v_rda; caddr_t rbuf[NRBA]; + paddr_t rbuf_phys[NRBA]; struct mtd mtda[NTDA]; int mtd_hw; /* idx of first mtd given to hw */ @@ -140,7 +138,7 @@ typedef struct sn_softc { void *p_cda; u_int32_t v_cda; - unsigned char *space; + vaddr_t space; } sn_softc_t; /* |