jmarin@embedtronics.fi wrote:How about the attached patch? (though I can't test it on so heavy load) --- Izumi Tsutsui Index: if_nfe.c =================================================================== RCS file: /cvsroot/src/sys/dev/pci/if_nfe.c,v retrieving revision 1.13 diff -u -r1.13 if_nfe.c --- if_nfe.c 9 Jan 2007 10:29:27 -0000 1.13 +++ if_nfe.c 25 Jan 2007 14:59:48 -0000 @@ -490,36 +490,50 @@ struct nfe_softc *sc = arg; struct ifnet *ifp = &sc->sc_ethercom.ec_if; uint32_t r; + int handled; - if ((r = NFE_READ(sc, NFE_IRQ_STATUS)) == 0) - return 0; /* not for us */ - NFE_WRITE(sc, NFE_IRQ_STATUS, r); + if ((ifp->if_flags & IFF_UP) == 0) + return 0; - DPRINTFN(5, ("nfe_intr: interrupt register %x\n", r)); + handled = 0; NFE_WRITE(sc, NFE_IRQ_MASK, 0); - if (r & NFE_IRQ_LINK) { - NFE_READ(sc, NFE_PHY_STATUS); - NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); - DPRINTF(("%s: link state changed\n", sc->sc_dev.dv_xname)); - } - - if (ifp->if_flags & IFF_RUNNING) { - /* check Rx ring */ - nfe_rxeof(sc); + for (;;) { + r = NFE_READ(sc, NFE_IRQ_STATUS); + if ((r & NFE_IRQ_WANTED) == 0) + break; - /* check Tx ring */ - nfe_txeof(sc); + NFE_WRITE(sc, NFE_IRQ_STATUS, r); + handled = 1; + DPRINTFN(5, ("nfe_intr: interrupt register %x\n", r)); + + if ((r & (NFE_IRQ_RXERR | NFE_IRQ_RX_NOBUF | NFE_IRQ_RX)) + != 0) { + /* check Rx ring */ + nfe_rxeof(sc); + } + + if ((r & (NFE_IRQ_TXERR | NFE_IRQ_TXERR2 | NFE_IRQ_TX_DONE)) + != 0) { + /* check Tx ring */ + nfe_txeof(sc); + } + + if ((r & NFE_IRQ_LINK) != 0) { + NFE_READ(sc, NFE_PHY_STATUS); + NFE_WRITE(sc, NFE_PHY_STATUS, 0xf); + DPRINTF(("%s: link state changed\n", + sc->sc_dev.dv_xname)); + } } NFE_WRITE(sc, NFE_IRQ_MASK, NFE_IRQ_WANTED); - if (ifp->if_flags & IFF_RUNNING && - !IF_IS_EMPTY(&ifp->if_snd)) + if (handled && !IF_IS_EMPTY(&ifp->if_snd)) nfe_start(ifp); - return 1; + return handled; } int @@ -692,32 +706,34 @@ struct mbuf *m, *mnew; bus_addr_t physaddr; uint16_t flags; - int error, len; + int error, len, i; desc32 = NULL; desc64 = NULL; - for (;;) { - data = &sc->rxq.data[sc->rxq.cur]; + for (i = sc->rxq.cur;; i = NFE_RX_NEXTDESC(i)) { + data = &sc->rxq.data[i]; if (sc->sc_flags & NFE_40BIT_ADDR) { - desc64 = &sc->rxq.desc64[sc->rxq.cur]; - nfe_rxdesc64_sync(sc, desc64, BUS_DMASYNC_POSTREAD); + desc64 = &sc->rxq.desc64[i]; + nfe_rxdesc64_sync(sc, desc64, + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); flags = le16toh(desc64->flags); len = le16toh(desc64->length) & 0x3fff; } else { - desc32 = &sc->rxq.desc32[sc->rxq.cur]; - nfe_rxdesc32_sync(sc, desc32, BUS_DMASYNC_POSTREAD); + desc32 = &sc->rxq.desc32[i]; + nfe_rxdesc32_sync(sc, desc32, + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); flags = le16toh(desc32->flags); len = le16toh(desc32->length) & 0x3fff; } - if (flags & NFE_RX_READY) + if ((flags & NFE_RX_READY) != 0) break; if ((sc->sc_flags & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) { - if (!(flags & NFE_RX_VALID_V1)) + if ((flags & NFE_RX_VALID_V1) == 0) goto skip; if ((flags & NFE_RX_FIXME_V1) == NFE_RX_FIXME_V1) { @@ -725,7 +741,7 @@ len--; /* fix buffer length */ } } else { - if (!(flags & NFE_RX_VALID_V2)) + if ((flags & NFE_RX_VALID_V2) == 0) goto skip; if ((flags & NFE_RX_FIXME_V2) == NFE_RX_FIXME_V2) { @@ -767,7 +783,7 @@ physaddr = jbuf->physaddr; } else { MCLGET(mnew, M_DONTWAIT); - if (!(mnew->m_flags & M_EXT)) { + if ((mnew->m_flags & M_EXT) == 0) { m_freem(mnew); ifp->if_ierrors++; goto skip; @@ -777,15 +793,14 @@ data->map->dm_mapsize, BUS_DMASYNC_POSTREAD); bus_dmamap_unload(sc->sc_dmat, data->map); - error = bus_dmamap_load(sc->sc_dmat, data->map, - mtod(mnew, void *), MCLBYTES, NULL, - BUS_DMA_READ | BUS_DMA_NOWAIT); + error = bus_dmamap_load_mbuf(sc->sc_dmat, data->map, + mnew, BUS_DMA_READ | BUS_DMA_NOWAIT); if (error != 0) { m_freem(mnew); /* try to reload the old mbuf */ - error = bus_dmamap_load(sc->sc_dmat, data->map, - mtod(data->m, void *), MCLBYTES, NULL, + error = bus_dmamap_load_mbuf(sc->sc_dmat, + data->map, data->m, BUS_DMA_READ | BUS_DMA_NOWAIT); if (error != 0) { /* very unlikely that it will fail.. */ @@ -852,20 +867,23 @@ desc32->physaddr = htole32(physaddr); } -skip: if (sc->sc_flags & NFE_40BIT_ADDR) { + skip: + if (sc->sc_flags & NFE_40BIT_ADDR) { desc64->length = htole16(sc->rxq.bufsz); desc64->flags = htole16(NFE_RX_READY); - nfe_rxdesc64_sync(sc, desc64, BUS_DMASYNC_PREWRITE); + nfe_rxdesc64_sync(sc, desc64, + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); } else { desc32->length = htole16(sc->rxq.bufsz); desc32->flags = htole16(NFE_RX_READY); - nfe_rxdesc32_sync(sc, desc32, BUS_DMASYNC_PREWRITE); + nfe_rxdesc32_sync(sc, desc32, + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); } - - sc->rxq.cur = (sc->rxq.cur + 1) % NFE_RX_RING_COUNT; } + /* update current RX pointer */ + sc->rxq.cur = i; } void @@ -875,29 +893,35 @@ struct nfe_desc32 *desc32; struct nfe_desc64 *desc64; struct nfe_tx_data *data = NULL; + int i; uint16_t flags; - while (sc->txq.next != sc->txq.cur) { + for (i = sc->txq.next; + sc->txq.queued > 0; + i = NFE_TX_NEXTDESC(i), sc->txq.queued--) { if (sc->sc_flags & NFE_40BIT_ADDR) { - desc64 = &sc->txq.desc64[sc->txq.next]; - nfe_txdesc64_sync(sc, desc64, BUS_DMASYNC_POSTREAD); + desc64 = &sc->txq.desc64[i]; + nfe_txdesc64_sync(sc, desc64, + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); flags = le16toh(desc64->flags); } else { - desc32 = &sc->txq.desc32[sc->txq.next]; - nfe_txdesc32_sync(sc, desc32, BUS_DMASYNC_POSTREAD); + desc32 = &sc->txq.desc32[i]; + nfe_txdesc32_sync(sc, desc32, + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); flags = le16toh(desc32->flags); } - if (flags & NFE_TX_VALID) + if ((flags & NFE_TX_VALID) != 0) break; - data = &sc->txq.data[sc->txq.next]; + data = &sc->txq.data[i]; if ((sc->sc_flags & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) { - if (!(flags & NFE_TX_LASTFRAG_V1) && data->m == NULL) - goto skip; + if ((flags & NFE_TX_LASTFRAG_V1) == 0 && + data->m == NULL) + continue; if ((flags & NFE_TX_ERROR_V1) != 0) { printf("%s: tx v1 error 0x%04x\n", @@ -906,8 +930,9 @@ } else ifp->if_opackets++; } else { - if (!(flags & NFE_TX_LASTFRAG_V2) && data->m == NULL) - goto skip; + if ((flags & NFE_TX_LASTFRAG_V2) == 0 && + data->m == NULL) + continue; if ((flags & NFE_TX_ERROR_V2) != 0) { printf("%s: tx v2 error 0x%04x\n", @@ -920,7 +945,7 @@ if (data->m == NULL) { /* should not get there */ printf("%s: last fragment bit w/o associated mbuf!\n", sc->sc_dev.dv_xname); - goto skip; + continue; } /* last fragment of the mbuf chain transmitted */ @@ -929,16 +954,18 @@ bus_dmamap_unload(sc->sc_dmat, data->active); m_freem(data->m); data->m = NULL; + } - ifp->if_timer = 0; + sc->txq.next = i; -skip: sc->txq.queued--; - sc->txq.next = (sc->txq.next + 1) % NFE_TX_RING_COUNT; + if (sc->txq.queued < NFE_TX_RING_COUNT) { + /* at least one slot freed */ + ifp->if_flags &= ~IFF_OACTIVE; } - if (data != NULL) { /* at least one slot freed */ - ifp->if_flags &= ~IFF_OACTIVE; - nfe_start(ifp); + if (sc->txq.queued == 0) { + /* all queued packets are sent */ + ifp->if_timer = 0; } } @@ -1019,7 +1046,7 @@ flags |= NFE_TX_VALID; sc->txq.queued++; - sc->txq.cur = (sc->txq.cur + 1) % NFE_TX_RING_COUNT; + sc->txq.cur = NFE_TX_NEXTDESC(sc->txq.cur); } /* the whole mbuf chain has been setup */ @@ -1064,7 +1091,7 @@ nfe_start(struct ifnet *ifp) { struct nfe_softc *sc = ifp->if_softc; - int old = sc->txq.cur; + int old = sc->txq.queued; struct mbuf *m0; for (;;) { @@ -1085,21 +1112,23 @@ bpf_mtap(ifp->if_bpf, m0); #endif } - if (sc->txq.cur == old) /* nothing sent */ - return; - if (sc->sc_flags & NFE_40BIT_ADDR) - nfe_txdesc64_rsync(sc, old, sc->txq.cur, BUS_DMASYNC_PREWRITE); - else - nfe_txdesc32_rsync(sc, old, sc->txq.cur, BUS_DMASYNC_PREWRITE); - - /* kick Tx */ - NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_KICKTX | sc->rxtxctl); + if (sc->txq.queued != old) { + /* packets are queued */ + if (sc->sc_flags & NFE_40BIT_ADDR) + nfe_txdesc64_rsync(sc, old, sc->txq.cur, + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + else + nfe_txdesc32_rsync(sc, old, sc->txq.cur, + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + /* kick Tx */ + NFE_WRITE(sc, NFE_RXTX_CTL, NFE_RXTX_KICKTX | sc->rxtxctl); - /* - * Set a timeout in case the chip goes out to lunch. - */ - ifp->if_timer = 5; + /* + * Set a timeout in case the chip goes out to lunch. + */ + ifp->if_timer = 5; + } } void Index: if_nfereg.h =================================================================== RCS file: /cvsroot/src/sys/dev/pci/if_nfereg.h,v retrieving revision 1.3 diff -u -r1.3 if_nfereg.h --- if_nfereg.h 9 Jan 2007 10:29:27 -0000 1.3 +++ if_nfereg.h 25 Jan 2007 14:59:48 -0000 @@ -22,6 +22,9 @@ #define NFE_RX_RING_COUNT 128 #define NFE_TX_RING_COUNT 64 +#define NFE_RX_NEXTDESC(x) (((x) + 1) & (NFE_RX_RING_COUNT - 1)) +#define NFE_TX_NEXTDESC(x) (((x) + 1) & (NFE_TX_RING_COUNT - 1)) + #define ETHER_ALIGN 2 #define NFE_JBYTES (ETHER_MAX_LEN_JUMBO + ETHER_ALIGN) #define NFE_JPOOL_COUNT (NFE_RX_RING_COUNT + 64)
| Andrea Arcangeli | [PATCH 00 of 12] mmu notifier #v13 |
| Eric W. Biederman | Remaining straight forward kthread API conversions... |
| Eric Paris | Re: [malware-list] [RFC 0/5] [TALPA] Intro to a linux interface for on access scan... |
| Trond Myklebust | Re: Announce: Linux-next (Or Andrew's dream :-)) |
git: | |
| Gerrit Renker | [PATCH 0/37] dccp: Feature negotiation - last call for comments |
| David Miller | [GIT]: Networking |
| Herbert Xu | Re: [PATCH] pkt_sched: Destroy gen estimators under rtnl_lock(). |
| Alexey Dobriyan | [PATCH 04/33] Fix {ip,6}_route_me_harder() in netns |
