Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 10 Nov 2004 14:27:10 +0100
From:      Christian Brueffer <chris@unixpages.org>
To:        net@freebsd.org
Subject:   Re: sf(4) device polling
Message-ID:  <20041110132709.GC9922@unixpages.org>
In-Reply-To: <20041109164942.GC555@unixpages.org>
References:  <20041109164942.GC555@unixpages.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--HWvPVVuAAfuRc6SZ
Content-Type: multipart/mixed; boundary="Izn7cH1Com+I3R9J"
Content-Disposition: inline


--Izn7cH1Com+I3R9J
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

On Tue, Nov 09, 2004 at 05:49:42PM +0100, Christian Brueffer wrote:
> Hi,
>=20
> the attached patch implements device polling for the sf(4) driver.  It
> has been running on my home gateway for almost two weeks now, without any
> ill effects.
>=20

Here's a new patch from Ruslan, which corrects some stuff and adds
missing error recovery.

- Christian

--=20
Christian Brueffer	chris@unixpages.org	brueffer@FreeBSD.org
GPG Key:	 http://people.freebsd.org/~brueffer/brueffer.key.asc
GPG Fingerprint: A5C8 2099 19FF AACA F41B  B29B 6C76 178C A0ED 982D

--Izn7cH1Com+I3R9J
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="if_sf.patch"
Content-Transfer-Encoding: quoted-printable

Index: if_sf.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/ncvs/src/sys/pci/if_sf.c,v
retrieving revision 1.73
diff -u -p -r1.73 if_sf.c
--- if_sf.c	28 Aug 2004 15:10:35 -0000	1.73
+++ if_sf.c	10 Nov 2004 08:08:34 -0000
@@ -164,6 +164,12 @@ static u_int8_t sf_read_eeprom	(struct s
 static int sf_miibus_readreg	(device_t, int, int);
 static int sf_miibus_writereg	(device_t, int, int, int);
 static void sf_miibus_statchg	(device_t);
+#ifdef DEVICE_POLLING
+static void sf_poll		(struct ifnet *ifp, enum poll_cmd cmd,
+				 int count);
+static void sf_poll_locked	(struct ifnet *ifp, enum poll_cmd cmd,
+				 int count);
+#endif /* DEVICE_POLLING */
=20
 static u_int32_t csr_read_4	(struct sf_softc *, int);
 static void csr_write_4		(struct sf_softc *, int, u_int32_t);
@@ -534,6 +540,10 @@ sf_ioctl(ifp, command, data)
 		mii =3D device_get_softc(sc->sf_miibus);
 		error =3D ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
 		break;
+	case SIOCSIFCAP:
+		ifp->if_capenable &=3D ~IFCAP_POLLING;
+		ifp->if_capenable |=3D ifr->ifr_reqcap & IFCAP_POLLING;
+		break;
 	default:
 		error =3D ether_ioctl(ifp, command, data);
 		break;
@@ -714,6 +724,10 @@ sf_attach(dev)
 	ifp->if_init =3D sf_init;
 	ifp->if_baudrate =3D 10000000;
 	ifp->if_snd.ifq_maxlen =3D SF_TX_DLIST_CNT - 1;
+#ifdef DEVICE_POLLING
+	ifp->if_capabilities |=3D IFCAP_POLLING;
+#endif /* DEVICE_POLLING */
+	ifp->if_capenable =3D ifp->if_capabilities;
=20
 	/*
 	 * Call MI attach routine.
@@ -903,6 +917,14 @@ sf_rxeof(sc)
 	while (cmpconsidx !=3D cmpprodidx) {
 		struct mbuf		*m0;
=20
+#ifdef DEVICE_POLLING
+		if (ifp->if_flags & IFF_POLLING) {
+			if (sc->rxcycles <=3D 0)
+				break;
+			sc->rxcycles--;
+		}
+#endif /* DEVICE_POLLING */
+
 		cur_rx =3D &sc->sf_ldata->sf_rx_clist[cmpconsidx];
 		desc =3D &sc->sf_ldata->sf_rx_dlist_big[cur_rx->sf_endidx];
 		m =3D desc->sf_mbuf;
@@ -1010,6 +1032,63 @@ sf_txthresh_adjust(sc)
 	}
 }
