summaryrefslogtreecommitdiffstats
path: root/sys/pci
diff options
context:
space:
mode:
authorsilby <silby@FreeBSD.org>2003-04-09 02:21:54 +0000
committersilby <silby@FreeBSD.org>2003-04-09 02:21:54 +0000
commit979ed3a82ea34d46466c4d6f755b15b85df66f15 (patch)
treea60b1810b7420f57f1b635330dfe0941413a6e25 /sys/pci
parent339cdd9fae72c60095061f96c9d8ad19e8267275 (diff)
downloadFreeBSD-src-979ed3a82ea34d46466c4d6f755b15b85df66f15.zip
FreeBSD-src-979ed3a82ea34d46466c4d6f755b15b85df66f15.tar.gz
Fix if_vr's handling of vr_encap failures. 3 parts:
- Don't bother setting OACTIVE when the descriptors are all full or there's a vr_encap failure, it doesn't help anything. - Correctly roll back on the descriptor list after a failure so as not to corrupt the list. - Add a missing VR_UNLOCK(). Without these changes, vr_encap failure (which is assured during a low mbuf situation) would result in the card locking until the watchdog could fire. MFC after: 1 week
Diffstat (limited to 'sys/pci')
-rw-r--r--sys/pci/if_vr.c19
1 files changed, 9 insertions, 10 deletions
diff --git a/sys/pci/if_vr.c b/sys/pci/if_vr.c
index f220190..ad0ed09 100644
--- a/sys/pci/if_vr.c
+++ b/sys/pci/if_vr.c
@@ -1414,7 +1414,6 @@ vr_encap(sc, c, m_head)
m_new = m_defrag(m_head, M_DONTWAIT);
if (m_new == NULL) {
- printf("vr%d: no memory for tx list\n", sc->vr_unit);
return(1);
}
@@ -1456,22 +1455,18 @@ vr_start(ifp)
{
struct vr_softc *sc;
struct mbuf *m_head = NULL;
- struct vr_chain *cur_tx = NULL, *start_tx;
+ struct vr_chain *cur_tx = NULL, *start_tx, *prev_tx;
sc = ifp->if_softc;
VR_LOCK(sc);
- if (ifp->if_flags & IFF_OACTIVE) {
- VR_UNLOCK(sc);
- return;
- }
/*
* Check for an available queue slot. If there are none,
* punt.
*/
if (sc->vr_cdata.vr_tx_free->vr_mbuf != NULL) {
- ifp->if_flags |= IFF_OACTIVE;
+ VR_UNLOCK(sc);
return;
}
@@ -1483,14 +1478,16 @@ vr_start(ifp)
break;
/* Pick a descriptor off the free list. */
+ prev_tx = cur_tx;
cur_tx = sc->vr_cdata.vr_tx_free;
sc->vr_cdata.vr_tx_free = cur_tx->vr_nextdesc;
/* Pack the data into the descriptor. */
if (vr_encap(sc, cur_tx, m_head)) {
+ /* Rollback, send what we were able to encap. */
IF_PREPEND(&ifp->if_snd, m_head);
- ifp->if_flags |= IFF_OACTIVE;
- cur_tx = NULL;
+ sc->vr_cdata.vr_tx_free = cur_tx;
+ cur_tx = prev_tx;
break;
}
@@ -1504,7 +1501,6 @@ vr_start(ifp)
BPF_MTAP(ifp, cur_tx->vr_mbuf);
VR_TXOWN(cur_tx) = VR_TXSTAT_OWN;
- VR_SETBIT16(sc, VR_COMMAND, /*VR_CMD_TX_ON|*/VR_CMD_TX_GO);
}
/*
@@ -1519,6 +1515,9 @@ vr_start(ifp)
if (sc->vr_cdata.vr_tx_head == NULL)
sc->vr_cdata.vr_tx_head = start_tx;
+
+ /* Tell the chip to start transmitting. */
+ VR_SETBIT16(sc, VR_COMMAND, /*VR_CMD_TX_ON|*/VR_CMD_TX_GO);
/*
* Set a timeout in case the chip goes out to lunch.
OpenPOWER on IntegriCloud