Le 25/03/2013 05:59, Brad Smith a écrit :
On Sun, Mar 24, 2013 at 03:46:38PM +0100, Com??te wrote:
Hello,
i own a Shuttle XS35v2 and actually run OpenBSD 5.2 amd64 (SMP) on
it. I run OpenBSD on this hardware since 4.9 and i always
encountered the following problem, sorry for the late report it took
me some time to identify it:
The NIC uses the jme driver which run in a kernel panic each time i
upload data from the XS35v2 to any other machine with a transfer
rate above 7 Mbits/s (XS35v2 -----> other PC). No problem at all
when downloading.
I made some tests that you can follow to easily reproduce the crash:
Please test the following diff that should fix the obvious bug.
Index: if_jme.c
===================================================================
RCS file: /home/cvs/src/sys/dev/pci/if_jme.c,v
retrieving revision 1.29
diff -u -p -r1.29 if_jme.c
--- if_jme.c 29 Nov 2012 21:10:32 -0000 1.29
+++ if_jme.c 25 Mar 2013 04:54:01 -0000
@@ -1058,48 +1058,31 @@ jme_encap(struct jme_softc *sc, struct m
struct jme_txdesc *txd;
struct jme_desc *desc;
struct mbuf *m;
- int maxsegs;
int error, i, prod;
uint32_t cflags;
prod = sc->jme_cdata.jme_tx_prod;
txd = &sc->jme_cdata.jme_txdesc[prod];
- maxsegs = (JME_TX_RING_CNT - sc->jme_cdata.jme_tx_cnt) -
- (JME_TXD_RSVD + 1);
- if (maxsegs > JME_MAXTXSEGS)
- maxsegs = JME_MAXTXSEGS;
- if (maxsegs < (sc->jme_txd_spare - 1))
- panic("%s: not enough segments %d", sc->sc_dev.dv_xname,
- maxsegs);
-
error = bus_dmamap_load_mbuf(sc->sc_dmat, txd->tx_dmamap,
*m_head, BUS_DMA_NOWAIT);
+ if (error != 0 && error != EFBIG)
+ goto drop;
if (error != 0) {
- bus_dmamap_unload(sc->sc_dmat, txd->tx_dmamap);
- error = EFBIG;
- }
- if (error == EFBIG) {
if (m_defrag(*m_head, M_DONTWAIT)) {
- printf("%s: can't defrag TX mbuf\n",
- sc->sc_dev.dv_xname);
- m_freem(*m_head);
- *m_head = NULL;
- return (ENOBUFS);
+ error = ENOBUFS;
+ goto drop;
}
- error = bus_dmamap_load_mbuf(sc->sc_dmat,
- txd->tx_dmamap, *m_head,
- BUS_DMA_NOWAIT);
- if (error != 0) {
- printf("%s: could not load defragged TX mbuf\n",
- sc->sc_dev.dv_xname);
- m_freem(*m_head);
- *m_head = NULL;
- return (error);
- }
- } else if (error) {
- printf("%s: could not load TX mbuf\n", sc->sc_dev.dv_xname);
- return (error);
+ error = bus_dmamap_load_mbuf(sc->sc_dmat, txd->tx_dmamap,
+ *m_head, BUS_DMA_NOWAIT);
+ if (error != 0)
+ goto drop;
+ }
+
+ if (sc->jme_cdata.jme_tx_cnt + txd->tx_dmamap->dm_nsegs +
+ 1 > JME_TX_RING_CNT - 1) {
+ bus_dmamap_unload(sc->sc_dmat, txd->tx_dmamap);
+ return (ENOBUFS);
}
m = *m_head;
@@ -1127,7 +1110,6 @@ jme_encap(struct jme_softc *sc, struct m
desc->addr_hi = htole32(m->m_pkthdr.len);
desc->addr_lo = 0;
sc->jme_cdata.jme_tx_cnt++;
- KASSERT(sc->jme_cdata.jme_tx_cnt < JME_TX_RING_CNT - JME_TXD_RSVD);
JME_DESC_INC(prod, JME_TX_RING_CNT);
for (i = 0; i < txd->tx_dmamap->dm_nsegs; i++) {
desc = &sc->jme_rdata.jme_tx_ring[prod];
@@ -1137,10 +1119,7 @@ jme_encap(struct jme_softc *sc, struct m
htole32(JME_ADDR_HI(txd->tx_dmamap->dm_segs[i].ds_addr));
desc->addr_lo =
htole32(JME_ADDR_LO(txd->tx_dmamap->dm_segs[i].ds_addr));
-
sc->jme_cdata.jme_tx_cnt++;
- KASSERT(sc->jme_cdata.jme_tx_cnt <=
- JME_TX_RING_CNT - JME_TXD_RSVD);
JME_DESC_INC(prod, JME_TX_RING_CNT);
}
@@ -1163,6 +1142,11 @@ jme_encap(struct jme_softc *sc, struct m
sc->jme_cdata.jme_tx_ring_map->dm_mapsize,
BUS_DMASYNC_PREWRITE);
return (0);
+
+ drop:
+ m_freem(*m_head);
+ *m_head = NULL;
+ return (error);
}
void
@@ -1204,13 +1188,13 @@ jme_start(struct ifnet *ifp)
* for the NIC to drain the ring.
*/
if (jme_encap(sc, &m_head)) {
- if (m_head == NULL) {
+ if (m_head == NULL)
ifp->if_oerrors++;
- break;
- }
- ifp->if_flags |= IFF_OACTIVE;
+ else
+ ifp->if_flags |= IFF_OACTIVE;
break;
}
+
enq++;
#if NBPFILTER > 0
Thanks a lot ! It works like a charm now :)
Thanks again