summaryrefslogtreecommitdiff
path: root/sys/dev/ic/re.c
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2006-10-31 07:04:26 +0000
committerBrad Smith <brad@cvs.openbsd.org>2006-10-31 07:04:26 +0000
commitcc931ca42cb32d3b9405fa56a71855a8219859b1 (patch)
treea4a2aae54d3fe88a34cf72adfc77d9c2ad871506 /sys/dev/ic/re.c
parent00155d94c95911dc2baedcfe0b620e67115781eb (diff)
- Make DMA descripter members volatile
- Remove usage of BUS_DMA_ALLOCNOW with bus_dmamap_create - Use BUS_DMA_COHERENT on mapping DMA memory for TX/RX descriptors - Adjust m_data and m_len directly rather than calling m_adj - Proper use of bus_dmamap_sync against DMA descriptors From tsutsui@NetBSD Tested by kettenis@ brad@ otto@ Tested on armish/amd64/i386/sparc64
Diffstat (limited to 'sys/dev/ic/re.c')
-rw-r--r--sys/dev/ic/re.c159
1 files changed, 71 insertions, 88 deletions
diff --git a/sys/dev/ic/re.c b/sys/dev/ic/re.c
index 17f6fc8677e..b2ae526a69f 100644
--- a/sys/dev/ic/re.c
+++ b/sys/dev/ic/re.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: re.c,v 1.49 2006/10/22 21:19:22 brad Exp $ */
+/* $OpenBSD: re.c,v 1.50 2006/10/31 07:04:25 brad Exp $ */
/* $FreeBSD: if_re.c,v 1.31 2004/09/04 07:54:05 ru Exp $ */
/*
* Copyright (c) 1997, 1998-2003
@@ -679,10 +679,6 @@ re_diag(struct rl_softc *sc)
* entry in the RX DMA ring. Grab it from there.
*/
- dmamap = sc->rl_ldata.rl_rx_list_map;
- bus_dmamap_sync(sc->sc_dmat,
- dmamap, 0, dmamap->dm_mapsize,
- BUS_DMASYNC_POSTREAD);
dmamap = sc->rl_ldata.rl_rx_dmamap[0];
bus_dmamap_sync(sc->sc_dmat,
dmamap, 0, dmamap->dm_mapsize,
@@ -694,9 +690,10 @@ re_diag(struct rl_softc *sc)
sc->rl_ldata.rl_rx_mbuf[0] = NULL;
eh = mtod(m0, struct ether_header *);
+ RL_RXDESCSYNC(sc, 0, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
cur_rx = &sc->rl_ldata.rl_rx_list[0];
- total_len = RL_RXBYTES(cur_rx);
rxstat = letoh32(cur_rx->rl_cmdstat);
+ total_len = rxstat & sc->rl_rxlenmask;
if (total_len != ETHER_MIN_LEN) {
printf("%s: diagnostic failed, received short packet\n",
@@ -845,7 +842,7 @@ re_attach(struct rl_softc *sc)
if ((error = bus_dmamem_map(sc->sc_dmat, &sc->rl_ldata.rl_tx_listseg,
sc->rl_ldata.rl_tx_listnseg, RL_TX_LIST_SZ(sc),
(caddr_t *)&sc->rl_ldata.rl_tx_list,
- BUS_DMA_NOWAIT)) != 0) {
+ BUS_DMA_COHERENT | BUS_DMA_NOWAIT)) != 0) {
printf("%s: can't map tx list, error = %d\n",
sc->sc_dev.dv_xname, error);
goto fail_1;
@@ -853,7 +850,7 @@ re_attach(struct rl_softc *sc)
memset(sc->rl_ldata.rl_tx_list, 0, RL_TX_LIST_SZ(sc));
if ((error = bus_dmamap_create(sc->sc_dmat, RL_TX_LIST_SZ(sc), 1,
- RL_TX_LIST_SZ(sc), 0, BUS_DMA_ALLOCNOW,
+ RL_TX_LIST_SZ(sc), 0, 0,
&sc->rl_ldata.rl_tx_list_map)) != 0) {
printf("%s: can't create tx list map, error = %d\n",
sc->sc_dev.dv_xname, error);
@@ -873,7 +870,7 @@ re_attach(struct rl_softc *sc)
error = bus_dmamap_create(sc->sc_dmat,
RL_JUMBO_FRAMELEN,
RL_TX_DESC_CNT(sc) - 4, RL_TDESC_CMD_FRAGLEN,
- 0, BUS_DMA_ALLOCNOW,
+ 0, 0,
&sc->rl_ldata.rl_txq[i].txq_dmamap);
if (error) {
printf("%s: can't create DMA map for TX\n",
@@ -895,7 +892,7 @@ re_attach(struct rl_softc *sc)
if ((error = bus_dmamem_map(sc->sc_dmat, &sc->rl_ldata.rl_rx_listseg,
sc->rl_ldata.rl_rx_listnseg, RL_RX_LIST_SZ,
(caddr_t *)&sc->rl_ldata.rl_rx_list,
- BUS_DMA_NOWAIT)) != 0) {
+ BUS_DMA_COHERENT | BUS_DMA_NOWAIT)) != 0) {
printf("%s: can't map rx list, error = %d\n",
sc->sc_dev.dv_xname, error);
goto fail_5;
@@ -904,7 +901,7 @@ re_attach(struct rl_softc *sc)
memset(sc->rl_ldata.rl_rx_list, 0, RL_RX_LIST_SZ);
if ((error = bus_dmamap_create(sc->sc_dmat, RL_RX_LIST_SZ, 1,
- RL_RX_LIST_SZ, 0, BUS_DMA_ALLOCNOW,
+ RL_RX_LIST_SZ, 0, 0,
&sc->rl_ldata.rl_rx_list_map)) != 0) {
printf("%s: can't create rx list map, error = %d\n",
sc->sc_dev.dv_xname, error);
@@ -922,7 +919,7 @@ re_attach(struct rl_softc *sc)
/* Create DMA maps for RX buffers */
for (i = 0; i < RL_RX_DESC_CNT; i++) {
error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
- 0, BUS_DMA_ALLOCNOW, &sc->rl_ldata.rl_rx_dmamap[i]);
+ 0, 0, &sc->rl_ldata.rl_rx_dmamap[i]);
if (error) {
printf("%s: can't create DMA map for RX\n",
sc->sc_dev.dv_xname);
@@ -1055,13 +1052,13 @@ re_newbuf(struct rl_softc *sc, int idx, struct mbuf *m)
MGETHDR(n, M_DONTWAIT, MT_DATA);
if (n == NULL)
return (ENOBUFS);
- m = n;
- MCLGET(m, M_DONTWAIT);
- if (! (m->m_flags & M_EXT)) {
- m_freem(m);
+ MCLGET(n, M_DONTWAIT);
+ if (!(n->m_flags & M_EXT)) {
+ m_freem(n);
return (ENOBUFS);
}
+ m = n;
} else
m->m_data = m->m_ext.ext_buf;
@@ -1088,26 +1085,34 @@ re_newbuf(struct rl_softc *sc, int idx, struct mbuf *m)
if (error)
goto out;
+ bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+ BUS_DMASYNC_PREREAD);
+
d = &sc->rl_ldata.rl_rx_list[idx];
- if (letoh32(d->rl_cmdstat) & RL_RDESC_STAT_OWN)
+ RL_RXDESCSYNC(sc, idx, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+ cmdstat = letoh32(d->rl_cmdstat);
+ RL_RXDESCSYNC(sc, idx, BUS_DMASYNC_PREREAD);
+ if (cmdstat & RL_RDESC_STAT_OWN) {
+ printf("%s: tried to map busy RX descriptor\n",
+ sc->sc_dev.dv_xname);
goto out;
+ }
cmdstat = map->dm_segs[0].ds_len;
- d->rl_bufaddr_lo = htole32(RL_ADDR_LO(map->dm_segs[0].ds_addr));
- d->rl_bufaddr_hi = htole32(RL_ADDR_HI(map->dm_segs[0].ds_addr));
if (idx == (RL_RX_DESC_CNT - 1))
cmdstat |= RL_RDESC_CMD_EOR;
+ d->rl_bufaddr_lo = htole32(RL_ADDR_LO(map->dm_segs[0].ds_addr));
+ d->rl_bufaddr_hi = htole32(RL_ADDR_HI(map->dm_segs[0].ds_addr));
d->rl_cmdstat = htole32(cmdstat);
+ RL_RXDESCSYNC(sc, idx, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+ cmdstat |= RL_RDESC_CMD_OWN;
+ d->rl_cmdstat = htole32(cmdstat);
+ RL_RXDESCSYNC(sc, idx, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
- sc->rl_ldata.rl_rx_list[idx].rl_cmdstat |= htole32(RL_RDESC_CMD_OWN);
sc->rl_ldata.rl_rx_mbuf[idx] = m;
- bus_dmamap_sync(sc->sc_dmat, sc->rl_ldata.rl_rx_dmamap[idx], 0,
- sc->rl_ldata.rl_rx_dmamap[idx]->dm_mapsize,
- BUS_DMASYNC_PREREAD);
-
return (0);
-out:
+ out:
if (n != NULL)
m_freem(n);
return (ENOMEM);
@@ -1142,7 +1147,8 @@ re_tx_list_init(struct rl_softc *sc)
bus_dmamap_sync(sc->sc_dmat,
sc->rl_ldata.rl_tx_list_map, 0,
- sc->rl_ldata.rl_tx_list_map->dm_mapsize, BUS_DMASYNC_PREWRITE);
+ sc->rl_ldata.rl_tx_list_map->dm_mapsize,
+ BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
sc->rl_ldata.rl_txq_prodidx = 0;
sc->rl_ldata.rl_txq_considx = 0;
sc->rl_ldata.rl_tx_free = RL_TX_DESC_CNT(sc);
@@ -1165,13 +1171,6 @@ re_rx_list_init(struct rl_softc *sc)
return (ENOBUFS);
}
- /* Flush the RX descriptors */
-
- bus_dmamap_sync(sc->sc_dmat,
- sc->rl_ldata.rl_rx_list_map,
- 0, sc->rl_ldata.rl_rx_list_map->dm_mapsize,
- BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
-
sc->rl_ldata.rl_rx_prodidx = 0;
sc->rl_head = sc->rl_tail = NULL;
@@ -1193,20 +1192,17 @@ re_rxeof(struct rl_softc *sc)
u_int32_t rxstat;
ifp = &sc->sc_arpcom.ac_if;
- i = sc->rl_ldata.rl_rx_prodidx;
-
- /* Invalidate the descriptor memory */
-
- bus_dmamap_sync(sc->sc_dmat,
- sc->rl_ldata.rl_rx_list_map,
- 0, sc->rl_ldata.rl_rx_list_map->dm_mapsize,
- BUS_DMASYNC_POSTREAD);
- while (!RL_OWN(&sc->rl_ldata.rl_rx_list[i])) {
+ for (i = sc->rl_ldata.rl_rx_prodidx;; RL_RX_DESC_INC(sc, i)) {
cur_rx = &sc->rl_ldata.rl_rx_list[i];
- m = sc->rl_ldata.rl_rx_mbuf[i];
- total_len = RL_RXBYTES(cur_rx);
+ RL_RXDESCSYNC(sc, i,
+ BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
rxstat = letoh32(cur_rx->rl_cmdstat);
+ RL_RXDESCSYNC(sc, i, BUS_DMASYNC_PREREAD);
+ if ((rxstat & RL_RDESC_STAT_OWN) != 0)
+ break;
+ total_len = rxstat & sc->rl_rxlenmask;
+ m = sc->rl_ldata.rl_rx_mbuf[i];
/* Invalidate the RX mbuf and unload its map */
@@ -1227,7 +1223,6 @@ re_rxeof(struct rl_softc *sc)
sc->rl_tail = m;
}
re_newbuf(sc, i, NULL);
- RL_RX_DESC_INC(sc, i);
continue;
}
@@ -1266,7 +1261,6 @@ re_rxeof(struct rl_softc *sc)
sc->rl_head = sc->rl_tail = NULL;
}
re_newbuf(sc, i, m);
- RL_RX_DESC_INC(sc, i);
continue;
}
@@ -1282,12 +1276,9 @@ re_rxeof(struct rl_softc *sc)
sc->rl_head = sc->rl_tail = NULL;
}
re_newbuf(sc, i, m);
- RL_RX_DESC_INC(sc, i);
continue;
}
- RL_RX_DESC_INC(sc, i);
-
if (sc->rl_head != NULL) {
m->m_len = total_len % RE_RX_DESC_BUFLEN;
if (m->m_len == 0)
@@ -1341,13 +1332,6 @@ re_rxeof(struct rl_softc *sc)
ether_input_mbuf(ifp, m);
}
- /* Flush the RX DMA ring */
-
- bus_dmamap_sync(sc->sc_dmat,
- sc->rl_ldata.rl_rx_list_map,
- 0, sc->rl_ldata.rl_rx_list_map->dm_mapsize,
- BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
-
sc->rl_ldata.rl_rx_prodidx = i;
}
@@ -1360,14 +1344,7 @@ re_txeof(struct rl_softc *sc)
ifp = &sc->sc_arpcom.ac_if;
idx = sc->rl_ldata.rl_txq_considx;
- /* Invalidate the TX descriptor list */
-
- bus_dmamap_sync(sc->sc_dmat,
- sc->rl_ldata.rl_tx_list_map,
- 0, sc->rl_ldata.rl_tx_list_map->dm_mapsize,
- BUS_DMASYNC_POSTREAD);
-
- while (/* CONSTCOND */ 1) {
+ for (;;) {
struct rl_txq *txq = &sc->rl_ldata.rl_txq[idx];
int descidx;
u_int32_t txstat;
@@ -1378,14 +1355,19 @@ re_txeof(struct rl_softc *sc)
}
descidx = txq->txq_descidx;
+ RL_TXDESCSYNC(sc, descidx,
+ BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
txstat =
letoh32(sc->rl_ldata.rl_tx_list[descidx].rl_cmdstat);
+ RL_TXDESCSYNC(sc, descidx, BUS_DMASYNC_PREREAD);
KASSERT((txstat & RL_TDESC_CMD_EOF) != 0);
if (txstat & RL_TDESC_CMD_OWN)
break;
sc->rl_ldata.rl_tx_free += txq->txq_dmamap->dm_nsegs;
KASSERT(sc->rl_ldata.rl_tx_free <= RL_TX_DESC_CNT(sc));
+ bus_dmamap_sync(sc->sc_dmat, txq->txq_dmamap,
+ 0, txq->txq_dmamap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->sc_dmat, txq->txq_dmamap);
m_freem(txq->txq_mbuf);
txq->txq_mbuf = NULL;
@@ -1519,7 +1501,7 @@ int
re_encap(struct rl_softc *sc, struct mbuf *m, int *idx)
{
bus_dmamap_t map;
- int error, i, startidx, curidx;
+ int error, i, uidx, startidx, curidx;
#ifdef RE_VLAN
struct m_tag *mtag;
#endif
@@ -1590,13 +1572,21 @@ re_encap(struct rl_softc *sc, struct mbuf *m, int *idx)
*/
i = 0;
curidx = startidx = sc->rl_ldata.rl_tx_nextfree;
- while (1) {
+ for (;;) {
d = &sc->rl_ldata.rl_tx_list[curidx];
- if (letoh32(d->rl_cmdstat) & RL_TDESC_STAT_OWN) {
+ RL_TXDESCSYNC(sc, curidx,
+ BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
+ cmdstat = letoh32(d->rl_cmdstat);
+ RL_TXDESCSYNC(sc, curidx, BUS_DMASYNC_PREREAD);
+ if (cmdstat & RL_TDESC_STAT_OWN) {
+ printf("%s: tried to map busy TX descriptor\n",
+ sc->sc_dev.dv_xname);
while (i > 0) {
- sc->rl_ldata.rl_tx_list[
- (curidx + RL_TX_DESC_CNT(sc) - i) %
- RL_TX_DESC_CNT(sc)].rl_cmdstat = 0;
+ uidx = (curidx + RL_TX_DESC_CNT(sc) - i) %
+ RL_TX_DESC_CNT(sc);
+ sc->rl_ldata.rl_tx_list[uidx].rl_cmdstat = 0;
+ RL_TXDESCSYNC(sc, uidx,
+ BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
i--;
}
error = ENOBUFS;
@@ -1604,25 +1594,27 @@ re_encap(struct rl_softc *sc, struct mbuf *m, int *idx)
}
cmdstat = map->dm_segs[i].ds_len;
- d->rl_bufaddr_lo =
- htole32(RL_ADDR_LO(map->dm_segs[i].ds_addr));
- d->rl_bufaddr_hi =
- htole32(RL_ADDR_HI(map->dm_segs[i].ds_addr));
if (i == 0)
cmdstat |= RL_TDESC_CMD_SOF;
else
cmdstat |= RL_TDESC_CMD_OWN;
+ if (i == map->dm_nsegs - 1)
+ cmdstat |= RL_TDESC_CMD_EOF;
if (curidx == (RL_TX_DESC_CNT(sc) - 1))
cmdstat |= RL_TDESC_CMD_EOR;
d->rl_cmdstat = htole32(cmdstat | rl_flags);
+ d->rl_bufaddr_lo =
+ htole32(RL_ADDR_LO(map->dm_segs[i].ds_addr));
+ d->rl_bufaddr_hi =
+ htole32(RL_ADDR_HI(map->dm_segs[i].ds_addr));
+ RL_TXDESCSYNC(sc, curidx,
+ BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
i++;
if (i == map->dm_nsegs)
break;
RL_TX_DESC_INC(sc, curidx);
}
- d->rl_cmdstat |= htole32(RL_TDESC_CMD_EOF);
-
txq->txq_mbuf = m;
sc->rl_ldata.rl_tx_free -= map->dm_nsegs;
@@ -1642,11 +1634,9 @@ re_encap(struct rl_softc *sc, struct mbuf *m, int *idx)
/* Transfer ownership of packet to the chip. */
- sc->rl_ldata.rl_tx_list[curidx].rl_cmdstat |=
+ sc->rl_ldata.rl_tx_list[startidx].rl_cmdstat |=
htole32(RL_TDESC_CMD_OWN);
- if (startidx != curidx)
- sc->rl_ldata.rl_tx_list[startidx].rl_cmdstat |=
- htole32(RL_TDESC_CMD_OWN);
+ RL_TXDESCSYNC(sc, startidx, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
txq->txq_descidx = curidx;
RL_TX_DESC_INC(sc, curidx);
@@ -1677,7 +1667,7 @@ re_start(struct ifnet *ifp)
return;
idx = sc->rl_ldata.rl_txq_prodidx;
- while (/* CONSTCOND */ 1) {
+ for (;;) {
struct mbuf *m;
int error;
@@ -1725,13 +1715,6 @@ re_start(struct ifnet *ifp)
sc->rl_ldata.rl_txq_prodidx = idx;
- /* Flush the TX descriptors */
-
- bus_dmamap_sync(sc->sc_dmat,
- sc->rl_ldata.rl_tx_list_map,
- 0, sc->rl_ldata.rl_tx_list_map->dm_mapsize,
- BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
-
CSR_WRITE_1(sc, sc->rl_txstart, RL_TXSTART_START);
/*