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>