PERFORCE change 87637 for review

Sam Leffler sam at FreeBSD.org
Fri Dec 2 05:49:37 GMT 2005


http://perforce.freebsd.org/chv.cgi?CH=87637

Change 87637 by sam at sam_ebb on 2005/12/02 05:49:19

	device polling

Affected files ...

.. //depot/projects/wifi/sys/dev/ath/if_ath.c#118 edit

Differences ...

==== //depot/projects/wifi/sys/dev/ath/if_ath.c#118 (text+ko) ====

@@ -44,6 +44,9 @@
  * is greatly appreciated.
  */
 
+#ifdef HAVE_KERNEL_OPTION_HEADERS
+#include "opt_device_polling.h"
+#endif
 #include "opt_inet.h"
 
 #include <sys/param.h>
@@ -490,6 +493,7 @@
 	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
 	ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
 	IFQ_SET_READY(&ifp->if_snd);
+	ifp->if_capabilities |= IFCAP_POLLING;
 
 	ic->ic_ifp = ifp;
 	ic->ic_reset = ath_reset;
@@ -634,6 +638,10 @@
 	DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n",
 		__func__, ifp->if_flags);
 
+#ifdef DEVICE_POLLING
+	if (ifp->if_capenable & IFCAP_POLLING)
+		ether_poll_deregister(ifp);
+#endif
 	ath_stop(ifp);
 	bpfdetach(ifp);
 	/* 
@@ -705,34 +713,25 @@
 }
 
 /*
- * Interrupt handler.  Most of the actual processing is deferred.
+ * Set/enable interrupts. We actually enable
+ * interrupts only if we are not polling.
  */
-void
-ath_intr(void *arg)
+static __inline void
+ath_intrset(struct ath_softc *sc, u_int32_t mask)
+{
+	struct ath_hal *ah = sc->sc_ah;
+
+	if (sc->sc_ifp->if_capenable & IFCAP_POLLING)
+		mask &= ~HAL_INT_GLOBAL;
+	ath_hal_intrset(ah, mask);
+}
+
+static void
+ath_intr_body(struct ath_softc *sc, int count)
 {
-	struct ath_softc *sc = arg;
-	struct ifnet *ifp = sc->sc_ifp;
 	struct ath_hal *ah = sc->sc_ah;
 	HAL_INT status;
 
-	if (sc->sc_invalid) {
-		/*
-		 * The hardware is not ready/present, don't touch anything.
-		 * Note this can happen early on if the IRQ is shared.
-		 */
-		DPRINTF(sc, ATH_DEBUG_ANY, "%s: invalid; ignored\n", __func__);
-		return;
-	}
-	if (!ath_hal_intrpend(ah))		/* shared irq, not for us */
-		return;
-	if (!((ifp->if_flags & IFF_UP) && (ifp->if_drv_flags &
-	    IFF_DRV_RUNNING))) {
-		DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags 0x%x\n",
-			__func__, ifp->if_flags);
-		ath_hal_getisr(ah, &status);	/* clear ISR */
-		ath_hal_intrset(ah, 0);		/* disable further intr's */
-		return;
-	}
 	/*
 	 * Figure out the reason(s) for the interrupt.  Note
 	 * that the hal returns a pseudo-ISR that may include
@@ -800,11 +799,58 @@
 			 * clear whatever condition caused the interrupt.
 			 */
 			ath_hal_mibevent(ah, &sc->sc_halstats);
-			ath_hal_intrset(ah, sc->sc_imask);
+			ath_intrset(sc, sc->sc_imask);
 		}
 	}
 }
 
