diff options
author | Bill Paul <wpaul@FreeBSD.org> | 1999-01-16 06:19:38 +0000 |
---|---|---|
committer | Bill Paul <wpaul@FreeBSD.org> | 1999-01-16 06:19:38 +0000 |
commit | 51b875b355d9a9c99b08fed043b6cdbd889f8000 (patch) | |
tree | 3c80b9b35d66bbbabbb01227d9360d6975ca24bd /sys/pci/if_ax.c | |
parent | 54e609ba5ccfd9d9a7abbe2fbda45ed1a7581d7a (diff) | |
download | src-51b875b355d9a9c99b08fed043b6cdbd889f8000.tar.gz src-51b875b355d9a9c99b08fed043b6cdbd889f8000.zip |
Fix some stability problems:
- Normally, the driver allocates an mbuf cluster for each receive
descriptor. This is because we have to be prepared to accomodate up to
1500 bytes (a cluster buffer can hold up to 2K). However, using up a
whole cluster buffer for a tiny packet is a bit of a waste. Also,
it seems to me that sometimes mbufs will linger in the kernel for
a while after being passed out of the driver, which means we might
drain the mbuf cluster pool. The cluster pool is smaller than the
mbuf pool in general, so we do the following: if the packet is less
that MINCLSIZE bytes, then we copy it into a small mbuf chain and
leave the mbuf cluster in place for another go-round. This saves
mbuf clusters in some cases while still allowing them to be used
for heavy traffic exchanges with lots of full-sized frames.
- The transmit descriptor has a bit in the control word which allows
the driver to request that a 'TX OK' interrupt be generated when
a frame has been completed. Sometimes, a frame can be fragmented
across several descriptors. The manual for the real DEC 21140A says
that if this happens, the 'TX interrupt request' bit is only valid
in the descriptor of the last fragment. With the ASIX chip, it seems
the 'TX interrupt request' bit is only valid in the descriptor of
the _first_ fragment. Actually, the manual contains conflicting
information, but I think it's supposed to be the first fragment.
To play it safe, set the bit in both the first and last fragment to
be sure that we get a TX OK interrupt. Without this fix, the driver
can sometimes be late in releasing mbufs from the transmit queue
after transmission.
Notes
Notes:
svn path=/head/; revision=42717
Diffstat (limited to 'sys/pci/if_ax.c')
-rw-r--r-- | sys/pci/if_ax.c | 31 |
1 files changed, 22 insertions, 9 deletions
diff --git a/sys/pci/if_ax.c b/sys/pci/if_ax.c index 42463bb20a2b..05a556b109c2 100644 --- a/sys/pci/if_ax.c +++ b/sys/pci/if_ax.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_ax.c,v 1.6 1999/01/08 19:40:59 wpaul Exp $ + * $Id: if_ax.c,v 1.7 1999/01/16 01:23:56 wpaul Exp $ */ /* @@ -87,7 +87,7 @@ #ifndef lint static const char rcsid[] = - "$Id: if_ax.c,v 1.6 1999/01/08 19:40:59 wpaul Exp $"; + "$Id: if_ax.c,v 1.7 1999/01/16 01:23:56 wpaul Exp $"; #endif /* @@ -1446,6 +1446,17 @@ static void ax_rxeof(sc) total_len -= ETHER_CRC_LEN; + if (total_len < MINCLSIZE) { + m = m_devget(mtod(cur_rx->ax_mbuf, char *), + total_len, 0, ifp, NULL); + cur_rx->ax_ptr->ax_status = AX_RXSTAT; + cur_rx->ax_ptr->ax_ctl = (MCLBYTES - 1); + if (m == NULL) { + ifp->if_ierrors++; + continue; + } + } else { + m = cur_rx->ax_mbuf; /* * Try to conjure up a new mbuf cluster. If that * fails, it means we have an out of memory condition and @@ -1453,17 +1464,18 @@ static void ax_rxeof(sc) * result in a lost packet, but there's little else we * can do in this situation. */ - if (ax_newbuf(sc, cur_rx) == ENOBUFS) { - ifp->if_ierrors++; - cur_rx->ax_ptr->ax_status = AX_RXSTAT; - cur_rx->ax_ptr->ax_ctl = (MCLBYTES - 1); - continue; + if (ax_newbuf(sc, cur_rx) == ENOBUFS) { + ifp->if_ierrors++; + cur_rx->ax_ptr->ax_status = AX_RXSTAT; + cur_rx->ax_ptr->ax_ctl = (MCLBYTES - 1); + continue; + } + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = m->m_len = total_len; } ifp->if_ipackets++; eh = mtod(m, struct ether_header *); - m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = m->m_len = total_len; #if NBPFILTER > 0 /* * Handle BPF listeners. Let the BPF user see the packet, but @@ -1746,6 +1758,7 @@ static int ax_encap(sc, c, m_head) c->ax_mbuf = m_head; c->ax_lastdesc = frag - 1; AX_TXCTL(c) |= AX_TXCTL_LASTFRAG|AX_TXCTL_FINT; + c->ax_ptr->ax_frag[0].ax_ctl |= AX_TXCTL_FINT; AX_TXNEXT(c) = vtophys(&c->ax_nextdesc->ax_ptr->ax_frag[0]); return(0); } |