Pull some bge_encap() fixes from OpenBSD:

> - Move TX ring full sanity check further up and check the number of DMA
> segments from the DMA map, instead of counting the DMA segments in the
> for loop and breaking out later.
> - Unload the DMA map if encountering an error condition.
This commit is contained in:
tsutsui 2006-11-26 02:40:10 +00:00
parent cc80189e88
commit fc28f9749e
1 changed files with 21 additions and 17 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_bge.c,v 1.117 2006/11/25 13:31:00 tsutsui Exp $ */
/* $NetBSD: if_bge.c,v 1.118 2006/11/26 02:40:10 tsutsui Exp $ */
/*
* Copyright (c) 2001 Wind River Systems
@ -79,7 +79,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.117 2006/11/25 13:31:00 tsutsui Exp $");
__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.118 2006/11/26 02:40:10 tsutsui Exp $");
#include "bpfilter.h"
#include "vlan.h"
@ -3429,7 +3429,7 @@ static int
bge_encap(struct bge_softc *sc, struct mbuf *m_head, u_int32_t *txidx)
{
struct bge_tx_bd *f = NULL;
u_int32_t frag, cur, cnt = 0;
u_int32_t frag, cur;
u_int16_t csum_flags = 0;
u_int16_t txbd_tso_flags = 0;
struct txdmamap_pool_entry *dma;
@ -3627,6 +3627,16 @@ doit:
if (error) {
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)) {
BGE_TSO_PRINTF(("%s: "
" dmamap_load_mbuf too close to ring wrap\n",
sc->bge_dev.dv_xname));
goto fail_unload;
}
mtag = sc->ethercom.ec_nvlans ?
m_tag_find(m_head, PACKET_TAG_VLAN, NULL) : NULL;
@ -3667,25 +3677,14 @@ doit:
} else {
f->bge_vlan_tag = 0;
}
/*
* Sanity check: avoid coming within 16 descriptors
* of the end of the ring.
*/
if ((BGE_TX_RING_CNT - (sc->bge_txcnt + cnt)) < 16) {
BGE_TSO_PRINTF(("%s: "
" dmamap_load_mbuf too close to ring wrap\n",
sc->bge_dev.dv_xname));
return(ENOBUFS);
}
cur = frag;
BGE_INC(frag, BGE_TX_RING_CNT);
cnt++;
}
if (i < dmamap->dm_nsegs) {
BGE_TSO_PRINTF(("%s: reached %d < dm_nsegs %d\n",
sc->bge_dev.dv_xname, i, dmamap->dm_nsegs));
return ENOBUFS;
goto fail_unload;
}
bus_dmamap_sync(sc->bge_dmatag, dmamap, 0, dmamap->dm_mapsize,
@ -3695,18 +3694,23 @@ doit:
BGE_TSO_PRINTF(("%s: frag %d = wrapped id %d?\n",
sc->bge_dev.dv_xname, frag, sc->bge_tx_saved_considx));
return(ENOBUFS);
goto fail_unload;
}
sc->bge_rdata->bge_tx_ring[cur].bge_flags |= BGE_TXBDFLAG_END;
sc->bge_cdata.bge_tx_chain[cur] = m_head;
SLIST_REMOVE_HEAD(&sc->txdma_list, link);
sc->txdma[cur] = dma;
sc->bge_txcnt += cnt;
sc->bge_txcnt += dmamap->dm_nsegs;
*txidx = frag;
return(0);
fail_unload:
bus_dmamap_unload(sc->bge_dmatag, dmamap);
return ENOBUFS;
}
/*