Date: Tue, 30 Mar 2004 18:00:02 +0300 From: Ruslan Ermilov <ru@FreeBSD.org> To: Doug Ambrisko <ambrisko@FreeBSD.org> Cc: net@FreeBSD.org Subject: ste(4) NIC's RX ring head may get ahead of the driver [PATCH] Message-ID: <20040330150001.GB94442@ip.net.ua>
next in thread | raw e-mail | index | archive | help
--qtZFehHsKgwS5rPz Content-Type: multipart/mixed; boundary="St7VIuEGZ6dlpu13" Content-Disposition: inline --St7VIuEGZ6dlpu13 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Hey Doug, I'm writing to you because you were the last who touched this driver seriously, but since it's been 1,5 years ago, I'm also Cc:ing the freebsd-net mailing list, as I'm not sure if you're still interested in this driver. To make the long story short, under a heavy RX load, the ste(4) NIC's RX ring head may get ahead of what driver thinks, bringing all sort of havoc like stuck traffic, disordered packets, etc. The NIC never gets out of this state, and the only workaround is to reset the chip, and so we did for some time (by adding the IFF_LINK2 handler to call the driver's watchdog function). A similar problem is known to exist with other NICs, such as dc(4) and xl(4), and their drivers have workarounds for this situation. We've adopted the approach used by dc(4) and xl(4), but instead of seeing if we need to re-synchronize the head _after_ receiving (like dc(4) and xl(4) drivers do), we do it at the beginning of ste_rxeof(). As statistics shows, the number of resyncs needed is smaller by a factor of 3 or more in this case, because often the RxDMAComplete interrupt is generated when RX ring is completely empty(!), and as NIC continues to do DMA and fill the RX ring while we're still servicing the RxDMAComplete interrupt, we did more resyncs than was actually necessary. Also, we were able to further reduce the number of resyncs by setting the RxDMAPollPeriod to a higher value. 320ns looked like an overkill here, and I'm not sure why you have chosen it in the first place, when adding polling support for RX in the driver. Also, we believe that this setting may be responsible for what you referred to as: > This card still has seemingly unfixable issues under heavy RX load in > which the card takes over the PCI bus. in the commit log for revision 1.33 of if_ste.c. Attached is the patch (for RELENG_4) we're currently using, and are quite happy with. If anyone is using ste(4) NICs and is experiencing similar problems, I'd be glad to hear the reports about this patch. Cheers, --=20 Ruslan Ermilov ru@FreeBSD.org FreeBSD committer --St7VIuEGZ6dlpu13 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=p Content-Transfer-Encoding: quoted-printable Index: if_ste.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D RCS file: /home/cvs/ipnet/freebsd/src/sys/pci/if_ste.c,v retrieving revision 1.1.1.2 retrieving revision 1.7 diff -u -p -r1.1.1.2 -r1.7 --- if_ste.c 29 Mar 2004 11:47:42 -0000 1.1.1.2 +++ if_ste.c 29 Mar 2004 13:41:47 -0000 1.7 @@ -30,6 +30,7 @@ * THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/pci/if_ste.c,v 1.14.2.10 2004/03/25 08:49:22 ru Exp $ + * $IPNet: ipnet/freebsd/src/sys/pci/if_ste.c,v 1.7 2004/03/29 13:41:47 ru= Exp $ */ =20 #include <sys/param.h> @@ -39,6 +40,7 @@ #include <sys/malloc.h> #include <sys/kernel.h> #include <sys/socket.h> +#include <sys/sysctl.h> =20 #include <net/if.h> #include <net/if_arp.h> @@ -163,6 +165,10 @@ static driver_t ste_driver =3D { =20 static devclass_t ste_devclass; =20 +static int ste_rxresync; +SYSCTL_INT(_hw, OID_AUTO, ste_rxresync, CTLFLAG_RW, + &ste_rxresync, 0, ""); + DRIVER_MODULE(if_ste, pci, ste_driver, ste_devclass, 0, 0); DRIVER_MODULE(miibus, ste, miibus_driver, miibus_devclass, 0, 0); =20 @@ -691,6 +697,19 @@ static void ste_rxeof(sc) =20 ifp =3D &sc->arpcom.ac_if; =20 + if (sc->ste_cdata.ste_rx_head->ste_ptr->ste_status =3D=3D 0) { + cur_rx =3D sc->ste_cdata.ste_rx_head; + do { + cur_rx =3D cur_rx->ste_next; + /* If the ring is empty, just return. */ + if (cur_rx =3D=3D sc->ste_cdata.ste_rx_head) + return; + } while (cur_rx->ste_ptr->ste_status =3D=3D 0); + /* We've fallen behind the chip: catch it. */ + sc->ste_cdata.ste_rx_head =3D cur_rx; + ++ste_rxresync; + }; + while((rxstat =3D sc->ste_cdata.ste_rx_head->ste_ptr->ste_status) & STE_RXSTAT_DMADONE) { if ((STE_RX_LIST_CNT - count) < 3) { @@ -1255,7 +1274,7 @@ static void ste_init(xsc) } =20 /* Set RX polling interval */ - CSR_WRITE_1(sc, STE_RX_DMAPOLL_PERIOD, 1); + CSR_WRITE_1(sc, STE_RX_DMAPOLL_PERIOD, 64); =20 /* Init TX descriptors */ ste_init_tx_list(sc); --St7VIuEGZ6dlpu13-- --qtZFehHsKgwS5rPz Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.4 (FreeBSD) iD8DBQFAaYtxUkv4P6juNwoRAsDmAKCFR+dRSyOaZdnQ6MiIdPSCqX8iTQCggTVX 0JOAvF0tSgTiR7yRGmZUHgc= =6VzZ -----END PGP SIGNATURE----- --qtZFehHsKgwS5rPz--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040330150001.GB94442>