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

Reply via email to