mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-03 14:48:57 +00:00
Spruce up the Sundance ST201 driver:
- Convert to using TX descritor polling similar to the xl driver (the ST201 is a clone of the 3c90xB chipset and offers the same transmit polling scheme). This should reduce TX overhad a little. - Make sure to reset PHY when switching mode, as in the starfire driver. - Fix instances of free() that should be contigfree(). - Remove dead code.
This commit is contained in:
parent
87db5eaa0d
commit
a2c195896a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=54268
242
sys/pci/if_ste.c
242
sys/pci/if_ste.c
@ -441,6 +441,13 @@ static int ste_ifmedia_upd(ifp)
|
||||
|
||||
sc = ifp->if_softc;
|
||||
mii = device_get_softc(sc->ste_miibus);
|
||||
sc->ste_link = 0;
|
||||
if (mii->mii_instance) {
|
||||
struct mii_softc *miisc;
|
||||
for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL;
|
||||
miisc = LIST_NEXT(miisc, mii_list))
|
||||
mii_phy_reset(miisc);
|
||||
}
|
||||
mii_mediachg(mii);
|
||||
|
||||
return(0);
|
||||
@ -800,11 +807,10 @@ static void ste_txeoc(sc)
|
||||
ifp->if_oerrors++;
|
||||
printf("ste%d: transmission error: %x\n",
|
||||
sc->ste_unit, txstat);
|
||||
STE_SETBIT4(sc, STE_ASICCTL, STE_ASICCTL_TX_RESET);
|
||||
|
||||
if (sc->ste_cdata.ste_tx_head != NULL)
|
||||
CSR_WRITE_4(sc, STE_TX_DMALIST_PTR,
|
||||
vtophys(sc->ste_cdata.ste_tx_head->ste_ptr));
|
||||
ste_reset(sc);
|
||||
ste_init(sc);
|
||||
|
||||
if (txstat & STE_TXSTATUS_UNDERRUN &&
|
||||
sc->ste_tx_thresh < STE_PACKET_SIZE) {
|
||||
sc->ste_tx_thresh += STE_MIN_FRAMELEN;
|
||||
@ -826,39 +832,35 @@ static void ste_txeoc(sc)
|
||||
static void ste_txeof(sc)
|
||||
struct ste_softc *sc;
|
||||
{
|
||||
struct ste_chain *cur_tx;
|
||||
struct ste_chain *cur_tx = NULL;
|
||||
struct ifnet *ifp;
|
||||
int idx;
|
||||
|
||||
ifp = &sc->arpcom.ac_if;
|
||||
|
||||
/* Clear the timeout timer. */
|
||||
ifp->if_timer = 0;
|
||||
idx = sc->ste_cdata.ste_tx_cons;
|
||||
while(idx != sc->ste_cdata.ste_tx_prod) {
|
||||
cur_tx = &sc->ste_cdata.ste_tx_chain[idx];
|
||||
|
||||
while(sc->ste_cdata.ste_tx_head != NULL) {
|
||||
cur_tx = sc->ste_cdata.ste_tx_head;
|
||||
if (!(cur_tx->ste_ptr->ste_ctl & STE_TXCTL_DMADONE))
|
||||
break;
|
||||
sc->ste_cdata.ste_tx_head = cur_tx->ste_next;
|
||||
|
||||
m_freem(cur_tx->ste_mbuf);
|
||||
cur_tx->ste_mbuf = NULL;
|
||||
if (cur_tx->ste_mbuf != NULL) {
|
||||
m_freem(cur_tx->ste_mbuf);
|
||||
cur_tx->ste_mbuf = NULL;
|
||||
}
|
||||
|
||||
ifp->if_opackets++;
|
||||
|
||||
cur_tx->ste_next = sc->ste_cdata.ste_tx_free;
|
||||
sc->ste_cdata.ste_tx_free = cur_tx;
|
||||
sc->ste_cdata.ste_tx_cnt--;
|
||||
STE_INC(idx, STE_TX_LIST_CNT);
|
||||
ifp->if_timer = 0;
|
||||
}
|
||||
|
||||
if (sc->ste_cdata.ste_tx_head == NULL) {
|
||||
sc->ste_cdata.ste_tx_cons = idx;
|
||||
|
||||
if (cur_tx != NULL)
|
||||
ifp->if_flags &= ~IFF_OACTIVE;
|
||||
sc->ste_cdata.ste_tx_tail = NULL;
|
||||
} else {
|
||||
if (CSR_READ_4(sc, STE_DMACTL) & STE_DMACTL_TXDMA_STOPPED ||
|
||||
!CSR_READ_4(sc, STE_TX_DMALIST_PTR)) {
|
||||
CSR_WRITE_4(sc, STE_TX_DMALIST_PTR,
|
||||
vtophys(sc->ste_cdata.ste_tx_head->ste_ptr));
|
||||
CSR_WRITE_4(sc, STE_DMACTL, STE_DMACTL_TXDMA_UNSTALL);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@ -890,6 +892,14 @@ static void ste_stats_update(xsc)
|
||||
stats.ste_multi_colls + stats.ste_late_colls;
|
||||
|
||||
mii_tick(mii);
|
||||
if (!sc->ste_link) {
|
||||
mii_pollstat(mii);
|
||||
if (mii->mii_media_status & IFM_ACTIVE &&
|
||||
IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE)
|
||||
sc->ste_link++;
|
||||
if (ifp->if_snd.ifq_head != NULL)
|
||||
ste_start(ifp);
|
||||
}
|
||||
|
||||
sc->ste_stat_ch = timeout(ste_stats_update, sc, hz);
|
||||
splx(s);
|
||||
@ -1072,7 +1082,8 @@ static int ste_attach(dev)
|
||||
bus_teardown_intr(dev, sc->ste_irq, sc->ste_intrhand);
|
||||
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ste_irq);
|
||||
bus_release_resource(dev, STE_RES, STE_RID, sc->ste_res);
|
||||
free(sc->ste_ldata, M_DEVBUF);
|
||||
contigfree(sc->ste_ldata,
|
||||
sizeof(struct ste_list_data), M_DEVBUF);
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
@ -1127,7 +1138,7 @@ static int ste_detach(dev)
|
||||
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->ste_irq);
|
||||
bus_release_resource(dev, STE_RES, STE_RID, sc->ste_res);
|
||||
|
||||
free(sc->ste_ldata, M_DEVBUF);
|
||||
contigfree(sc->ste_ldata, sizeof(struct ste_list_data), M_DEVBUF);
|
||||
|
||||
splx(s);
|
||||
|
||||
@ -1216,15 +1227,28 @@ static void ste_init_tx_list(sc)
|
||||
ld = sc->ste_ldata;
|
||||
for (i = 0; i < STE_TX_LIST_CNT; i++) {
|
||||
cd->ste_tx_chain[i].ste_ptr = &ld->ste_tx_list[i];
|
||||
cd->ste_tx_chain[i].ste_phys = vtophys(&ld->ste_tx_list[i]);
|
||||
if (i == (STE_TX_LIST_CNT - 1))
|
||||
cd->ste_tx_chain[i].ste_next = NULL;
|
||||
cd->ste_tx_chain[i].ste_next =
|
||||
&cd->ste_tx_chain[0];
|
||||
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_free = &cd->ste_tx_chain[0];
|
||||
cd->ste_tx_tail = cd->ste_tx_head = NULL;
|
||||
|
||||
bzero((char *)ld->ste_tx_list,
|
||||
sizeof(struct ste_desc) * STE_TX_LIST_CNT);
|
||||
|
||||
cd->ste_tx_prod = 0;
|
||||
cd->ste_tx_cons = 0;
|
||||
cd->ste_tx_cnt = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
@ -1266,7 +1290,6 @@ static void ste_init(xsc)
|
||||
CSR_WRITE_1(sc, STE_TX_DMABURST_THRESH, STE_PACKET_SIZE >> 8);
|
||||
|
||||
/* Set the TX start threshold for best performance. */
|
||||
sc->ste_tx_thresh = STE_MIN_FRAMELEN;
|
||||
CSR_WRITE_2(sc, STE_TX_STARTTHRESH, sc->ste_tx_thresh);
|
||||
|
||||
/* Set the TX reclaim threshold. */
|
||||
@ -1299,6 +1322,18 @@ static void ste_init(xsc)
|
||||
STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_RXDMA_UNSTALL);
|
||||
STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_RXDMA_UNSTALL);
|
||||
|
||||
/* Set TX polling interval */
|
||||
CSR_WRITE_1(sc, STE_TX_DMAPOLL_PERIOD, 64);
|
||||
|
||||
/* Load address of the TX list */
|
||||
STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_TXDMA_STALL);
|
||||
ste_wait(sc);
|
||||
CSR_WRITE_4(sc, STE_TX_DMALIST_PTR,
|
||||
vtophys(&sc->ste_ldata->ste_tx_list[0]));
|
||||
STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_TXDMA_UNSTALL);
|
||||
STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_TXDMA_UNSTALL);
|
||||
ste_wait(sc);
|
||||
|
||||
/* Enable receiver and transmitter */
|
||||
CSR_WRITE_2(sc, STE_MACCTL0, 0);
|
||||
STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_TX_ENABLE);
|
||||
@ -1311,7 +1346,7 @@ static void ste_init(xsc)
|
||||
CSR_WRITE_2(sc, STE_ISR, 0xFFFF);
|
||||
CSR_WRITE_2(sc, STE_IMR, STE_INTRS);
|
||||
|
||||
mii_mediachg(mii);
|
||||
ste_ifmedia_upd(ifp);
|
||||
|
||||
ifp->if_flags |= IFF_RUNNING;
|
||||
ifp->if_flags &= ~IFF_OACTIVE;
|
||||
@ -1341,6 +1376,8 @@ static void ste_stop(sc)
|
||||
STE_SETBIT2(sc, STE_DMACTL, STE_DMACTL_RXDMA_STALL);
|
||||
ste_wait(sc);
|
||||
|
||||
sc->ste_link = 0;
|
||||
|
||||
for (i = 0; i < STE_RX_LIST_CNT; i++) {
|
||||
if (sc->ste_cdata.ste_rx_chain[i].ste_mbuf != NULL) {
|
||||
m_freem(sc->ste_cdata.ste_rx_chain[i].ste_mbuf);
|
||||
@ -1382,30 +1419,6 @@ static void ste_reset(sc)
|
||||
if (i == STE_TIMEOUT)
|
||||
printf("ste%d: global reset never completed\n", sc->ste_unit);
|
||||
|
||||
#ifdef foo
|
||||
STE_SETBIT4(sc, STE_ASICCTL, STE_ASICCTL_RX_RESET);
|
||||
for (i = 0; i < STE_TIMEOUT; i++) {
|
||||
if (!(CSR_READ_4(sc, STE_ASICCTL) & STE_ASICCTL_RX_RESET))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == STE_TIMEOUT)
|
||||
printf("ste%d: RX reset never completed\n", sc->ste_unit);
|
||||
|
||||
DELAY(100000);
|
||||
|
||||
STE_SETBIT4(sc, STE_ASICCTL, STE_ASICCTL_TX_RESET);
|
||||
for (i = 0; i < STE_TIMEOUT; i++) {
|
||||
if (!(CSR_READ_4(sc, STE_ASICCTL) & STE_ASICCTL_TX_RESET))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == STE_TIMEOUT)
|
||||
printf("ste%d: TX reset never completed\n", sc->ste_unit);
|
||||
|
||||
DELAY(100000);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1432,11 +1445,25 @@ static int ste_ioctl(ifp, command, data)
|
||||
break;
|
||||
case SIOCSIFFLAGS:
|
||||
if (ifp->if_flags & IFF_UP) {
|
||||
ste_init(sc);
|
||||
if (ifp->if_flags & IFF_RUNNING &&
|
||||
ifp->if_flags & IFF_PROMISC &&
|
||||
!(sc->ste_if_flags & IFF_PROMISC)) {
|
||||
STE_SETBIT1(sc, STE_RX_MODE,
|
||||
STE_RXMODE_PROMISC);
|
||||
} else if (ifp->if_flags & IFF_RUNNING &&
|
||||
!(ifp->if_flags & IFF_PROMISC) &&
|
||||
sc->ste_if_flags & IFF_PROMISC) {
|
||||
STE_CLRBIT1(sc, STE_RX_MODE,
|
||||
STE_RXMODE_PROMISC);
|
||||
} else if (!(ifp->if_flags & IFF_RUNNING)) {
|
||||
sc->ste_tx_thresh = STE_MIN_FRAMELEN;
|
||||
ste_init(sc);
|
||||
}
|
||||
} else {
|
||||
if (ifp->if_flags & IFF_RUNNING)
|
||||
ste_stop(sc);
|
||||
}
|
||||
sc->ste_if_flags = ifp->if_flags;
|
||||
error = 0;
|
||||
break;
|
||||
case SIOCADDMULTI:
|
||||
@ -1466,11 +1493,13 @@ static int ste_encap(sc, c, m_head)
|
||||
{
|
||||
int frag = 0;
|
||||
struct ste_frag *f = NULL;
|
||||
int total_len;
|
||||
struct mbuf *m;
|
||||
struct ste_desc *d;
|
||||
int total_len = 0;
|
||||
|
||||
m = m_head;
|
||||
total_len = 0;
|
||||
d = c->ste_ptr;
|
||||
d->ste_ctl = 0;
|
||||
d->ste_next = 0;
|
||||
|
||||
for (m = m_head, frag = 0; m != NULL; m = m->m_next) {
|
||||
if (m->m_len != 0) {
|
||||
@ -1484,39 +1513,9 @@ static int ste_encap(sc, c, m_head)
|
||||
}
|
||||
}
|
||||
|
||||
if (m != NULL) {
|
||||
struct mbuf *m_new = NULL;
|
||||
|
||||
MGETHDR(m_new, M_DONTWAIT, MT_DATA);
|
||||
if (m_new == NULL) {
|
||||
printf("ste%d: no memory for "
|
||||
"tx list", sc->ste_unit);
|
||||
return(1);
|
||||
}
|
||||
if (m_head->m_pkthdr.len > MHLEN) {
|
||||
MCLGET(m_new, M_DONTWAIT);
|
||||
if (!(m_new->m_flags & M_EXT)) {
|
||||
m_freem(m_new);
|
||||
printf("ste%d: no memory for "
|
||||
"tx list", sc->ste_unit);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
m_copydata(m_head, 0, m_head->m_pkthdr.len,
|
||||
mtod(m_new, caddr_t));
|
||||
m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len;
|
||||
m_freem(m_head);
|
||||
m_head = m_new;
|
||||
f = &c->ste_ptr->ste_frags[0];
|
||||
f->ste_addr = vtophys(mtod(m_new, caddr_t));
|
||||
f->ste_len = total_len = m_new->m_len;
|
||||
frag = 1;
|
||||
}
|
||||
|
||||
c->ste_mbuf = m_head;
|
||||
c->ste_ptr->ste_frags[frag - 1].ste_len |= STE_FRAG_LAST;
|
||||
c->ste_ptr->ste_ctl = total_len;
|
||||
c->ste_ptr->ste_next = 0;
|
||||
|
||||
return(0);
|
||||
}
|
||||
@ -1527,40 +1526,47 @@ static void ste_start(ifp)
|
||||
struct ste_softc *sc;
|
||||
struct mbuf *m_head = NULL;
|
||||
struct ste_chain *prev = NULL, *cur_tx = NULL, *start_tx;
|
||||
int idx;
|
||||
|
||||
sc = ifp->if_softc;
|
||||
|
||||
if (sc->ste_cdata.ste_tx_free == NULL) {
|
||||
ifp->if_flags |= IFF_OACTIVE;
|
||||
if (!sc->ste_link)
|
||||
return;
|
||||
}
|
||||
|
||||
start_tx = sc->ste_cdata.ste_tx_free;
|
||||
if (ifp->if_flags & IFF_OACTIVE)
|
||||
return;
|
||||
|
||||
idx = sc->ste_cdata.ste_tx_prod;
|
||||
start_tx = &sc->ste_cdata.ste_tx_chain[idx];
|
||||
|
||||
while(sc->ste_cdata.ste_tx_chain[idx].ste_mbuf == NULL) {
|
||||
|
||||
if ((STE_TX_LIST_CNT - sc->ste_cdata.ste_tx_cnt) < 3) {
|
||||
ifp->if_flags |= IFF_OACTIVE;
|
||||
break;
|
||||
}
|
||||
|
||||
while(sc->ste_cdata.ste_tx_free != NULL) {
|
||||
IF_DEQUEUE(&ifp->if_snd, m_head);
|
||||
if (m_head == NULL)
|
||||
break;
|
||||
|
||||
cur_tx = sc->ste_cdata.ste_tx_free;
|
||||
sc->ste_cdata.ste_tx_free = cur_tx->ste_next;
|
||||
|
||||
cur_tx->ste_next = NULL;
|
||||
cur_tx = &sc->ste_cdata.ste_tx_chain[idx];
|
||||
|
||||
ste_encap(sc, cur_tx, m_head);
|
||||
|
||||
if (prev != NULL) {
|
||||
prev->ste_next = cur_tx;
|
||||
prev->ste_ptr->ste_next = vtophys(cur_tx->ste_ptr);
|
||||
}
|
||||
if (prev != NULL)
|
||||
prev->ste_ptr->ste_next = cur_tx->ste_phys;
|
||||
prev = cur_tx;
|
||||
|
||||
/*
|
||||
* If there's a BPF listener, bounce a copt of this frame
|
||||
* If there's a BPF listener, bounce a copy of this frame
|
||||
* to him.
|
||||
*/
|
||||
if (ifp->if_bpf)
|
||||
bpf_mtap(ifp, cur_tx->ste_mbuf);
|
||||
|
||||
STE_INC(idx, STE_TX_LIST_CNT);
|
||||
sc->ste_cdata.ste_tx_cnt++;
|
||||
}
|
||||
|
||||
if (cur_tx == NULL)
|
||||
@ -1568,25 +1574,9 @@ static void ste_start(ifp)
|
||||
|
||||
cur_tx->ste_ptr->ste_ctl |= STE_TXCTL_DMAINTR;
|
||||
|
||||
STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_TXDMA_STALL);
|
||||
ste_wait(sc);
|
||||
|
||||
if (sc->ste_cdata.ste_tx_head != NULL) {
|
||||
sc->ste_cdata.ste_tx_tail->ste_next = start_tx;
|
||||
sc->ste_cdata.ste_tx_tail->ste_ptr->ste_next =
|
||||
vtophys(start_tx->ste_ptr);
|
||||
sc->ste_cdata.ste_tx_tail->ste_ptr->ste_ctl &=
|
||||
~STE_TXCTL_DMAINTR;
|
||||
sc->ste_cdata.ste_tx_tail = cur_tx;
|
||||
} else {
|
||||
sc->ste_cdata.ste_tx_head = start_tx;
|
||||
sc->ste_cdata.ste_tx_tail = cur_tx;
|
||||
}
|
||||
|
||||
if (!CSR_READ_4(sc, STE_TX_DMALIST_PTR))
|
||||
CSR_WRITE_4(sc, STE_TX_DMALIST_PTR,
|
||||
vtophys(start_tx->ste_ptr));
|
||||
STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_TXDMA_UNSTALL);
|
||||
/* Start transmission */
|
||||
sc->ste_cdata.ste_tx_prod = idx;
|
||||
start_tx->ste_prev->ste_ptr->ste_next = start_tx->ste_phys;
|
||||
|
||||
ifp->if_timer = 5;
|
||||
|
||||
@ -1603,14 +1593,6 @@ static void ste_watchdog(ifp)
|
||||
ifp->if_oerrors++;
|
||||
printf("ste%d: watchdog timeout\n", sc->ste_unit);
|
||||
|
||||
#ifdef foo
|
||||
if (sc->ste_pinfo != NULL) {
|
||||
if (!(ste_phy_readreg(sc, PHY_BMSR) & PHY_BMSR_LINKSTAT))
|
||||
printf("ste%d: no carrier - transceiver "
|
||||
"cable problem?\n", sc->ste_unit);
|
||||
}
|
||||
#endif
|
||||
|
||||
ste_txeoc(sc);
|
||||
ste_txeof(sc);
|
||||
ste_rxeof(sc);
|
||||
|
@ -454,12 +454,13 @@ struct ste_desc_onefrag {
|
||||
#define CSR_READ_1(sc, reg) \
|
||||
bus_space_read_1(sc->ste_btag, sc->ste_bhandle, reg)
|
||||
|
||||
#define STE_TIMEOUT 1000
|
||||
#define STE_MIN_FRAMELEN 60
|
||||
#define STE_PACKET_SIZE 1536
|
||||
#define ETHER_ALIGN 2
|
||||
#define STE_RX_LIST_CNT 128
|
||||
#define STE_TX_LIST_CNT 256
|
||||
#define STE_TIMEOUT 1000
|
||||
#define STE_MIN_FRAMELEN 60
|
||||
#define STE_PACKET_SIZE 1536
|
||||
#define ETHER_ALIGN 2
|
||||
#define STE_RX_LIST_CNT 128
|
||||
#define STE_TX_LIST_CNT 256
|
||||
#define STE_INC(x, y) (x) = (x + 1) % y
|
||||
|
||||
struct ste_type {
|
||||
u_int16_t ste_vid;
|
||||
@ -477,6 +478,8 @@ 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;
|
||||
};
|
||||
|
||||
struct ste_chain_onefrag {
|
||||
@ -490,9 +493,9 @@ struct ste_chain_data {
|
||||
struct ste_chain ste_tx_chain[STE_TX_LIST_CNT];
|
||||
struct ste_chain_onefrag *ste_rx_head;
|
||||
|
||||
struct ste_chain *ste_tx_head;
|
||||
struct ste_chain *ste_tx_tail;
|
||||
struct ste_chain *ste_tx_free;
|
||||
int ste_tx_prod;
|
||||
int ste_tx_cons;
|
||||
int ste_tx_cnt;
|
||||
};
|
||||
|
||||
struct ste_softc {
|
||||
@ -506,6 +509,8 @@ struct ste_softc {
|
||||
device_t ste_miibus;
|
||||
int ste_unit;
|
||||
int ste_tx_thresh;
|
||||
u_int8_t ste_link;
|
||||
int ste_if_flags;
|
||||
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