+/*
+ * Interrupt handler.  Most of the actual processing is deferred.
+ */
+void
+ath_intr(void *arg)
+{
+	struct ath_softc *sc = arg;
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ath_hal *ah = sc->sc_ah;
+
+	if (ifp->if_capenable & IFCAP_POLLING)
+		return;
+	if (sc->sc_invalid) {
+		/*
+		 * The hardware is not ready/present, don't touch anything.
+		 * Note this can happen early on if the IRQ is shared.
+		 */
+		DPRINTF(sc, ATH_DEBUG_ANY, "%s: invalid; ignored\n", __func__);
+		return;
+	}
+	if (!ath_hal_intrpend(ah))		/* shared irq, not for us */
+		return;
+	if ((ifp->if_flags & IFF_UP) == 0 ||
+	    (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+		HAL_INT status;
+
+		DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags 0x%x\n",
+			__func__, ifp->if_flags);
+		ath_hal_getisr(ah, &status);	/* clear ISR */
+		ath_hal_intrset(ah, 0);		/* disable further intr's */
+		return;
+	}
+	ath_intr_body(sc, 1);
+}
+
+/*
+ * Polling callback.
+ */
+static void     
+ath_poll(struct ifnet *ifp, enum poll_cmd cmd, int count)
+{
+        struct ath_softc *sc = ifp->if_softc;
+
+	if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+		ath_intr_body(sc, count);
+}
+
 static void
 ath_fatal_proc(void *arg, int pending)
 {
@@ -951,7 +997,7 @@
 	 */
 	if (sc->sc_needmib && ic->ic_opmode == IEEE80211_M_STA)
 		sc->sc_imask |= HAL_INT_MIB;
-	ath_hal_intrset(ah, sc->sc_imask);
+	ath_intrset(sc, sc->sc_imask);
 
 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
 	ic->ic_state = IEEE80211_S_INIT;
@@ -1093,7 +1139,7 @@
 	ath_chan_change(sc, c);
 	if (ic->ic_state == IEEE80211_S_RUN)
 		ath_beacon_config(sc);	/* restart beacons */
-	ath_hal_intrset(ah, sc->sc_imask);
+	ath_intrset(sc, sc->sc_imask);
 
 	ath_start(ifp);			/* restart xmit */
 	return 0;
@@ -2686,7 +2732,7 @@
 		ath_hal_intrset(ah, 0);
 		ath_hal_beacontimers(ah, &bs);
 		sc->sc_imask |= HAL_INT_BMISS;
-		ath_hal_intrset(ah, sc->sc_imask);
+		ath_intrset(sc, sc->sc_imask);
 	} else {
 		ath_hal_intrset(ah, 0);
 		if (nexttbtt == intval)
@@ -2725,7 +2771,7 @@
 		}
 		ath_hal_beaconinit(ah, nexttbtt, intval);
 		sc->sc_bmisscount = 0;
-		ath_hal_intrset(ah, sc->sc_imask);
+		ath_intrset(sc, sc->sc_imask);
 		/*
 		 * When using a self-linked beacon descriptor in
 		 * ibss mode load it once here.
@@ -4705,7 +4751,7 @@
 		/*
 		 * Re-enable interrupts.
 		 */
-		ath_hal_intrset(ah, sc->sc_imask);
+		ath_intrset(sc, sc->sc_imask);
 	}
 	return 0;
 }
@@ -4852,7 +4898,7 @@
 		/*
 		 * NB: disable interrupts so we don't rx frames.
 		 */
-		ath_hal_intrset(ah, sc->sc_imask &~ HAL_INT_GLOBAL);
+		ath_intrset(sc, sc->sc_imask &~ HAL_INT_GLOBAL);
 		/*
 		 * Notify the rate control algorithm.
 		 */
@@ -4948,8 +4994,7 @@
 		sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER;
 		sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER;
 	} else {
-		ath_hal_intrset(ah,
-			sc->sc_imask &~ (HAL_INT_SWBA | HAL_INT_BMISS));
+		ath_intrset(sc, sc->sc_imask &~ (HAL_INT_SWBA | HAL_INT_BMISS));
 		sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS);
 	}
 done:
@@ -5470,6 +5515,22 @@
 	case SIOCGATHDIAG:
 		error = ath_ioctl_diag(sc, (struct ath_diag *) ifr);
 		break;
+	case SIOCSIFCAP:
+#ifdef DEVICE_POLLING
+		if ((ifr->ifr_reqcap ^ ifp->if_capenable) & IFCAP_POLLING) {
+			if (ifr->ifr_reqcap & IFCAP_POLLING) {
+				error = ether_poll_register(ath_poll, ifp);
+				if (!error)
+					ifp->if_capenable |= IFCAP_POLLING;
+			} else {
+				error = ether_poll_deregister(ifp);
+				/* NB: enable interrupts even if error */
+				ifp->if_capenable &= ~IFCAP_POLLING;
+			}
+			ath_intrset(sc, sc->sc_imask);
+		}
+#endif
+		break;
 	default:
 		error = ieee80211_ioctl(ic, cmd, data);
 		if (error == ENETRESET) {


More information about the p4-projects mailing list