=20
+#ifdef DEVICE_POLLING
+static void
+sf_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+{
+	struct sf_softc *sc =3D ifp->if_softc;
+
+	SF_LOCK(sc);
+	sf_poll_locked(ifp, cmd, count);
+	SF_UNLOCK(sc);
+}
+
+static void
+sf_poll_locked(struct ifnet *ifp, enum poll_cmd cmd, int count)
+{
+	struct sf_softc *sc =3D ifp->if_softc;
+
+	SF_LOCK_ASSERT(sc);
+
+	if (!(ifp->if_capenable & IFCAP_POLLING)) {
+		ether_poll_deregister(ifp);
+		cmd =3D POLL_DEREGISTER;
+	}
+
+	if (cmd =3D=3D POLL_DEREGISTER) {
+		/* Final call, enable interrupts. */
+		csr_write_4(sc, SF_IMR, SF_INTRS);
+		return;
+	}
+
+	sc->rxcycles =3D count;
+	sf_rxeof(sc);
+	sf_txeof(sc);
+	if (ifp->if_snd.ifq_head !=3D NULL)
+		sf_start(ifp);
+
+	if (cmd =3D=3D POLL_AND_CHECK_STATUS) {
+		u_int32_t status;
+
+		status =3D csr_read_4(sc, SF_ISR);
+		if (status)
+			csr_write_4(sc, SF_ISR, status);
+
+		if (status & SF_ISR_TX_LOFIFO)
+			sf_txthresh_adjust(sc);
+
+		if (status & SF_ISR_ABNORMALINTR) {
+			if (status & SF_ISR_STATSOFLOW) {
+				untimeout(sf_stats_update, sc,
+				    sc->sf_stat_ch);
+				sf_stats_update(sc);
+			} else
+				sf_init(sc);
+		}
+	}
+}
+#endif /* DEVICE_POLLING */
+
 static void
 sf_intr(arg)
 	void			*arg;
@@ -1023,6 +1102,19 @@ sf_intr(arg)
=20
 	ifp =3D &sc->arpcom.ac_if;
=20
+#ifdef DEVICE_POLLING
+	if (ifp->if_flags & IFF_POLLING)
+		goto done_locked;
+
+	if ((ifp->if_capenable & IFCAP_POLLING) &&
+	    ether_poll_register(sf_poll, ifp)) {
+		/* OK, disable interrupts. */
+		csr_write_4(sc, SF_IMR, 0x00000000);
+		sf_poll_locked(ifp, 0, 1);
+		goto done_locked;
+	}
+#endif /* DEVICE_POLLING */
+
 	if (!(csr_read_4(sc, SF_ISR_SHADOW) & SF_ISR_PCIINT_ASSERTED)) {
 		SF_UNLOCK(sc);
 		return;
@@ -1066,6 +1158,9 @@ sf_intr(arg)
 	if (ifp->if_snd.ifq_head !=3D NULL)
 		sf_start(ifp);
=20
+#ifdef DEVICE_POLLING
+done_locked:
+#endif /* DEVICE_POLLING */
 	SF_UNLOCK(sc);
 }
=20
@@ -1163,6 +1258,13 @@ sf_init(xsc)
 	/* Enable autopadding of short TX frames. */
 	SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_AUTOPAD);
=20
+#ifdef DEVICE_POLLING
+	/* Disable interrupts if we are polling. */
+	if (ifp->if_flags & IFF_POLLING)
+		csr_write_4(sc, SF_IMR, 0x00000000);
+	else
+#endif /* DEVICE_POLLING */
+
 	/* Enable interrupts. */
 	csr_write_4(sc, SF_IMR, SF_INTRS);
 	SF_SETBIT(sc, SF_PCI_DEVCFG, SF_PCIDEVCFG_INTR_ENB);
@@ -1339,6 +1441,10 @@ sf_stop(sc)
=20
 	untimeout(sf_stats_update, sc, sc->sf_stat_ch);
=20
+#ifdef DEVICE_POLLING
+	ether_poll_deregister(ifp);
+#endif /* DEVICE_POLLING */
+=09
 	csr_write_4(sc, SF_GEN_ETH_CTL, 0);
 	csr_write_4(sc, SF_CQ_CONSIDX, 0);
 	csr_write_4(sc, SF_CQ_PRODIDX, 0);
Index: if_sfreg.h
=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/ncvs/src/sys/pci/if_sfreg.h,v
retrieving revision 1.10
diff -u -p -r1.10 if_sfreg.h
--- if_sfreg.h	14 Nov 2003 19:00:31 -0000	1.10
+++ if_sfreg.h	10 Nov 2004 07:23:49 -0000
@@ -1046,6 +1046,9 @@ struct sf_softc {
 	int			sf_if_flags;
 	struct callout_handle	sf_stat_ch;
 	struct mtx		sf_mtx;
+#ifdef DEVICE_POLLING
+	int			rxcycles;
+#endif
 };
=20
=20

--Izn7cH1Com+I3R9J--

--HWvPVVuAAfuRc6SZ
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.6 (FreeBSD)

iD8DBQFBkhctbHYXjKDtmC0RAh2WAJ4xG1D8bQLoFZZKCKEg0llOxkEUUQCfQPnp
WuNWnrK/xCvTfsa/5bpDWeU=
=WoOS
-----END PGP SIGNATURE-----

--HWvPVVuAAfuRc6SZ--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20041110132709.GC9922>