summaryrefslogtreecommitdiffstats
path: root/sys/dev/nge
diff options
context:
space:
mode:
authorsimokawa <simokawa@FreeBSD.org>2002-11-06 15:50:32 +0000
committersimokawa <simokawa@FreeBSD.org>2002-11-06 15:50:32 +0000
commit131fe3293a00e11ceabd9867d8d9c613939fc186 (patch)
treef4d802d21c7b52af2066666d90ddf0b4a1e1a2ac /sys/dev/nge
parente6dea8f6330af598cd10c616e7e30614449c8d75 (diff)
downloadFreeBSD-src-131fe3293a00e11ceabd9867d8d9c613939fc186.zip
FreeBSD-src-131fe3293a00e11ceabd9867d8d9c613939fc186.tar.gz
Add support for DEVICE_POLLING.
PR: kern/44772 Submitted by: Takashi Oono <takashi@yha.att.ne.jp> MFC after: 1 week
Diffstat (limited to 'sys/dev/nge')
-rw-r--r--sys/dev/nge/if_nge.c76
-rw-r--r--sys/dev/nge/if_ngereg.h3
2 files changed, 79 insertions, 0 deletions
diff --git a/sys/dev/nge/if_nge.c b/sys/dev/nge/if_nge.c
index a99aea5..98f43f3 100644
--- a/sys/dev/nge/if_nge.c
+++ b/sys/dev/nge/if_nge.c
@@ -1340,6 +1340,14 @@ nge_rxeof(sc)
struct mbuf *m0 = NULL;
u_int32_t extsts;
+#ifdef DEVICE_POLLING
+ if (ifp->if_ipending & IFF_POLLING) {
+ if (sc->rxcycles <= 0)
+ break;
+ sc->rxcycles--;
+ }
+#endif /* DEVICE_POLLING */
+
cur_rx = &sc->nge_ldata->nge_rx_list[i];
rxstat = cur_rx->nge_rxstat;
extsts = cur_rx->nge_extsts;
@@ -1545,6 +1553,52 @@ nge_tick(xsc)
return;
}
+#ifdef DEVICE_POLLING
+static poll_handler_t nge_poll;
+
+static void
+nge_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+{
+ struct nge_softc *sc = ifp->if_softc;
+
+ if (cmd == POLL_DEREGISTER) { /* final call, enable interrupts */
+ CSR_WRITE_4(sc, NGE_IER, 1);
+ return;
+ }
+
+ /*
+ * On the nge, reading the status register also clears it.
+ * So before returning to intr mode we must make sure that all
+ * possible pending sources of interrupts have been served.
+ * In practice this means run to completion the *eof routines,
+ * and then call the interrupt routine
+ */
+ sc->rxcycles = count;
+ nge_rxeof(sc);
+ nge_txeof(sc);
+ if (ifp->if_snd.ifq_head != NULL)
+ nge_start(ifp);
+
+ if (sc->rxcycles > 0 || cmd == POLL_AND_CHECK_STATUS) {
+ u_int32_t status;
+
+ /* Reading the ISR register clears all interrupts. */
+ status = CSR_READ_4(sc, NGE_ISR);
+
+ if (status & (NGE_ISR_RX_ERR|NGE_ISR_RX_OFLOW))
+ nge_rxeof(sc);
+
+ if (status & (NGE_ISR_RX_IDLE))
+ NGE_SETBIT(sc, NGE_CSR, NGE_CSR_RX_ENABLE);
+
+ if (status & NGE_ISR_SYSERR) {
+ nge_reset(sc);
+ nge_init(sc);
+ }
+ }
+}
+#endif /* DEVICE_POLLING */
+
static void
nge_intr(arg)
void *arg;
@@ -1556,6 +1610,16 @@ nge_intr(arg)
sc = arg;
ifp = &sc->arpcom.ac_if;
+#ifdef DEVICE_POLLING
+ if (ifp->if_ipending & IFF_POLLING)
+ return;
+ if (ether_poll_register(nge_poll, ifp)) { /* ok, disable interrupts */
+ CSR_WRITE_4(sc, NGE_IER, 0);
+ nge_poll(ifp, 0, 1);
+ return;
+ }
+#endif /* DEVICE_POLLING */
+
/* Supress unwanted interrupts */
if (!(ifp->if_flags & IFF_UP)) {
nge_stop(sc);
@@ -1927,6 +1991,15 @@ nge_init(xsc)
* Enable interrupts.
*/
CSR_WRITE_4(sc, NGE_IMR, NGE_INTRS);
+#ifdef DEVICE_POLLING
+ /*
+ * ... only enable interrupts if we are not polling, make sure
+ * they are off otherwise.
+ */
+ if (ifp->if_ipending & IFF_POLLING)
+ CSR_WRITE_4(sc, NGE_IER, 0);
+ else
+#endif /* DEVICE_POLLING */
CSR_WRITE_4(sc, NGE_IER, 1);
/* Enable receiver and transmitter. */
@@ -2183,6 +2256,9 @@ nge_stop(sc)
}
untimeout(nge_tick, sc, sc->nge_stat_ch);
+#ifdef DEVICE_POLLING
+ ether_poll_deregister(ifp);
+#endif
CSR_WRITE_4(sc, NGE_IER, 0);
CSR_WRITE_4(sc, NGE_IMR, 0);
NGE_SETBIT(sc, NGE_CSR, NGE_CSR_TX_DISABLE|NGE_CSR_RX_DISABLE);
diff --git a/sys/dev/nge/if_ngereg.h b/sys/dev/nge/if_ngereg.h
index 13baa7b..27ea49a 100644
--- a/sys/dev/nge/if_ngereg.h
+++ b/sys/dev/nge/if_ngereg.h
@@ -659,6 +659,9 @@ struct nge_softc {
struct mtx nge_mtx;
u_int8_t nge_tbi;
struct ifmedia nge_ifmedia;
+#ifdef DEVICE_POLLING
+ int rxcycles;
+#endif
};
/*
OpenPOWER on IntegriCloud