PERFORCE change 102928 for review

Paolo Pisati piso at FreeBSD.org
Tue Aug 1 14:15:54 UTC 2006


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

Change 102928 by piso at piso_newluxor on 2006/08/01 14:15:37

	Convert iwi to use a filter+ithread:
	
	to synchronize the filter with the ithread handler,
	and to avoid any race between different parts of the
	driver working on the same registers, use a spin lock
	placed into softc.

Affected files ...

.. //depot/projects/soc2006/intr_filter/dev/iwi/if_iwi.c#3 edit
.. //depot/projects/soc2006/intr_filter/dev/iwi/if_iwivar.h#2 edit

Differences ...

==== //depot/projects/soc2006/intr_filter/dev/iwi/if_iwi.c#3 (text+ko) ====

@@ -144,6 +144,7 @@
 static void	iwi_rx_intr(struct iwi_softc *);
 static void	iwi_tx_intr(struct iwi_softc *, struct iwi_tx_ring *);
 static void	iwi_intr(void *);
+static int      iwi_filter(void *);
 static int	iwi_cmd(struct iwi_softc *, uint8_t, void *, uint8_t);
 static void	iwi_write_ibssnode(struct iwi_softc *, const u_int8_t [], int);
 static int	iwi_tx_start(struct ifnet *, struct mbuf *,
@@ -262,7 +263,9 @@
 
 	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
 	    MTX_DEF);
-
+	mtx_init(&sc->sc_smtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
+	    MTX_SPIN);
+	
 	sc->sc_unr = new_unrhdr(1, IWI_MAX_IBSSNODE-1, &sc->sc_mtx);
 
 #if __FreeBSD_version >= 700000
@@ -465,7 +468,7 @@
 	 * Hook our interrupt after all initialization is complete.
 	 */
 	error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE,
-	    NULL, iwi_intr, sc, &sc->sc_ih);
+	    iwi_filter, iwi_intr, sc, &sc->sc_ih);
 	if (error != 0) {
 		device_printf(dev, "could not set up interrupt\n");
 		goto fail;
@@ -519,6 +522,7 @@
 		delete_unrhdr(sc->sc_unr);
 
 	mtx_destroy(&sc->sc_mtx);
+	mtx_destroy(&sc->sc_smtx);
 
 	return 0;
 }
@@ -1639,41 +1643,70 @@
 	iwi_start(ifp);
 }
 
