diff options
author | Christian Weisgerber <naddy@cvs.openbsd.org> | 2010-03-30 14:24:04 +0000 |
---|---|---|
committer | Christian Weisgerber <naddy@cvs.openbsd.org> | 2010-03-30 14:24:04 +0000 |
commit | c7b5e00f3df9ef5fdd2f89df09a8d34291ecf39a (patch) | |
tree | c6c72ddcc8c09d0af1f5ceacd9d00d2165915c57 /sys/dev/pci | |
parent | 9e02bd18164142627f11f1bb122a2a423d13bd6d (diff) |
Have bge_start check if there are less than 16 free send BDs and if not
set IFF_OACTIVE and try again later. Previously bge(4) reserved 16 send
BDs after loading DMA maps but the hardware only requires one reserved
send BD.
From FreeBSD, via Brad
Diffstat (limited to 'sys/dev/pci')
-rw-r--r-- | sys/dev/pci/if_bge.c | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/sys/dev/pci/if_bge.c b/sys/dev/pci/if_bge.c index 325235dfbf2..518509d11f7 100644 --- a/sys/dev/pci/if_bge.c +++ b/sys/dev/pci/if_bge.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bge.c,v 1.291 2010/01/10 00:07:40 naddy Exp $ */ +/* $OpenBSD: if_bge.c,v 1.292 2010/03/30 14:24:03 naddy Exp $ */ /* * Copyright (c) 2001 Wind River Systems @@ -3043,11 +3043,8 @@ doit: BUS_DMA_NOWAIT)) return (ENOBUFS); - /* - * Sanity check: avoid coming within 16 descriptors - * of the end of the ring. - */ - if (dmamap->dm_nsegs > (BGE_TX_RING_CNT - sc->bge_txcnt - 16)) + /* Check if we have enough free send BDs. */ + if (sc->bge_txcnt + dmamap->dm_nsegs >= BGE_TX_RING_CNT) goto fail_unload; for (i = 0; i < dmamap->dm_nsegs; i++) { @@ -3101,9 +3098,9 @@ void bge_start(struct ifnet *ifp) { struct bge_softc *sc; - struct mbuf *m_head = NULL; + struct mbuf *m_head; u_int32_t prodidx; - int pkts = 0; + int pkts; sc = ifp->if_softc; @@ -3111,12 +3108,15 @@ bge_start(struct ifnet *ifp) return; if (!BGE_STS_BIT(sc, BGE_STS_LINK)) return; - if (IFQ_IS_EMPTY(&ifp->if_snd)) - return; prodidx = sc->bge_tx_prodidx; - while (sc->bge_cdata.bge_tx_chain[prodidx] == NULL) { + for (pkts = 0; !IFQ_IS_EMPTY(&ifp->if_snd);) { + if (sc->bge_txcnt > BGE_TX_RING_CNT - 16) { + ifp->if_flags |= IFF_OACTIVE; + break; + } + IFQ_POLL(&ifp->if_snd, m_head); if (m_head == NULL) break; |