Fix bug that can cause transmit corruption. There are actually two 'rings'

in the transmit code: the TX descriptor ring, and a 'shadow' ring of mbuf
pointers, one for each TX descriptor. When transmitting a packet that
consists of several fragments in an mbuf chain, we link each fragment
to a descriptor in the TX ring, but we only save a pointer to the mbuf
chain. This pointer is saved in the shadow ring entry which corresponds
to the first fragment in the packet. Later, ti_txeof() can release the
whole chain with a single m_freem() call. (We need the second ring to
keep track of the virtual addresses of the mbuf chains.)

The problem with this is that the Tigon isn't actually through with the
mbuf chain until it reaches the last fragment (which has the TI_BDFLAG_END
bit set), however the current scheme releases the mbuf chain as soon as
the first fragment is consumed. This is wrong, since the mbufs can then
be yanked out from under the Tigon and modified before the other fragments
can be transmitted.

The fix is to make a one line change to ti_encap() so that it saves the
mbuf chain pointer in the shadow ring entry that corresponds to the last
fragment in TX ring instead of the first. This prevents the mbufs from
being released until the last fragment is transmitted.

Painstakingly diagnosed and fixed by: Robert Picco <picco@mail.wevinc.com>
Brought to my attention by: dg
This commit is contained in:
Bill Paul 1999-05-24 14:56:55 +00:00
parent e142fadecb
commit 497760a16a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=47458
2 changed files with 6 additions and 6 deletions

View File

@ -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_ti.c,v 1.4 1999/04/29 16:27:51 wpaul Exp $
* $Id: if_ti.c,v 1.5 1999/05/09 17:07:00 peter Exp $
*/
/*
@ -128,7 +128,7 @@
#if !defined(lint)
static const char rcsid[] =
"$Id: if_ti.c,v 1.4 1999/04/29 16:27:51 wpaul Exp $";
"$Id: if_ti.c,v 1.5 1999/05/09 17:07:00 peter Exp $";
#endif
/*
@ -2061,7 +2061,7 @@ static int ti_encap(sc, m_head, txidx)
TI_BDFLAG_END;
else
sc->ti_rdata->ti_tx_ring[cur].ti_flags |= TI_BDFLAG_END;
sc->ti_cdata.ti_tx_chain[*txidx] = m_head;
sc->ti_cdata.ti_tx_chain[cur] = m_head;
*txidx = frag;

View File

@ -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_ti.c,v 1.4 1999/04/29 16:27:51 wpaul Exp $
* $Id: if_ti.c,v 1.5 1999/05/09 17:07:00 peter Exp $
*/
/*
@ -128,7 +128,7 @@
#if !defined(lint)
static const char rcsid[] =
"$Id: if_ti.c,v 1.4 1999/04/29 16:27:51 wpaul Exp $";
"$Id: if_ti.c,v 1.5 1999/05/09 17:07:00 peter Exp $";
#endif
/*
@ -2061,7 +2061,7 @@ static int ti_encap(sc, m_head, txidx)
TI_BDFLAG_END;
else
sc->ti_rdata->ti_tx_ring[cur].ti_flags |= TI_BDFLAG_END;
sc->ti_cdata.ti_tx_chain[*txidx] = m_head;
sc->ti_cdata.ti_tx_chain[cur] = m_head;
*txidx = frag;