From owner-freebsd-net@FreeBSD.ORG Sat Apr 10 15:21:17 2004 Return-Path: Delivered-To: freebsd-net@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id ACAE216A4CE; Sat, 10 Apr 2004 15:21:17 -0700 (PDT) Received: from tigra.ip.net.ua (tigra.ip.net.ua [82.193.96.10]) by mx1.FreeBSD.org (Postfix) with ESMTP id 8880E43D4C; Sat, 10 Apr 2004 15:21:16 -0700 (PDT) (envelope-from ru@ip.net.ua) Received: from heffalump.ip.net.ua (heffalump.ip.net.ua [82.193.96.213]) by tigra.ip.net.ua (8.12.11/8.12.11) with ESMTP id i3AMPmbU062736 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Sun, 11 Apr 2004 01:25:50 +0300 (EEST) (envelope-from ru@ip.net.ua) Received: (from ru@localhost) by heffalump.ip.net.ua (8.12.11/8.12.11) id i3AMLCIN023197; Sun, 11 Apr 2004 01:21:12 +0300 (EEST) (envelope-from ru) Date: Sun, 11 Apr 2004 01:21:12 +0300 From: Ruslan Ermilov To: net@FreeBSD.org Message-ID: <20040410222112.GA23046@ip.net.ua> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="61jdw2sOBCFtR2d/" Content-Disposition: inline User-Agent: Mutt/1.5.6i X-Virus-Scanned: by amavisd-new X-Spam-Checker-Version: SpamAssassin 2.55 (1.174.2.19-2003-05-19-exp) cc: Luigi Rizzo Subject: Per-interface polling(4) status X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 10 Apr 2004 22:21:17 -0000 --61jdw2sOBCFtR2d/ Content-Type: multipart/mixed; boundary="EVF5PPMfhYS0aIcm" Content-Disposition: inline --EVF5PPMfhYS0aIcm Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Dear networkers, Like I mumbled in another email, I've started working on a small project that (when done) will allow for a per-interface polling(4) status to be changed in run-time. Attached is a proof of the concept patch, that currently has support for the dc(4) driver only (basically because I have this card plugged into my notebook). That's how it looks like in the real life. + Turning individual polling status off/on: : # sysctl -n kern.polling.enable : 1 : # sysctl -n kern.polling.handlers : 1 : # ifconfig dc0 -polling : # ifconfig dc0 ether : dc0: flags=3D8843 mtu 1500 : ether 00:10:a4:c0:c0:45 : # sysctl -n kern.polling.handlers : 0 : # ifconfig dc0 polling : # ifconfig dc0 ether : dc0: flags=3D18843 mtu 15= 00 : ether 00:10:a4:c0:c0:45 : # sysctl -n kern.polling.handlers : 1 + Suspending all polling activity: : # sysctl -n kern.polling.handlers : 1 : # sysctl kern.polling.enable=3D0 : kern.polling.enable: 1 -> 0 : # sysctl -n kern.polling.handlers : 0 : # ifconfig dc0 ether : dc0: flags=3D18843 mtu 15= 00 : ether 00:10:a4:c0:c0:45 (Note that the IFF_POLLING flag on the interface was not flipped, please seek below for an explanation.) + Resuming all polling activity: : # sysctl kern.polling.enable=3D1 : kern.polling.enable: 0 -> 1 : # sysctl -n kern.polling.handlers : 1 : # ifconfig dc0 ether : dc0: flags=3D18843 mtu 15= 00 : ether 00:10:a4:c0:c0:45 The patch changes the current meaning of the IFF_POLLING flag indicating the polling status of this interface to a per-interface option indicating the willingness of the given interface to participate in the polling(4). It's completely under a control of the configuration software, normally ifconfig(8). All polling(4) activity can still be suspended by setting the sysctl kern.polling.enable to zero, and resumed by setting it to non-zero. Driver notes. The changes to drivers to catch up with this change are minimal and consist in: - Adding the "polling" boolean member to the softc structure, indicating if polling is active on this interface (the old meaning of the IFF_POLLING flag); - Replacing the (ifp->if_flags & IFF_POLLING) conditionals with (sc->polling); - Adding a few lines of code to support switching the polling status of the interface in the intr() and poll() functions. Points I'm not sure about, and would like to hear the comments on: - Should the initial polling status be on or off, on interfaces that support it? The current version of the patch makes it off by default. - Should I add the code to ether_poll_register() to sanity check that the interface doesn't attempt to register itself more than once? (As an aside, the patch for kern_poll.c also fixes a minor bug to ensure that ``poll_burst <=3D poll_burst_max'' is always true.) Cheers, --=20 Ruslan Ermilov ru@FreeBSD.org FreeBSD committer --EVF5PPMfhYS0aIcm Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename=p Content-Transfer-Encoding: quoted-printable Index: sbin/ifconfig/ifconfig.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/sbin/ifconfig/ifconfig.c,v retrieving revision 1.99 diff -u -p -r1.99 ifconfig.c --- sbin/ifconfig/ifconfig.c 12 Mar 2004 23:52:32 -0000 1.99 +++ sbin/ifconfig/ifconfig.c 9 Apr 2004 20:00:14 -0000 @@ -195,6 +195,8 @@ struct cmd { { "-arp", IFF_NOARP, setifflags }, { "debug", IFF_DEBUG, setifflags }, { "-debug", -IFF_DEBUG, setifflags }, + { "polling", IFF_POLLING, setifflags }, + { "-polling", -IFF_POLLING, setifflags }, { "promisc", IFF_PPROMISC, setifflags }, { "-promisc", -IFF_PPROMISC, setifflags }, { "add", IFF_UP, notealias }, Index: sys/net/if.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/net/if.h,v retrieving revision 1.83 diff -u -p -r1.83 if.h --- sys/net/if.h 31 Oct 2003 18:32:08 -0000 1.83 +++ sys/net/if.h 9 Apr 2004 19:55:15 -0000 @@ -155,8 +155,7 @@ struct if_data { /* flags set internally only: */ #define IFF_CANTCHANGE \ (IFF_BROADCAST|IFF_POINTOPOINT|IFF_RUNNING|IFF_OACTIVE|\ - IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI|IFF_SMART|IFF_PROMISC|\ - IFF_POLLING) + IFF_SIMPLEX|IFF_MULTICAST|IFF_ALLMULTI|IFF_SMART|IFF_PROMISC) =20 /* * Some convenience macros used for setting ifi_baudrate. Index: sys/kern/kern_poll.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/kern/kern_poll.c,v retrieving revision 1.16 diff -u -p -r1.16 kern_poll.c --- sys/kern/kern_poll.c 25 Jan 2004 03:54:52 -0000 1.16 +++ sys/kern/kern_poll.c 10 Apr 2004 21:10:12 -0000 @@ -363,6 +363,8 @@ netisr_poll(void) poll_burst_max =3D MIN_POLL_BURST_MAX; else if (poll_burst_max > MAX_POLL_BURST_MAX) poll_burst_max =3D MAX_POLL_BURST_MAX; + if (poll_burst > poll_burst_max) + poll_burst =3D poll_burst_max; =20 if (poll_each_burst < 1) poll_each_burst =3D 1; @@ -384,7 +386,6 @@ netisr_poll(void) for (i =3D 0 ; i < poll_handlers ; i++) { if (pr[i].handler && pr[i].ifp->if_flags & IFF_RUNNING) { - pr[i].ifp->if_flags &=3D ~IFF_POLLING; pr[i].handler(pr[i].ifp, POLL_DEREGISTER, 1); } pr[i].handler=3DNULL; @@ -416,8 +417,6 @@ ether_poll_register(poll_handler_t *h, s return 0; if ( !(ifp->if_flags & IFF_UP) ) /* must be up */ return 0; - if (ifp->if_flags & IFF_POLLING) /* already polling */ - return 0; =20 s =3D splhigh(); if (poll_handlers >=3D POLL_LIST_LEN) { @@ -441,7 +440,6 @@ ether_poll_register(poll_handler_t *h, s pr[poll_handlers].handler =3D h; pr[poll_handlers].ifp =3D ifp; poll_handlers++; - ifp->if_flags |=3D IFF_POLLING; splx(s); if (idlepoll_sleeping) wakeup(&idlepoll_sleeping); @@ -450,9 +448,6 @@ ether_poll_register(poll_handler_t *h, s =20 /* * Remove interface from the polling list. Normally called by *_stop(). - * It is not an error to call it with IFF_POLLING clear, the call is - * sufficiently rare to be preferable to save the space for the extra - * test in each driver in exchange of one additional function call. */ int ether_poll_deregister(struct ifnet *ifp) @@ -460,14 +455,13 @@ ether_poll_deregister(struct ifnet *ifp) int i; =20 mtx_lock(&Giant); - if ( !ifp || !(ifp->if_flags & IFF_POLLING) ) { + if (!ifp) { mtx_unlock(&Giant); return 0; } for (i =3D 0 ; i < poll_handlers ; i++) if (pr[i].ifp =3D=3D ifp) /* found it */ break; - ifp->if_flags &=3D ~IFF_POLLING; /* found or not... */ if (i =3D=3D poll_handlers) { mtx_unlock(&Giant); printf("ether_poll_deregister: ifp not found!!!\n"); Index: sys/pci/if_dc.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_dc.c,v retrieving revision 1.141 diff -u -p -r1.141 if_dc.c --- sys/pci/if_dc.c 17 Mar 2004 17:50:53 -0000 1.141 +++ sys/pci/if_dc.c 10 Apr 2004 21:12:01 -0000 @@ -2747,7 +2747,7 @@ dc_rxeof(struct dc_softc *sc) while (!(le32toh(sc->dc_ldata->dc_rx_list[i].dc_status) & DC_RXSTAT_OWN)) { #ifdef DEVICE_POLLING - if (ifp->if_flags & IFF_POLLING) { + if (sc->polling) { if (sc->rxcycles <=3D 0) break; sc->rxcycles--; @@ -3083,7 +3083,12 @@ dc_poll(struct ifnet *ifp, enum poll_cmd { struct dc_softc *sc =3D ifp->if_softc; =20 + if (!(ifp->if_flags & IFF_POLLING)) { + ether_poll_deregister(ifp); + cmd =3D POLL_DEREGISTER; + } if (cmd =3D=3D POLL_DEREGISTER) { /* final call, enable interrupts */ + sc->polling =3D 0; /* Re-enable interrupts. */ CSR_WRITE_4(sc, DC_IMR, DC_INTRS); return; @@ -3151,9 +3156,12 @@ dc_intr(void *arg) DC_LOCK(sc); ifp =3D &sc->arpcom.ac_if; #ifdef DEVICE_POLLING - if (ifp->if_flags & IFF_POLLING) + if (sc->polling) goto done; - if (ether_poll_register(dc_poll, ifp)) { /* ok, disable interrupts */ + if ((ifp->if_flags & IFF_POLLING) && + ether_poll_register(dc_poll, ifp)) { + /* ok, disable interrupts */ + sc->polling =3D 1; CSR_WRITE_4(sc, DC_IMR, 0x00000000); goto done; } @@ -3544,7 +3552,7 @@ dc_init(void *xsc) * the case of polling. Some cards (e.g. fxp) turn interrupts on * after a reset. */ - if (ifp->if_flags & IFF_POLLING) + if (sc->polling) CSR_WRITE_4(sc, DC_IMR, 0x00000000); else #endif @@ -3754,7 +3762,10 @@ dc_stop(struct dc_softc *sc) =20 ifp->if_flags &=3D ~(IFF_RUNNING | IFF_OACTIVE); #ifdef DEVICE_POLLING - ether_poll_deregister(ifp); + if (sc->polling) { + ether_poll_deregister(ifp); + sc->polling =3D 0; + } #endif =20 DC_CLRBIT(sc, DC_NETCFG, (DC_NETCFG_RX_ON | DC_NETCFG_TX_ON)); Index: sys/pci/if_dcreg.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_dcreg.h,v retrieving revision 1.41 diff -u -p -r1.41 if_dcreg.h --- sys/pci/if_dcreg.h 8 Jan 2004 06:22:15 -0000 1.41 +++ sys/pci/if_dcreg.h 10 Apr 2004 07:53:23 -0000 @@ -754,6 +754,7 @@ struct dc_softc { #endif struct mtx dc_mtx; #ifdef DEVICE_POLLING + int polling; int rxcycles; /* ... when polling */ #endif int suspended; /* 0 =3D normal 1 =3D suspended */ --EVF5PPMfhYS0aIcm-- --61jdw2sOBCFtR2d/ Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.2.4 (FreeBSD) iD8DBQFAeHNYUkv4P6juNwoRAihdAJwLsrPE8SvldV8dW+JZXLRelpiLvgCfZz0P hythFTA9YE/s8Wcod9clV1U= =IWSh -----END PGP SIGNATURE----- --61jdw2sOBCFtR2d/--