Index: if_bge.c =================================================================== RCS file: /data/fbsd-cvs/ncvs/src/sys/dev/bge/if_bge.c,v retrieving revision 1.63 diff -u -r1.63 if_bge.c --- if_bge.c 13 Jan 2004 11:31:09 -0000 1.63 +++ if_bge.c 20 Jan 2004 14:49:47 -0000 @@ -2624,8 +2624,9 @@ bge_rxeof(sc) struct bge_softc *sc; { + struct mbuf *mqueue, *mqueue_tail; struct ifnet *ifp; - int stdcnt = 0, jumbocnt = 0; + int stdcnt = 0, jumbocnt = 0, queuecnt; BGE_LOCK_ASSERT(sc); @@ -2641,6 +2642,8 @@ BUS_DMASYNC_POSTREAD); } + mqueue = mqueue_tail = NULL; + queuecnt = 0; while(sc->bge_rx_saved_considx != sc->bge_ldata.bge_status_block->bge_idx[0].bge_rx_prod_idx) { struct bge_rx_bd *cur_rx; @@ -2741,9 +2744,27 @@ if (have_tag) VLAN_INPUT_TAG(ifp, m, vlan_tag, continue); - BGE_UNLOCK(sc); - (*ifp->if_input)(ifp, m); - BGE_LOCK(sc); + if (mqueue != NULL) { + mqueue_tail->m_nextpkt = m; + mqueue_tail = m; + } else + mqueue = mqueue_tail = m; + queuecnt++; + } + /* + * Do less work by defering delivery to the network stack and + * locking/unlocking only once per interrupt. XXX: Bound the + * size of queuecnt to some fixed value? Measure latency? + */ + if (mqueue != NULL) { + BGE_UNLOCK(sx); + while (mqueue != NULL) { + m = mqueue; + mqueue = mqueue->m_nextpkt; + (*ifp->if_input)(ifp, m); + queuecnt--; + } + BGE_LOCK(sx); } bus_dmamap_sync(sc->bge_cdata.bge_rx_return_ring_tag,