Subject: Re: noncontingous DMA segments with mc0 at obio
To: Martin Husemann <martin@duskware.de>
From: None <khym@azeotrope.org>
List: port-mac68k
Date: 12/10/2006 13:25:40
On Sat, Dec 09, 2006 at 10:59:46PM +0100, Martin Husemann wrote:
> Hi folks,
>
> after some hardware troubles I got my "brand new" Quadra 660AV booting
> NetBSD for the first time.
>
> The 4.0 install kernel fails to attach mc0 at obio, due to physically non
> contingous memory returned by malloc. See the comment in obio/if_mc_obio.c
> around line 140.
>
> I can rebuild my own install kernel, as suggest with only two rx DMA buffers.
> I could even try to convert this driver to bus_dma ;-)
>
> But I primarily wonder if this is a common effect, and wether the install
> kernels should be build with options MC_RXDMABUFS=2 to work around it.
I think some changes made to the m68k pmap code a while back caused
malloc to return physically non-contiguous memory... I never saw that
message before, but I always get it in post-3.x kernels.
Using bus_dma would be great :) I took a stab at it a while back, but
I'm not sure if the best way of doing things:
Index: sys/arch/mac68k/dev/if_mc.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mac68k/dev/if_mc.c,v
retrieving revision 1.27
diff -u -r1.27 if_mc.c
--- sys/arch/mac68k/dev/if_mc.c 7 Sep 2006 02:40:31 -0000 1.27
+++ sys/arch/mac68k/dev/if_mc.c 10 Dec 2006 19:24:33 -0000
@@ -411,7 +411,7 @@
u_int len, totlen = 0;
u_char *buff;
- buff = sc->sc_txbuf;
+ buff = sc->sc_txbuf + (sc->sc_txset == 0 ? 0 : 0x800);
for (; m; m = n) {
u_char *data = mtod(m, u_char *);
Index: sys/arch/mac68k/dev/if_mcvar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/mac68k/dev/if_mcvar.h,v
retrieving revision 1.11
diff -u -r1.11 if_mcvar.h
--- sys/arch/mac68k/dev/if_mcvar.h 24 Dec 2005 20:07:15 -0000 1.11
+++ sys/arch/mac68k/dev/if_mcvar.h 10 Dec 2006 19:24:33 -0000
@@ -78,9 +78,12 @@
bus_space_tag_t sc_regt;
bus_space_handle_t sc_regh;
+ bus_dma_tag_t sc_dmat;
+ bus_dmamap_t sc_dmam_tx, sc_dmam_rx;
+ bus_dma_segment_t sc_dmasegs_tx, sc_dmasegs_rx;
- u_char *sc_txbuf, *sc_rxbuf;
- int sc_txbuf_phys, sc_rxbuf_phys;
+ caddr_t sc_txbuf, sc_rxbuf;
+ bus_addr_t sc_txbuf_phys, sc_rxbuf_phys;
int sc_tail;
int sc_rxset;
int sc_txset, sc_txseti;
Index: sys/arch/mac68k/obio/if_mc_obio.c
===================================================================
RCS file: /cvsroot/src/sys/arch/mac68k/obio/if_mc_obio.c,v
retrieving revision 1.15
diff -u -r1.15 if_mc_obio.c
--- sys/arch/mac68k/obio/if_mc_obio.c 11 Dec 2005 12:18:03 -0000 1.15
+++ sys/arch/mac68k/obio/if_mc_obio.c 10 Dec 2006 19:24:34 -0000
@@ -111,7 +111,7 @@
struct obio_attach_args *oa = (struct obio_attach_args *)aux;
struct mc_softc *sc = (void *)self;
u_int8_t myaddr[ETHER_ADDR_LEN];
- int i, noncontig = 0;
+ int rsegs;
sc->sc_regt = oa->oa_tag;
sc->sc_biucc = XMTSP_64;
@@ -130,38 +130,59 @@
return;
}
- /* 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);
+ /* allocate memory for transmit and receive DMA buffers */
+ sc->sc_dmat = oa->oa_dmat;
+ if (bus_dmamem_alloc(sc->sc_dmat, 2 * 0x800, 0, 0, &sc->sc_dmasegs_tx,
+ 1, &rsegs, BUS_DMA_NOWAIT) != 0) {
+ printf(": failed to allocate TX DMA buffers.\n");
+ return;
+ }
- /*
- * 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;
+ if (bus_dmamem_map(sc->sc_dmat, &sc->sc_dmasegs_tx, rsegs, 2 * 0x800,
+ &sc->sc_txbuf, BUS_DMA_NOWAIT | BUS_DMA_COHERENT) != 0) {
+ printf(": failed to map TX DMA buffers.\n");
+ return;
}
- if (noncontig) {
- printf("%s: receive DMA buffer not contiguous! "
- "Try compiling with \"options MC_RXDMABUFS=2\"\n",
- sc->sc_dev.dv_xname);
+ if (bus_dmamem_alloc(sc->sc_dmat, MC_RXDMABUFS * 0x800, 0, 0,
+ &sc->sc_dmasegs_rx, 1, &rsegs, BUS_DMA_NOWAIT) != 0) {
+ printf(": failed to allocate RX DMA buffers.\n");
+ return;
+ }
+
+ if (bus_dmamem_map(sc->sc_dmat, &sc->sc_dmasegs_rx, rsegs,
+ MC_RXDMABUFS * 0x800, &sc->sc_rxbuf,
+ BUS_DMA_NOWAIT | BUS_DMA_COHERENT) != 0) {
+ printf(": failed to map RX DMA buffers.\n");
+ return;
+ }
+
+ if (bus_dmamap_create(sc->sc_dmat, 2 * 0x800, 1, 2 * 0x800, 0,
+ BUS_DMA_NOWAIT, &sc->sc_dmam_tx) != 0) {
+ printf(": failed to allocate TX DMA map.\n");
return;
}
+
+ if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmam_tx, sc->sc_txbuf,
+ 2 * 0x800, NULL, BUS_DMA_NOWAIT) != 0) {
+ printf(": failed to map TX DMA mapping.\n");
+ return;
+ }
+
+ if (bus_dmamap_create(sc->sc_dmat, MC_RXDMABUFS * 0x800, 1,
+ MC_RXDMABUFS * 0x800, 0, BUS_DMA_NOWAIT, &sc->sc_dmam_rx) != 0) {
+ printf(": failed to allocate RX DMA map.\n");
+ return;
+ }
+
+ if (bus_dmamap_load(sc->sc_dmat, sc->sc_dmam_rx, sc->sc_rxbuf,
+ MC_RXDMABUFS * 0x800, NULL, BUS_DMA_NOWAIT) != 0) {
+ printf(": failed to map RX DMA mapping.\n");
+ return;
+ }
+
+ sc->sc_txbuf_phys = sc->sc_dmasegs_tx.ds_addr;
+ sc->sc_rxbuf_phys = sc->sc_dmasegs_rx.ds_addr;
sc->sc_bus_init = mc_obio_init;
sc->sc_putpacket = mc_obio_put;
@@ -219,9 +240,15 @@
hide void
mc_obio_put(struct mc_softc *sc, u_int len)
{
- psc_reg4(PSC_ENETWR_ADDR + sc->sc_txset) = sc->sc_txbuf_phys;
+ int offset = sc->sc_txset == 0 ? 0 : 0x800;
+
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_dmam_tx, offset, 0x800,
+ BUS_DMASYNC_PREWRITE);
+ psc_reg4(PSC_ENETWR_ADDR + sc->sc_txset) = sc->sc_txbuf_phys + offset;
psc_reg4(PSC_ENETWR_LEN + sc->sc_txset) = len;
psc_reg2(PSC_ENETWR_CMD + sc->sc_txset) = 0x9800;
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_dmam_tx, offset, 0x800,
+ BUS_DMASYNC_POSTWRITE);
sc->sc_txset ^= 0x10;
}
@@ -279,6 +306,11 @@
/* Loop through, processing each of the packets */
for (; sc->sc_tail < head; sc->sc_tail++) {
offset = sc->sc_tail * 0x800;
+
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_dmam_rx,
+ PAGE_SIZE + offset, 0x800,
+ BUS_DMASYNC_PREREAD);
+
sc->sc_rxframe.rx_rcvcnt = sc->sc_rxbuf[offset];
sc->sc_rxframe.rx_rcvsts = sc->sc_rxbuf[offset+2];
sc->sc_rxframe.rx_rntpc = sc->sc_rxbuf[offset+4];
@@ -286,6 +318,10 @@
sc->sc_rxframe.rx_frame = sc->sc_rxbuf + offset + 16;
mc_rint(sc);
+
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_dmam_rx,
+ PAGE_SIZE + offset, 0x800,
+ BUS_DMASYNC_POSTREAD);
}
/*
--
Name: Dave Huang | Mammal, mammal / their names are called /
INet: khym@azeotrope.org | they raise a paw / the bat, the cat /
FurryMUCK: Dahan | dolphin and dog / koala bear and hog -- TMBG
Dahan: Hani G Y+C 31 Y++ L+++ W- C++ T++ A+ E+ S++ V++ F- Q+++ P+ B+ PA+ PL++