summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2006-06-24 13:23:28 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2006-06-24 13:23:28 +0000
commite9eab0aae49664d0c130f1b60640f862d325d438 (patch)
treefe7535d02630b5457d712545c4ecaa7ec23bc5e0
parent03f621b4ad00ae11a297fdcebfc89315b2320da3 (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.c106
-rw-r--r--sys/arch/mac68k/dev/if_mcvar.h4
-rw-r--r--sys/arch/mac68k/dev/if_sn.c98
-rw-r--r--sys/arch/mac68k/dev/if_snvar.h18
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;
/*