aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Paul <wpaul@FreeBSD.org>1998-08-31 15:26:09 +0000
committerBill Paul <wpaul@FreeBSD.org>1998-08-31 15:26:09 +0000
commitcdb5ef5fbad99341b6d7146c47bba039b34a4151 (patch)
tree9ca31fe889294c7d1f335658d4501239239fc66e
parent2d9dae457a6fa19977e767fa8cab3e54c5a029f3 (diff)
downloadsrc-cdb5ef5fbad99341b6d7146c47bba039b34a4151.tar.gz
src-cdb5ef5fbad99341b6d7146c47bba039b34a4151.zip
Fix handling of ENOBUFS condition. During reception, the filled mbuf
cluster from the RX descriptor is passed up to the higher layers and replaced with an empty buffer for the next time the descriptor comes up in the RX ring. The xl_newbuf() routine returns ENOBUFS if it can't obtain a new mbuf cluster, but this return value was being ignored. Now, if buffer allocation fails, we leave the old one in place and drop the packet. This is rude, but there's not much else that can be done in this situation. Without this, the driver can cause a panic if the system runs out of MBUF clusters. Now it will complain loudly, but it shouldn't cause a panic. Also added another pair of missing newlines to some printf()s.
Notes
Notes: svn path=/head/; revision=38697
-rw-r--r--sys/pci/if_xl.c39
1 files changed, 27 insertions, 12 deletions
diff --git a/sys/pci/if_xl.c b/sys/pci/if_xl.c
index 3d47c692f49f..a21a82c076f6 100644
--- a/sys/pci/if_xl.c
+++ b/sys/pci/if_xl.c
@@ -29,7 +29,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: if_xl.c,v 1.5 1998/08/24 17:51:38 wpaul Exp $
+ * $Id: if_xl.c,v 1.46 1998/08/31 15:10:22 wpaul Exp $
*/
/*
@@ -124,7 +124,7 @@
#ifndef lint
static char rcsid[] =
- "$Id: if_xl.c,v 1.5 1998/08/24 17:51:38 wpaul Exp $";
+ "$Id: if_xl.c,v 1.46 1998/08/31 15:10:22 wpaul Exp $";
#endif
/*
@@ -1635,7 +1635,8 @@ static int xl_list_rx_init(sc)
for (i = 0; i < XL_RX_LIST_CNT; i++) {
cd->xl_rx_chain[i].xl_ptr =
(struct xl_list_onefrag *)&ld->xl_rx_list[i];
- xl_newbuf(sc, &cd->xl_rx_chain[i]);
+ if (xl_newbuf(sc, &cd->xl_rx_chain[i]) == ENOBUFS)
+ return(ENOBUFS);
if (i == (XL_RX_LIST_CNT - 1)) {
cd->xl_rx_chain[i].xl_next = &cd->xl_rx_chain[0];
ld->xl_rx_list[i].xl_next =
@@ -1663,14 +1664,15 @@ static int xl_newbuf(sc, c)
MGETHDR(m_new, M_DONTWAIT, MT_DATA);
if (m_new == NULL) {
- printf("xl%d: no memory for rx list",
- sc->xl_unit);
+ printf("xl%d: no memory for rx list -- packet dropped!\n",
+ sc->xl_unit);
return(ENOBUFS);
}
MCLGET(m_new, M_DONTWAIT);
if (!(m_new->m_flags & M_EXT)) {
- printf("xl%d: no memory for rx list", sc->xl_unit);
+ printf("xl%d: no memory for rx list -- packet dropped!\n",
+ sc->xl_unit);
m_freem(m_new);
return(ENOBUFS);
}
@@ -1703,6 +1705,8 @@ again:
while((rxstat = sc->xl_cdata.xl_rx_head->xl_ptr->xl_status)) {
cur_rx = sc->xl_cdata.xl_rx_head;
+ sc->xl_cdata.xl_rx_head = cur_rx->xl_next;
+
/*
* If an error occurs, update stats, clear the
* status word and leave the mbuf cluster in place:
@@ -1712,7 +1716,6 @@ again:
if (rxstat & XL_RXSTAT_UP_ERROR) {
ifp->if_ierrors++;
cur_rx->xl_ptr->xl_status = 0;
- sc->xl_cdata.xl_rx_head = cur_rx->xl_next;
continue;
}
@@ -1726,15 +1729,25 @@ again:
sc->xl_unit);
ifp->if_ierrors++;
cur_rx->xl_ptr->xl_status = 0;
- sc->xl_cdata.xl_rx_head = cur_rx->xl_next;
continue;
}
/* No errors; receive the packet. */
- sc->xl_cdata.xl_rx_head = cur_rx->xl_next;
m = cur_rx->xl_mbuf;
total_len = cur_rx->xl_ptr->xl_status & XL_RXSTAT_LENMASK;
- xl_newbuf(sc, cur_rx);
+
+ /*
+ * Try to conjure up a new mbuf cluster. If that
+ * fails, it means we have an out of memory condition and
+ * should leave the buffer in place and continue. This will
+ * result in a lost packet, but there's little else we
+ * can do in this situation.
+ */
+ if (xl_newbuf(sc, cur_rx) == ENOBUFS) {
+ ifp->if_ierrors++;
+ cur_rx->xl_ptr->xl_status = 0;
+ continue;
+ }
eh = mtod(m, struct ether_header *);
m->m_pkthdr.rcvif = ifp;
@@ -2250,8 +2263,10 @@ static void xl_init(xsc)
xl_wait(sc);
/* Init circular RX list. */
- if (xl_list_rx_init(sc)) {
- printf("xl%d: failed to set up rx lists\n", sc->xl_unit);
+ if (xl_list_rx_init(sc) == ENOBUFS) {
+ printf("xl%d: initialization failed: no "
+ "memory for rx buffers\n", sc->xl_unit);
+ xl_stop(sc);
return;
}