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.
This commit is contained in:
Ruslan Ermilov 2004-04-02 23:36:49 +00:00
parent 36c6538b7f
commit 6ec31f009a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=127775
2 changed files with 45 additions and 41 deletions

View File

@ -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);

View File

@ -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;