summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2013-12-07 07:22:38 +0000
committerBrad Smith <brad@cvs.openbsd.org>2013-12-07 07:22:38 +0000
commit22470cbb72639e25878645fe5c1f85b7ec9db378 (patch)
treedc7b3aae45d1a77db3a9969ab80580bbde86f9d6 /sys/dev
parent0f6089ea08b2ae397a923a78783e135b1df953f8 (diff)
Some fixes for jme_encap()..
- Remove the maximum DMA segments handling bits as it is unused between DragonFly and OpenBSD. - Fix error handling for bus_dmamap_load_mbuf() so as to not try unloading a DMA map that had not already been loaded. - Clean up the DMA chain defragmenting path to remove unwanted printfs and simplify things a bit. - Have jme_encap() check the number of mapped DMA segments against the TX ring to see if it'll fit as do most of the driver nowadays. - Remove the KASSERT's that shouldn't be there. - Simplify the dummy descriptor handling to be closer to the FreeBSD driver since unlike the DragonFly driver this originated from our driver always uses the 64-bit dummy descriptor. - If the ring was full make sure to IF_PREPEND() the packet back on the queue since it wasn't transmitted. Tested by myself, comete@daknet.org and vigdis+obsd@chown.me.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/pci/if_jme.c83
-rw-r--r--sys/dev/pci/if_jmevar.h4
2 files changed, 34 insertions, 53 deletions
diff --git a/sys/dev/pci/if_jme.c b/sys/dev/pci/if_jme.c
index c5f0e00d386..447029e6b1a 100644
--- a/sys/dev/pci/if_jme.c
+++ b/sys/dev/pci/if_jme.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_jme.c,v 1.32 2013/11/03 23:27:33 brad Exp $ */
+/* $OpenBSD: if_jme.c,v 1.33 2013/12/07 07:22:37 brad Exp $ */
/*-
* Copyright (c) 2008, Pyun YongHyeon <yongari@FreeBSD.org>
* All rights reserved.
@@ -1044,48 +1044,36 @@ jme_encap(struct jme_softc *sc, struct mbuf **m_head)
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 = 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);
+ error = ENOBUFS;
+ goto drop;
}
- } 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;
+ }
+
+ /*
+ * Check descriptor overrun. Leave one free descriptor.
+ * Since we always use 64bit address mode for transmitting,
+ * each Tx request requires one more dummy descriptor.
+ */
+ if (sc->jme_cdata.jme_tx_cnt + txd->tx_dmamap->dm_nsegs + JME_TXD_RSVD >
+ JME_TX_RING_CNT - JME_TXD_RSVD) {
+ bus_dmamap_unload(sc->sc_dmat, txd->tx_dmamap);
+ return (ENOBUFS);
}
m = *m_head;
@@ -1113,7 +1101,6 @@ jme_encap(struct jme_softc *sc, struct mbuf **m_head)
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];
@@ -1123,10 +1110,7 @@ jme_encap(struct jme_softc *sc, struct mbuf **m_head)
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);
}
@@ -1140,7 +1124,7 @@ jme_encap(struct jme_softc *sc, struct mbuf **m_head)
desc->flags |= htole32(JME_TD_OWN | JME_TD_INTR);
txd->tx_m = m;
- txd->tx_ndesc = txd->tx_dmamap->dm_nsegs + 1;
+ txd->tx_ndesc = txd->tx_dmamap->dm_nsegs + JME_TXD_RSVD;
/* Sync descriptors. */
bus_dmamap_sync(sc->sc_dmat, txd->tx_dmamap, 0,
@@ -1149,6 +1133,11 @@ jme_encap(struct jme_softc *sc, struct mbuf **m_head)
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
@@ -1174,7 +1163,7 @@ jme_start(struct ifnet *ifp)
* Check number of available TX descs, always
* leave JME_TXD_RSVD free TX descs.
*/
- if (sc->jme_cdata.jme_tx_cnt + sc->jme_txd_spare >
+ if (sc->jme_cdata.jme_tx_cnt + JME_TXD_RSVD >
JME_TX_RING_CNT - JME_TXD_RSVD) {
ifp->if_flags |= IFF_OACTIVE;
break;
@@ -1190,13 +1179,15 @@ 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;
+ else {
+ IF_PREPEND(&ifp->if_snd, m_head);
+ ifp->if_flags |= IFF_OACTIVE;
}
- ifp->if_flags |= IFF_OACTIVE;
break;
}
+
enq++;
#if NBPFILTER > 0
@@ -1528,7 +1519,7 @@ jme_txeof(struct jme_softc *sc)
if (sc->jme_cdata.jme_tx_cnt == 0)
ifp->if_timer = 0;
- if (sc->jme_cdata.jme_tx_cnt + sc->jme_txd_spare <=
+ if (sc->jme_cdata.jme_tx_cnt + JME_TXD_RSVD <=
JME_TX_RING_CNT - JME_TXD_RSVD)
ifp->if_flags &= ~IFF_OACTIVE;
@@ -1776,14 +1767,6 @@ jme_init(struct ifnet *ifp)
*/
jme_reset(sc);
- /*
- * Since we always use 64bit address mode for transmitting,
- * each Tx request requires one more dummy descriptor.
- */
- sc->jme_txd_spare =
- howmany(ifp->if_mtu + sizeof(struct ether_vlan_header), MCLBYTES) + 1;
- KASSERT(sc->jme_txd_spare >= 2);
-
/* Init descriptors. */
error = jme_init_rx_ring(sc);
if (error != 0) {
diff --git a/sys/dev/pci/if_jmevar.h b/sys/dev/pci/if_jmevar.h
index 3cb3811c539..2a15795137d 100644
--- a/sys/dev/pci/if_jmevar.h
+++ b/sys/dev/pci/if_jmevar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_jmevar.h,v 1.5 2009/01/10 15:33:05 kevlo Exp $ */
+/* $OpenBSD: if_jmevar.h,v 1.6 2013/12/07 07:22:37 brad Exp $ */
/*-
* Copyright (c) 2008, Pyun YongHyeon <yongari@FreeBSD.org>
* All rights reserved.
@@ -209,8 +209,6 @@ struct jme_softc {
uint32_t jme_txcsr;
uint32_t jme_rxcsr;
- int jme_txd_spare;
-
/*
* Sysctl variables
*/