sf(4) device polling
Christian Brueffer
chris at unixpages.org
Wed Nov 10 05:27:19 PST 2004
On Tue, Nov 09, 2004 at 05:49:42PM +0100, Christian Brueffer wrote:
> Hi,
>
> 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.
>
Here's a new patch from Ruslan, which corrects some stuff and adds
missing error recovery.
- Christian
--
Christian Brueffer chris at unixpages.org brueffer at FreeBSD.org
GPG Key: http://people.freebsd.org/~brueffer/brueffer.key.asc
GPG Fingerprint: A5C8 2099 19FF AACA F41B B29B 6C76 178C A0ED 982D
-------------- next part --------------
Index: if_sf.c
===================================================================
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 */
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 = device_get_softc(sc->sf_miibus);
error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command);
break;
+ case SIOCSIFCAP:
+ ifp->if_capenable &= ~IFCAP_POLLING;
+ ifp->if_capenable |= ifr->ifr_reqcap & IFCAP_POLLING;
+ break;
default:
error = ether_ioctl(ifp, command, data);
break;
@@ -714,6 +724,10 @@ sf_attach(dev)
ifp->if_init = sf_init;
ifp->if_baudrate = 10000000;
ifp->if_snd.ifq_maxlen = SF_TX_DLIST_CNT - 1;
+#ifdef DEVICE_POLLING
+ ifp->if_capabilities |= IFCAP_POLLING;
+#endif /* DEVICE_POLLING */
+ ifp->if_capenable = ifp->if_capabilities;
/*
* Call MI attach routine.
@@ -903,6 +917,14 @@ sf_rxeof(sc)
while (cmpconsidx != cmpprodidx) {
struct mbuf *m0;
+#ifdef DEVICE_POLLING
+ if (ifp->if_flags & IFF_POLLING) {
+ if (sc->rxcycles <= 0)
+ break;
+ sc->rxcycles--;
+ }
+#endif /* DEVICE_POLLING */
+
cur_rx = &sc->sf_ldata->sf_rx_clist[cmpconsidx];
desc = &sc->sf_ldata->sf_rx_dlist_big[cur_rx->sf_endidx];
m = desc->sf_mbuf;
@@ -1010,6 +1032,63 @@ sf_txthresh_adjust(sc)
}
}
+#ifdef DEVICE_POLLING
+static void
+sf_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+{
+ struct sf_softc *sc = 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 = ifp->if_softc;
+
+ SF_LOCK_ASSERT(sc);
+
+ if (!(ifp->if_capenable & IFCAP_POLLING)) {
+ ether_poll_deregister(ifp);
+ cmd = POLL_DEREGISTER;
+ }
+
+ if (cmd == POLL_DEREGISTER) {
+ /* Final call, enable interrupts. */
+ csr_write_4(sc, SF_IMR, SF_INTRS);
+ return;
+ }
+
+ sc->rxcycles = count;
+ sf_rxeof(sc);
+ sf_txeof(sc);
+ if (ifp->if_snd.ifq_head != NULL)
+ sf_start(ifp);
+
+ if (cmd == POLL_AND_CHECK_STATUS) {
+ u_int32_t status;
+
+ status = 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)
ifp = &sc->arpcom.ac_if;
+#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 != NULL)
sf_start(ifp);
+#ifdef DEVICE_POLLING
+done_locked:
+#endif /* DEVICE_POLLING */
SF_UNLOCK(sc);
}
@@ -1163,6 +1258,13 @@ sf_init(xsc)
/* Enable autopadding of short TX frames. */
SF_SETBIT(sc, SF_MACCFG_1, SF_MACCFG1_AUTOPAD);
+#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)
untimeout(sf_stats_update, sc, sc->sf_stat_ch);
+#ifdef DEVICE_POLLING
+ ether_poll_deregister(ifp);
+#endif /* DEVICE_POLLING */
+
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
===================================================================
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
};
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 187 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-net/attachments/20041110/8aa8f250/attachment.bin
More information about the freebsd-net
mailing list