On 2010/11/12 21:32, Stuart Henderson wrote:
>
> (at first I forgot to disable IPsec - the IPsec gateway for my
> netbook is an alix, so I was also able to discover that netblast
> is rather good at triggering the vr(4) hangs there which require
> ifconfig down+up to recover from - I guess I will be building a
> non-MCLGETI vr(4) sometime soon too).
And here's that diff, which does indeed help the vr(4) on my Alix
when I blast it with packets.
Index: if_vr.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_vr.c,v
retrieving revision 1.106
diff -u -p -r1.106 if_vr.c
--- if_vr.c 3 Sep 2010 18:14:54 -0000 1.106
+++ if_vr.c 13 Nov 2010 13:04:27 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_vr.c,v 1.106 2010/09/03 18:14:54 kettenis Exp $ */
+/* $OpenBSD: if_vr.c,v 1.95 2009/06/04 16:56:20 sthen Exp $ */
/*
* Copyright (c) 1997, 1998
@@ -135,10 +135,9 @@ void vr_setcfg(struct vr_softc *, int);
void vr_iff(struct vr_softc *);
void vr_reset(struct vr_softc *);
int vr_list_rx_init(struct vr_softc *);
-void vr_fill_rx_ring(struct vr_softc *);
int vr_list_tx_init(struct vr_softc *);
-int vr_alloc_mbuf(struct vr_softc *, struct vr_chain_onefrag *);
+int vr_alloc_mbuf(struct vr_softc *, struct vr_chain_onefrag *, struct mbuf *);
/*
* Supported devices & quirks
@@ -664,7 +663,6 @@ vr_attach(struct device *parent, struct
/*
* Call MI attach routines.
*/
- m_clsetwms(ifp, MCLBYTES, 2, VR_RX_LIST_CNT - 1);
if_attach(ifp);
ether_ifattach(ifp);
return;
@@ -749,6 +747,9 @@ vr_list_rx_init(struct vr_softc *sc)
sc->sc_listmap->dm_segs[0].ds_addr +
offsetof(struct vr_list_data, vr_rx_list[i]);
+ if (vr_alloc_mbuf(sc, &cd->vr_rx_chain[i], NULL))
+ return (ENOBUFS);
+
if (i == (VR_RX_LIST_CNT - 1))
nexti = 0;
else
@@ -760,30 +761,11 @@ vr_list_rx_init(struct vr_softc *sc)
offsetof(struct vr_list_data, vr_rx_list[nexti]));
}
- cd->vr_rx_prod = cd->vr_rx_cons = &cd->vr_rx_chain[0];
- cd->vr_rx_cnt = 0;
- vr_fill_rx_ring(sc);
+ cd->vr_rx_head = &cd->vr_rx_chain[0];
return (0);
}
-void
-vr_fill_rx_ring(struct vr_softc *sc)
-{
- struct vr_chain_data *cd;
- struct vr_list_data *ld;
-
- cd = &sc->vr_cdata;
- ld = sc->vr_ldata;
-
- while (cd->vr_rx_cnt < VR_RX_LIST_CNT) {
- if (vr_alloc_mbuf(sc, cd->vr_rx_prod))
- break;
- cd->vr_rx_prod = cd->vr_rx_prod->vr_nextdesc;
- cd->vr_rx_cnt++;
- }
-}
-
/*
* A frame has been uploaded: pass the resulting mbuf chain up to
* the higher level protocols.
@@ -791,7 +773,7 @@ vr_fill_rx_ring(struct vr_softc *sc)
void
vr_rxeof(struct vr_softc *sc)
{
- struct mbuf *m;
+ struct mbuf *m0, *m;
struct ifnet *ifp;
struct vr_chain_onefrag *cur_rx;
int total_len = 0;
@@ -799,21 +781,20 @@ vr_rxeof(struct vr_softc *sc)
ifp = &sc->arpcom.ac_if;
- while(sc->vr_cdata.vr_rx_cnt > 0) {
+ for (;;) {
+
bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
0, sc->sc_listmap->dm_mapsize,
BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
- rxstat = letoh32(sc->vr_cdata.vr_rx_cons->vr_ptr->vr_status);
+ rxstat = letoh32(sc->vr_cdata.vr_rx_head->vr_ptr->vr_status);
if (rxstat & VR_RXSTAT_OWN)
break;
- rxctl = letoh32(sc->vr_cdata.vr_rx_cons->vr_ptr->vr_ctl);
+ rxctl = letoh32(sc->vr_cdata.vr_rx_head->vr_ptr->vr_ctl);
- cur_rx = sc->vr_cdata.vr_rx_cons;
- m = cur_rx->vr_mbuf;
- cur_rx->vr_mbuf = NULL;
- sc->vr_cdata.vr_rx_cons = cur_rx->vr_nextdesc;
- sc->vr_cdata.vr_rx_cnt--;
+ m0 = NULL;
+ cur_rx = sc->vr_cdata.vr_rx_head;
+ sc->vr_cdata.vr_rx_head = cur_rx->vr_nextdesc;
/*
* If an error occurs, update stats, clear the
@@ -843,13 +824,24 @@ vr_rxeof(struct vr_softc *sc)
printf("\n");
#endif
- m_freem(m);
+ /* Reinitialize descriptor */
+ cur_rx->vr_ptr->vr_status = htole32(VR_RXSTAT);
+ cur_rx->vr_ptr->vr_data =
+ htole32(cur_rx->vr_map->dm_segs[0].ds_addr +
+ sizeof(u_int64_t));
+ cur_rx->vr_ptr->vr_ctl = htole32(VR_RXCTL | VR_RXLEN);
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
+ 0, sc->sc_listmap->dm_mapsize,
+ BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
continue;
}
/* No errors; receive the packet. */
total_len = VR_RXBYTES(letoh32(cur_rx->vr_ptr->vr_status));
+ m = cur_rx->vr_mbuf;
+ cur_rx->vr_mbuf = NULL;
+
bus_dmamap_sync(sc->sc_dmat, cur_rx->vr_map, 0,
cur_rx->vr_map->dm_mapsize, BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(sc->sc_dmat, cur_rx->vr_map);
@@ -861,22 +853,22 @@ vr_rxeof(struct vr_softc *sc)
*/
total_len -= ETHER_CRC_LEN;
-#ifdef __STRICT_ALIGNMENT
+#ifndef __STRICT_ALIGNMENT
+ if (vr_alloc_mbuf(sc, cur_rx, NULL) == 0) {
+ m->m_pkthdr.rcvif = ifp;
+ m->m_pkthdr.len = m->m_len = total_len;
+ } else
+#endif
{
- struct mbuf *m0;
m0 = m_devget(mtod(m, caddr_t), total_len,
ETHER_ALIGN, ifp, NULL);
- m_freem(m);
+ vr_alloc_mbuf(sc, cur_rx, m);
if (m0 == NULL) {
ifp->if_ierrors++;
continue;
}
m = m0;
- }
-#else
- m->m_pkthdr.rcvif = ifp;
- m->m_pkthdr.len = m->m_len = total_len;
-#endif
+ }
ifp->if_ipackets++;
if (sc->vr_quirks & VR_Q_CSUM &&
@@ -902,8 +894,6 @@ vr_rxeof(struct vr_softc *sc)
ether_input_mbuf(ifp, m);
}
- vr_fill_rx_ring(sc);
-
bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
0, sc->sc_listmap->dm_mapsize,
BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
@@ -935,7 +925,7 @@ vr_rxeoc(struct vr_softc *sc)
vr_rxeof(sc);
- CSR_WRITE_4(sc, VR_RXADDR, sc->vr_cdata.vr_rx_cons->vr_paddr);
+ CSR_WRITE_4(sc, VR_RXADDR, sc->vr_cdata.vr_rx_head->vr_paddr);
VR_SETBIT16(sc, VR_COMMAND, VR_CMD_RX_ON);
VR_SETBIT16(sc, VR_COMMAND, VR_CMD_RX_GO);
}
@@ -1345,7 +1335,7 @@ vr_init(void *xsc)
/*
* Load the address of the RX list.
*/
- CSR_WRITE_4(sc, VR_RXADDR, sc->vr_cdata.vr_rx_cons->vr_paddr);
+ CSR_WRITE_4(sc, VR_RXADDR, sc->vr_cdata.vr_rx_head->vr_paddr);
/* Enable receiver and transmitter. */
CSR_WRITE_2(sc, VR_COMMAND, VR_CMD_TX_NOPOLL|VR_CMD_START|
@@ -1534,23 +1524,34 @@ vr_stop(struct vr_softc *sc)
}
int
-vr_alloc_mbuf(struct vr_softc *sc, struct vr_chain_onefrag *r)
+vr_alloc_mbuf(struct vr_softc *sc, struct vr_chain_onefrag *r, struct mbuf *mb)
{
struct vr_desc *d;
struct mbuf *m;
- if (r == NULL)
- return (EINVAL);
+ if (mb == NULL) {
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == NULL)
+ return (ENOBUFS);
- m = MCLGETI(NULL, M_DONTWAIT, &sc->arpcom.ac_if, MCLBYTES);
- if (!m)
- return (ENOBUFS);
+ MCLGET(m, M_DONTWAIT);
+ if (!(m->m_flags & M_EXT)) {
+ m_free(m);
+ return (ENOBUFS);
+ }
+ } else {
+ m = mb;
+ m->m_data = m->m_ext.ext_buf;
+ }
m->m_len = m->m_pkthdr.len = MCLBYTES;
+ r->vr_mbuf = m;
+
m_adj(m, sizeof(u_int64_t));
- if (bus_dmamap_load_mbuf(sc->sc_dmat, r->vr_map, m, BUS_DMA_NOWAIT)) {
- m_free(m);
+ if (bus_dmamap_load_mbuf(sc->sc_dmat, r->vr_map, r->vr_mbuf,
+ BUS_DMA_NOWAIT)) {
+ m_freem(r->vr_mbuf);
return (ENOBUFS);
}
@@ -1558,7 +1559,6 @@ vr_alloc_mbuf(struct vr_softc *sc, struc
BUS_DMASYNC_PREREAD);
/* Reinitialize the RX descriptor */
- r->vr_mbuf = m;
d = r->vr_ptr;
d->vr_data = htole32(r->vr_map->dm_segs[0].ds_addr);
d->vr_ctl = htole32(VR_RXCTL | VR_RXLEN);
Index: if_vrreg.h
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_vrreg.h,v
retrieving revision 1.27
diff -u -p -r1.27 if_vrreg.h
--- if_vrreg.h 18 Jun 2009 17:48:15 -0000 1.27
+++ if_vrreg.h 13 Nov 2010 13:04:27 -0000
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_vrreg.h,v 1.27 2009/06/18 17:48:15 claudio Exp $ */
+/* $OpenBSD: if_vrreg.h,v 1.26 2009/05/12 13:30:56 sthen Exp $ */
/*
* Copyright (c) 1997, 1998
@@ -435,9 +435,7 @@ struct vr_chain_data {
struct vr_chain_onefrag vr_rx_chain[VR_RX_LIST_CNT];
struct vr_chain vr_tx_chain[VR_TX_LIST_CNT];
- struct vr_chain_onefrag *vr_rx_cons;
- struct vr_chain_onefrag *vr_rx_prod;
- int vr_rx_cnt;
+ struct vr_chain_onefrag *vr_rx_head;
struct vr_chain *vr_tx_cons;
struct vr_chain *vr_tx_prod;