-static void
-iwi_intr(void *arg)
+static int
+iwi_filter(void *arg)
 {
 	struct iwi_softc *sc = arg;
 	uint32_t r;
-	IWI_LOCK_DECL;
+	int ret = FILTER_HANDLED;
 
-	IWI_LOCK(sc);
-
+	mtx_lock_spin(&sc->sc_smtx);
 	if ((r = CSR_READ_4(sc, IWI_CSR_INTR)) == 0 || r == 0xffffffff) {
-		IWI_UNLOCK(sc);
-		return;
+		mtx_unlock_spin(&sc->sc_smtx);
+		return (FILTER_STRAY);
 	}
 
 	/* acknowledge interrupts */
 	CSR_WRITE_4(sc, IWI_CSR_INTR, r);
 
-	if (r & IWI_INTR_FATAL_ERROR) {
-		device_printf(sc->sc_dev, "firmware error\n");
-		taskqueue_enqueue(sc->sc_tq, &sc->sc_restarttask);
-	}
-
 	if (r & IWI_INTR_FW_INITED) {
 		if (!(r & (IWI_INTR_FATAL_ERROR | IWI_INTR_PARITY_ERROR)))
 			wakeup(sc);
+		r &= ~(IWI_INTR_FW_INITED | IWI_INTR_FATAL_ERROR | 
+		      IWI_INTR_PARITY_ERROR);
 	}
-
-	if (r & IWI_INTR_RADIO_OFF)
-		taskqueue_enqueue(sc->sc_tq, &sc->sc_radiofftask);
-
+	
 	if (r & IWI_INTR_CMD_DONE) {
 		sc->flags &= ~IWI_FLAG_BUSY;
 		wakeup(sc);
+		r &= ~IWI_INTR_CMD_DONE;
+	}
+
+	if (r & IWI_INTR_PARITY_ERROR) {
+		/* XXX rate-limit */
+		device_printf(sc->sc_dev, "parity error\n");
+		r &= ~IWI_INTR_PARITY_ERROR;
 	}
 
+	if (r) {	
+		/* disable interrupts */
+		CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, 0);
+		ret |= FILTER_SCHEDULE_THREAD;
+	}
+	sc->intr = r;
+	mtx_unlock_spin(&sc->sc_smtx);
+	return (ret);
+}
+
+static void
+iwi_intr(void *arg)
+{
+	struct iwi_softc *sc = arg;
+	uint32_t r;
+	IWI_LOCK_DECL;
+
+	IWI_LOCK(sc);
+	mtx_lock_spin(&sc->sc_smtx);
+	r = sc->intr;
+
+	if (r & IWI_INTR_FATAL_ERROR) {
+		device_printf(sc->sc_dev, "firmware error\n");
+		taskqueue_enqueue(sc->sc_tq, &sc->sc_restarttask);
+	}
+
+	if (r & IWI_INTR_RADIO_OFF)
+		taskqueue_enqueue(sc->sc_tq, &sc->sc_radiofftask);
+
 	if (r & IWI_INTR_TX1_DONE)
 		iwi_tx_intr(sc, &sc->txq[0]);
 
@@ -1689,12 +1722,9 @@
 	if (r & IWI_INTR_RX_DONE)
 		iwi_rx_intr(sc);
 
-	if (r & IWI_INTR_PARITY_ERROR) {
-		/* XXX rate-limit */
-		device_printf(sc->sc_dev, "parity error\n");
-	}
-
 	IWI_UNLOCK(sc);
+	CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, IWI_INTR_MASK);
+	mtx_unlock_spin(&sc->sc_smtx);
 }
 
 static int
@@ -2100,8 +2130,10 @@
 	uint32_t tmp;
 	int ntries;
 
+	mtx_lock_spin(&sc->sc_smtx);
 	/* disable interrupts */
 	CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, 0);
+	mtx_unlock_spin(&sc->sc_smtx);
 
 	CSR_WRITE_4(sc, IWI_CSR_RST, IWI_RST_STOP_MASTER);
 	for (ntries = 0; ntries < 5; ntries++) {
@@ -2116,6 +2148,7 @@
 	CSR_WRITE_4(sc, IWI_CSR_RST, tmp | IWI_RST_PRINCETON_RESET);
 
 	sc->flags &= ~IWI_FLAG_FW_INITED;
+	
 }
 
 static int
@@ -2502,8 +2535,10 @@
 	/* we're done with command blocks processing */
 	MEM_WRITE_4(sc, 0x3000a4, 0x540c00);
 
+	mtx_lock_spin(&sc->sc_smtx);
 	/* allow interrupts so we know when the firmware is ready */
 	CSR_WRITE_4(sc, IWI_CSR_INTR_MASK, IWI_INTR_MASK);
+	mtx_unlock_spin(&sc->sc_smtx);
 
 	/* tell the adapter to initialize the firmware */
 	CSR_WRITE_4(sc, IWI_CSR_RST, 0);

==== //depot/projects/soc2006/intr_filter/dev/iwi/if_iwivar.h#2 (text+ko) ====

@@ -123,6 +123,7 @@
 	device_t		sc_dev;
 
 	struct mtx		sc_mtx;
+	struct mtx		sc_smtx;
 	uint8_t			sc_mcast[IEEE80211_ADDR_LEN];
 	struct unrhdr		*sc_unr;
 	struct taskqueue	*sc_tq;		/* private task queue */
@@ -131,6 +132,7 @@
 #endif
 
 	uint32_t		flags;
+	uint32_t		intr;
 #define IWI_FLAG_FW_INITED	(1 << 0)
 #define IWI_FLAG_SCANNING	(1 << 1)
 #define	IWI_FLAG_FW_LOADING	(1 << 2)


More information about the p4-projects mailing list