Date: Fri, 2 Aug 2002 20:39:28 -0700 (PDT) From: Doug Ambrisko <ambrisko@ambrisko.com> To: Kal Torak <kaltorak@quake.com.au> Cc: FreeBSD ISP <freebsd-isp@FreeBSD.ORG>, FreeBSD Stable <freebsd-stable@FreeBSD.ORG> Subject: Re: Problems with D-Link DEF-580TX?? Message-ID: <200208030339.g733dSD06635@ambrisko.com> In-Reply-To: <3D461766.6090901@quake.com.au>
next in thread | previous in thread | raw e-mail | index | archive | help
Kal Torak writes: | Just wondering if anyone has been able to use the new DEF-580TX | quad port card without any problems?? No ... doesn't seem possible but you can make it happier with these patches. I need to test under current and then I will commit them. Seems like the chip has a fundamental problem to block any I/O but it's own under have RX load. Happens under Linux, Windows, FreeBSD etc. The Znyx (http://www.znyx.com/) cards seem to work fine under -stable. I have the 32 and 64 bit versions of the dc(4) versions. Doug A. Index: sys/pci/if_ste.c =================================================================== RCS file: /cvs/src/sys/pci/if_ste.c,v retrieving revision 1.14.2.5 diff -u -r1.14.2.5 if_ste.c --- sys/pci/if_ste.c 16 Dec 2001 15:46:08 -0000 1.14.2.5 +++ sys/pci/if_ste.c 3 Aug 2002 03:36:06 -0000 @@ -45,6 +45,7 @@ #include <net/ethernet.h> #include <net/if_dl.h> #include <net/if_media.h> +#include <net/if_vlan_var.h> #include <net/bpf.h> @@ -415,6 +416,7 @@ { struct ste_softc *sc; struct mii_data *mii; + int i; sc = device_get_softc(dev); mii = device_get_softc(sc->ste_miibus); @@ -425,6 +427,15 @@ STE_CLRBIT2(sc, STE_MACCTL0, STE_MACCTL0_FULLDUPLEX); } + STE_SETBIT4(sc, STE_ASICCTL,STE_ASICCTL_RX_RESET | + STE_ASICCTL_TX_RESET); + for (i = 0; i < STE_TIMEOUT; i++) { + if (!(CSR_READ_4(sc, STE_ASICCTL) & STE_ASICCTL_RESET_BUSY)) + break; + } + if (i == STE_TIMEOUT) + printf("ste%d: rx reset never completed\n", sc->ste_unit); + return; } @@ -643,6 +654,9 @@ ste_stats_update(sc); } + if (status & STE_ISR_LINKEVENT) + mii_pollstat(device_get_softc(sc->ste_miibus)); + if (status & STE_ISR_HOSTERR) { ste_reset(sc); ste_init(sc); @@ -669,17 +683,20 @@ struct mbuf *m; struct ifnet *ifp; struct ste_chain_onefrag *cur_rx; - int total_len = 0; + int total_len = 0, count=0; u_int32_t rxstat; ifp = &sc->arpcom.ac_if; -again: + while((rxstat = sc->ste_cdata.ste_rx_head->ste_ptr->ste_status) + & STE_RXSTAT_DMADONE) { + if ((STE_RX_LIST_CNT - count) < 3) { + break; + } - while((rxstat = sc->ste_cdata.ste_rx_head->ste_ptr->ste_status)) { cur_rx = sc->ste_cdata.ste_rx_head; sc->ste_cdata.ste_rx_head = cur_rx->ste_next; - + /* * If an error occurs, update stats, clear the * status word and leave the mbuf cluster in place: @@ -730,29 +747,9 @@ /* Remove header from mbuf and pass it on. */ m_adj(m, sizeof(struct ether_header)); ether_input(ifp, eh, m); - } - - /* - * Handle the 'end of channel' condition. When the upload - * engine hits the end of the RX ring, it will stall. This - * is our cue to flush the RX ring, reload the uplist pointer - * register and unstall the engine. - * XXX This is actually a little goofy. With the ThunderLAN - * chip, you get an interrupt when the receiver hits the end - * of the receive ring, which tells you exactly when you - * you need to reload the ring pointer. Here we have to - * fake it. I'm mad at myself for not being clever enough - * to avoid the use of a goto here. - */ - if (CSR_READ_4(sc, STE_RX_DMALIST_PTR) == 0 || - CSR_READ_4(sc, STE_DMACTL) & STE_DMACTL_RXDMA_STOPPED) { - STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_RXDMA_STALL); - ste_wait(sc); - CSR_WRITE_4(sc, STE_RX_DMALIST_PTR, - vtophys(&sc->ste_ldata->ste_rx_list[0])); - sc->ste_cdata.ste_rx_head = &sc->ste_cdata.ste_rx_chain[0]; - STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_RXDMA_UNSTALL); - goto again; + + cur_rx->ste_ptr->ste_status = 0; + count++; } return; @@ -836,11 +833,9 @@ void *xsc; { struct ste_softc *sc; - struct ste_stats stats; struct ifnet *ifp; struct mii_data *mii; - int i, s; - u_int8_t *p; + int s; s = splimp(); @@ -848,24 +843,23 @@ ifp = &sc->arpcom.ac_if; mii = device_get_softc(sc->ste_miibus); - p = (u_int8_t *)&stats; - - for (i = 0; i < sizeof(stats); i++) { - *p = CSR_READ_1(sc, STE_STATS + i); - p++; - } - - ifp->if_collisions += stats.ste_single_colls + - stats.ste_multi_colls + stats.ste_late_colls; + ifp->if_collisions += CSR_READ_1(sc, STE_LATE_COLLS) + + CSR_READ_1(sc, STE_MULTI_COLLS) + + CSR_READ_1(sc, STE_SINGLE_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) + IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { sc->ste_link++; + /* + * we don't get a call-back on re-init so do it + * otherwise we get stuck in the wrong link state + */ + ste_miibus_statchg(sc->ste_dev); if (ifp->if_snd.ifq_head != NULL) ste_start(ifp); + } } sc->ste_stat_ch = timeout(ste_stats_update, sc, hz); @@ -916,6 +910,7 @@ sc = device_get_softc(dev); unit = device_get_unit(dev); bzero(sc, sizeof(struct ste_softc)); + sc->ste_dev = dev; /* * Handle power management nonsense. @@ -1069,11 +1064,18 @@ ifp->if_baudrate = 10000000; ifp->if_snd.ifq_maxlen = STE_TX_LIST_CNT - 1; + sc->ste_tx_thresh = STE_TXSTART_THRESH; + /* * Call MI attach routine. */ ether_ifattach(ifp, ETHER_BPF_SUPPORTED); + /* + * Tell the upper layer(s) we support long frames. + */ + ifp->if_data.ifi_hdrlen = sizeof(struct ether_vlan_header); + fail: splx(s); return(error); @@ -1136,7 +1138,7 @@ c->ste_mbuf = m_new; c->ste_ptr->ste_status = 0; c->ste_ptr->ste_frag.ste_addr = vtophys(mtod(m_new, caddr_t)); - c->ste_ptr->ste_frag.ste_len = 1536 | STE_FRAG_LAST; + c->ste_ptr->ste_frag.ste_len = (1536 + EVL_ENCAPLEN) | STE_FRAG_LAST; return(0); } @@ -1166,7 +1168,7 @@ ld->ste_rx_list[i].ste_next = vtophys(&ld->ste_rx_list[i + 1]); } - + ld->ste_rx_list[i].ste_status = 0; } cd->ste_rx_head = &cd->ste_rx_chain[0]; @@ -1185,6 +1187,8 @@ 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_ptr->ste_next = 0; + cd->ste_tx_chain[i].ste_ptr->ste_ctl = 0; 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 = @@ -1200,10 +1204,6 @@ &cd->ste_tx_chain[i - 1]; } - - 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; @@ -1241,6 +1241,9 @@ return; } + /* Set RX polling interval */ + CSR_WRITE_1(sc, STE_RX_DMAPOLL_PERIOD, 1); + /* Init TX descriptors */ ste_init_tx_list(sc); @@ -1280,20 +1283,21 @@ 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); + /* Set TX polling interval (defer until we TX first packet */ + CSR_WRITE_1(sc, STE_TX_DMAPOLL_PERIOD, 0); /* 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])); + CSR_WRITE_4(sc, STE_TX_DMALIST_PTR, 0); 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; /* Enable receiver and transmitter */ CSR_WRITE_2(sc, STE_MACCTL0, 0); + CSR_WRITE_2(sc, STE_MACCTL1, 0); STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_TX_ENABLE); STE_SETBIT2(sc, STE_MACCTL1, STE_MACCTL1_RX_ENABLE); @@ -1304,6 +1308,9 @@ CSR_WRITE_2(sc, STE_ISR, 0xFFFF); CSR_WRITE_2(sc, STE_IMR, STE_INTRS); + /* Accept VLAN length packets */ + CSR_WRITE_2(sc, STE_MAX_FRAMELEN, ETHER_MAX_LEN + EVL_ENCAPLEN); + ste_ifmedia_upd(ifp); ifp->if_flags |= IFF_RUNNING; @@ -1333,6 +1340,11 @@ STE_SETBIT2(sc, STE_DMACTL, STE_DMACTL_TXDMA_STALL); STE_SETBIT2(sc, STE_DMACTL, STE_DMACTL_RXDMA_STALL); ste_wait(sc); + /* + * Try really hard to stop the RX engine or under heavy RX + * data chip will write into de-allocated memory. + */ + ste_reset(sc); sc->ste_link = 0; @@ -1350,6 +1362,8 @@ } } + bzero(sc->ste_ldata, sizeof(struct ste_list_data)); + ifp->if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); return; @@ -1413,8 +1427,10 @@ 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; + } + if (!(ifp->if_flags & IFF_RUNNING)) { + sc->ste_tx_thresh = STE_MIN_FRAMELEN * 2; + sc->ste_tx_thresh = STE_TXSTART_THRESH; ste_init(sc); } } else { @@ -1457,14 +1473,13 @@ 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) { if (frag == STE_MAXFRAGS) break; total_len += m->m_len; - f = &c->ste_ptr->ste_frags[frag]; + f = &d->ste_frags[frag]; f->ste_addr = vtophys(mtod(m, vm_offset_t)); f->ste_len = m->m_len; frag++; @@ -1472,8 +1487,8 @@ } c->ste_mbuf = m_head; - c->ste_ptr->ste_frags[frag - 1].ste_len |= STE_FRAG_LAST; - c->ste_ptr->ste_ctl = total_len; + d->ste_frags[frag - 1].ste_len |= STE_FRAG_LAST; + d->ste_ctl = 1; return(0); } @@ -1483,7 +1498,7 @@ { struct ste_softc *sc; struct mbuf *m_head = NULL; - struct ste_chain *prev = NULL, *cur_tx = NULL, *start_tx; + struct ste_chain *cur_tx = NULL; int idx; sc = ifp->if_softc; @@ -1495,7 +1510,6 @@ 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) { @@ -1512,9 +1526,32 @@ ste_encap(sc, cur_tx, m_head); - if (prev != NULL) - prev->ste_ptr->ste_next = cur_tx->ste_phys; - prev = cur_tx; + cur_tx->ste_ptr->ste_next = 0; + + if(sc->ste_tx_prev_idx < 0){ + 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); + ste_wait(sc); + + CSR_WRITE_4(sc, STE_TX_DMALIST_PTR, + vtophys(&sc->ste_ldata->ste_tx_list[0])); + + /* Set TX polling interval to start TX engine */ + CSR_WRITE_1(sc, STE_TX_DMAPOLL_PERIOD, 64); + + STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_TXDMA_UNSTALL); + STE_SETBIT4(sc, STE_DMACTL, STE_DMACTL_TXDMA_UNSTALL); + 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 + = cur_tx->ste_phys; + } + + sc->ste_tx_prev_idx=idx; /* * If there's a BPF listener, bounce a copy of this frame @@ -1525,18 +1562,9 @@ STE_INC(idx, STE_TX_LIST_CNT); sc->ste_cdata.ste_tx_cnt++; + ifp->if_timer = 5; + sc->ste_cdata.ste_tx_prod = idx; } - - if (cur_tx == NULL) - return; - - cur_tx->ste_ptr->ste_ctl |= STE_TXCTL_DMAINTR; - - /* 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; return; } Index: sys/pci/if_stereg.h =================================================================== RCS file: /cvs/src/sys/pci/if_stereg.h,v retrieving revision 1.5.2.1 diff -u -r1.5.2.1 if_stereg.h --- sys/pci/if_stereg.h 23 Aug 2001 20:04:06 -0000 1.5.2.1 +++ sys/pci/if_stereg.h 3 Aug 2002 03:36:06 -0000 @@ -93,6 +93,10 @@ #define STE_MAR3 0x66 #define STE_STATS 0x68 +#define STE_LATE_COLLS 0x75 +#define STE_MULTI_COLLS 0x76 +#define STE_SINGLE_COLLS 0x77 + #define STE_DMACTL_RXDMA_STOPPED 0x00000001 #define STE_DMACTL_TXDMA_CMPREQ 0x00000002 #define STE_DMACTL_TXDMA_STOPPED 0x00000004 @@ -224,13 +228,13 @@ * The number of bytes that must in present in the TX FIFO before * transmission begins. Value should be in increments of 4 bytes. */ -#define STE_TXSTART_THRESH 0x1FFF +#define STE_TXSTART_THRESH 0x1FFC /* * Number of bytes that must be present in the RX FIFO before * an RX EARLY interrupt is generated. */ -#define STE_RXEARLY_THRESH 0x1FFF +#define STE_RXEARLY_THRESH 0x1FFC #define STE_WAKEEVENT_WAKEPKT_ENB 0x01 #define STE_WAKEEVENT_MAGICPKT_ENB 0x02 @@ -272,8 +276,9 @@ #define STE_IMR_RX_DMADONE 0x0400 #define STE_INTRS \ - (STE_IMR_RX_DMADONE|STE_IMR_TX_DMADONE|STE_IMR_STATS_OFLOW| \ - STE_IMR_TX_DONE|STE_IMR_HOSTERR|STE_IMR_RX_EARLY) + (STE_IMR_RX_DMADONE|STE_IMR_TX_DMADONE| \ + STE_IMR_TX_DONE|STE_IMR_HOSTERR| \ + STE_IMR_LINKEVENT) #define STE_ISR_INTLATCH 0x0001 #define STE_ISR_HOSTERR 0x0002 @@ -406,7 +411,7 @@ #define STE_FRAG_LAST 0x80000000 #define STE_FRAG_LEN 0x00001FFF -#define STE_MAXFRAGS 63 +#define STE_MAXFRAGS 8 struct ste_desc { u_int32_t ste_next; @@ -460,9 +465,10 @@ #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_RX_LIST_CNT 64 +#define STE_TX_LIST_CNT 64 #define STE_INC(x, y) (x) = (x + 1) % y +#define STE_NEXT(x, y) (x + 1) % y struct ste_type { u_int16_t ste_vid; @@ -509,10 +515,12 @@ void *ste_intrhand; struct ste_type *ste_info; device_t ste_miibus; + device_t ste_dev; int ste_unit; int ste_tx_thresh; u_int8_t ste_link; int ste_if_flags; + int ste_tx_prev_idx; struct ste_list_data *ste_ldata; struct ste_chain_data ste_cdata; struct callout_handle ste_stat_ch; To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-isp" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200208030339.g733dSD06635>