summaryrefslogtreecommitdiff
path: root/sys/dev/pci
diff options
context:
space:
mode:
authorChristian Weisgerber <naddy@cvs.openbsd.org>2010-03-30 14:24:04 +0000
committerChristian Weisgerber <naddy@cvs.openbsd.org>2010-03-30 14:24:04 +0000
commitc7b5e00f3df9ef5fdd2f89df09a8d34291ecf39a (patch)
treec6c72ddcc8c09d0af1f5ceacd9d00d2165915c57 /sys/dev/pci
parent9e02bd18164142627f11f1bb122a2a423d13bd6d (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.c22
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;