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:
parent
36c6538b7f
commit
6ec31f009a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=127775
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user