From 6ec31f009abffa75ab28b784d6e95e584a5391e7 Mon Sep 17 00:00:00 2001 From: Ruslan Ermilov Date: Fri, 2 Apr 2004 23:36:49 +0000 Subject: [PATCH] Performance tuning. Moved the RX ring resyncing code to ste_rxeoc(), and only run it if we were asked to POLL_AND_CHECK_STATUS, under DEVICE_POLLING. (This significantly reduces the CPU load.) Improved the RX ring resyncing code by re-checking if the head is still empty before doing resyncing. This mostly affects the DEVICE_POLLING mode, where we run this code periodically. We could start checking with an empty head (well, an empty ring even), and after doing a few iterations, the chip might write a few entries, including the head, and we would bogusly consider this case as requiring resyncing. On a test box, this reduced the number of resyncs done by a factor of 10. In ste_txeof(sc), only reset the watchdog timer to zero when the TX list is completely empty. Converted ste_tx_prev_idx to a pointer -- faster. Removed some bitrot. --- sys/pci/if_ste.c | 82 ++++++++++++++++++++++++--------------------- sys/pci/if_stereg.h | 4 +-- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/sys/pci/if_ste.c b/sys/pci/if_ste.c index 65d47dda3c45..90e28d753ee9 100644 --- a/sys/pci/if_ste.c +++ b/sys/pci/if_ste.c @@ -91,6 +91,7 @@ static int ste_attach (device_t); static int ste_detach (device_t); static void ste_init (void *); static void ste_intr (void *); +static void ste_rxeoc (struct ste_softc *); static void ste_rxeof (struct ste_softc *); static void ste_txeoc (struct ste_softc *); static void ste_txeof (struct ste_softc *); @@ -643,6 +644,8 @@ ste_poll(struct ifnet *ifp, enum poll_cmd cmd, int count) } sc->rxcycles = count; + if (cmd == POLL_AND_CHECK_STATUS) + ste_rxeoc(sc); ste_rxeof(sc); ste_txeof(sc); if (ifp->if_snd.ifq_head != NULL) @@ -708,8 +711,10 @@ ste_intr(xsc) if (!(status & STE_INTRS)) break; - if (status & STE_ISR_RX_DMADONE) + if (status & STE_ISR_RX_DMADONE) { + ste_rxeoc(sc); ste_rxeof(sc); + } if (status & STE_ISR_TX_DMADONE) ste_txeof(sc); @@ -746,6 +751,29 @@ ste_intr(xsc) return; } +static void +ste_rxeoc(struct ste_softc *sc) +{ + struct ste_chain_onefrag *cur_rx; + + STE_LOCK_ASSERT(sc); + + if (sc->ste_cdata.ste_rx_head->ste_ptr->ste_status == 0) { + cur_rx = sc->ste_cdata.ste_rx_head; + do { + cur_rx = cur_rx->ste_next; + /* If the ring is empty, just return. */ + if (cur_rx == sc->ste_cdata.ste_rx_head) + return; + } while (cur_rx->ste_ptr->ste_status == 0); + if (sc->ste_cdata.ste_rx_head->ste_ptr->ste_status == 0) { + /* We've fallen behind the chip: catch it. */ + sc->ste_cdata.ste_rx_head = cur_rx; + ++ste_rxsyncs; + } + } +} + /* * A frame has been uploaded: pass the resulting mbuf chain up to * the higher level protocols. @@ -764,19 +792,6 @@ ste_rxeof(sc) ifp = &sc->arpcom.ac_if; - if (sc->ste_cdata.ste_rx_head->ste_ptr->ste_status == 0) { - cur_rx = sc->ste_cdata.ste_rx_head; - do { - cur_rx = cur_rx->ste_next; - /* If the ring is empty, just return. */ - if (cur_rx == sc->ste_cdata.ste_rx_head) - return; - } while (cur_rx->ste_ptr->ste_status == 0); - /* We've fallen behind the chip: catch it. */ - sc->ste_cdata.ste_rx_head = cur_rx; - ++ste_rxsyncs; - }; - while((rxstat = sc->ste_cdata.ste_rx_head->ste_ptr->ste_status) & STE_RXSTAT_DMADONE) { #ifdef DEVICE_POLLING @@ -893,7 +908,7 @@ static void ste_txeof(sc) struct ste_softc *sc; { - struct ste_chain *cur_tx = NULL; + struct ste_chain *cur_tx; struct ifnet *ifp; int idx; @@ -906,24 +921,21 @@ ste_txeof(sc) if (!(cur_tx->ste_ptr->ste_ctl & STE_TXCTL_DMADONE)) break; - if (cur_tx->ste_mbuf != NULL) { - m_freem(cur_tx->ste_mbuf); - cur_tx->ste_mbuf = NULL; - } + m_freem(cur_tx->ste_mbuf); + cur_tx->ste_mbuf = NULL; ifp->if_opackets++; sc->ste_cdata.ste_tx_cnt--; STE_INC(idx, STE_TX_LIST_CNT); - ifp->if_timer = 0; } - sc->ste_cdata.ste_tx_cons = idx; - - if (cur_tx != NULL) + if (idx != sc->ste_cdata.ste_tx_cons) { + sc->ste_cdata.ste_tx_cons = idx; ifp->if_flags &= ~IFF_OACTIVE; - - return; + if (idx == sc->ste_cdata.ste_tx_prod) + ifp->if_timer = 0; + } } static void @@ -1284,12 +1296,6 @@ ste_init_tx_list(sc) else cd->ste_tx_chain[i].ste_next = &cd->ste_tx_chain[i + 1]; - if (i == 0) - cd->ste_tx_chain[i].ste_prev = - &cd->ste_tx_chain[STE_TX_LIST_CNT - 1]; - else - cd->ste_tx_chain[i].ste_prev = - &cd->ste_tx_chain[i - 1]; } cd->ste_tx_prod = 0; @@ -1379,7 +1385,7 @@ ste_init(xsc) STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_TXDMA_UNSTALL); STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_TXDMA_UNSTALL); ste_wait(sc); - sc->ste_tx_prev_idx=-1; + sc->ste_tx_prev = NULL; /* Enable receiver and transmitter */ CSR_WRITE_2(sc, STE_MACCTL0, 0); @@ -1610,7 +1616,7 @@ ste_start(ifp) { struct ste_softc *sc; struct mbuf *m_head = NULL; - struct ste_chain *cur_tx = NULL; + struct ste_chain *cur_tx; int idx; sc = ifp->if_softc; @@ -1646,7 +1652,7 @@ ste_start(ifp) cur_tx->ste_ptr->ste_next = 0; - if(sc->ste_tx_prev_idx < 0){ + if (sc->ste_tx_prev == NULL) { cur_tx->ste_ptr->ste_ctl = STE_TXCTL_DMAINTR | 1; /* Load address of the TX list */ STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_TXDMA_STALL); @@ -1662,12 +1668,11 @@ ste_start(ifp) ste_wait(sc); }else{ cur_tx->ste_ptr->ste_ctl = STE_TXCTL_DMAINTR | 1; - sc->ste_cdata.ste_tx_chain[ - sc->ste_tx_prev_idx].ste_ptr->ste_next + sc->ste_tx_prev->ste_ptr->ste_next = cur_tx->ste_phys; } - sc->ste_tx_prev_idx=idx; + sc->ste_tx_prev = cur_tx; /* * If there's a BPF listener, bounce a copy of this frame @@ -1678,8 +1683,8 @@ ste_start(ifp) STE_INC(idx, STE_TX_LIST_CNT); sc->ste_cdata.ste_tx_cnt++; ifp->if_timer = 5; - sc->ste_cdata.ste_tx_prod = idx; } + sc->ste_cdata.ste_tx_prod = idx; STE_UNLOCK(sc); @@ -1700,6 +1705,7 @@ ste_watchdog(ifp) ste_txeoc(sc); ste_txeof(sc); + ste_rxeoc(sc); ste_rxeof(sc); ste_reset(sc); ste_init(sc); diff --git a/sys/pci/if_stereg.h b/sys/pci/if_stereg.h index 0de4f78d8654..90350b4e3889 100644 --- a/sys/pci/if_stereg.h +++ b/sys/pci/if_stereg.h @@ -479,14 +479,12 @@ struct ste_type { struct ste_list_data { struct ste_desc_onefrag ste_rx_list[STE_RX_LIST_CNT]; struct ste_desc ste_tx_list[STE_TX_LIST_CNT]; - u_int8_t ste_pad[STE_MIN_FRAMELEN]; }; struct ste_chain { struct ste_desc *ste_ptr; struct mbuf *ste_mbuf; struct ste_chain *ste_next; - struct ste_chain *ste_prev; u_int32_t ste_phys; }; @@ -520,7 +518,7 @@ struct ste_softc { int ste_tx_thresh; u_int8_t ste_link; int ste_if_flags; - int ste_tx_prev_idx; + struct ste_chain *ste_tx_prev; struct ste_list_data *ste_ldata; struct ste_chain_data ste_cdata; struct callout_handle ste_stat_ch;