Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 13 Feb 2008 13:45:41 GMT
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 135313 for review
Message-ID:  <200802131345.m1DDjfp5079227@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=135313

Change 135313 by sephe@sephe_zealot:sam_wifi on 2008/02/13 13:45:11

	- Use mtx callout for amrr_ch and calib_ch.  This has side effect
	  to properly protect TX power calibration.
	- Release+hold mtx during ieee80211_find_rxnode() + ieee80211_input()
	  Possible races between lock/unlock sequence and ifp/ic's external
	  interfaces need more care thoughts.
	
	This commit makes bwi work with freebsd.

Affected files ...

.. //depot/projects/wifi/sys/dev/bwi/if_bwi.c#15 edit
.. //depot/projects/wifi/sys/dev/bwi/if_bwivar.h#10 edit

Differences ...

==== //depot/projects/wifi/sys/dev/bwi/if_bwi.c#15 (text+ko) ====

@@ -428,8 +428,8 @@
 	/* set these up early for if_printf use */
 	if_initname(ifp, device_get_name(dev), device_get_unit(dev));
 
-	callout_init(&sc->sc_calib_ch, CALLOUT_MPSAFE);
-	callout_init(&sc->sc_amrr_ch, CALLOUT_MPSAFE);
+	callout_init_mtx(&sc->sc_calib_ch, &sc->sc_mtx, 0);
+	callout_init_mtx(&sc->sc_amrr_ch, &sc->sc_mtx, 0);
 
 	/*
 	 * Add sysctl nodes
@@ -564,8 +564,12 @@
 	struct ifnet *ifp = sc->sc_ifp;
 	int i;
 
+	BWI_LOCK(sc);
 	bwi_stop(sc);
-	callout_stop(&sc->sc_amrr_ch);
+	BWI_UNLOCK(sc);
+
+	callout_drain(&sc->sc_calib_ch);
+	callout_drain(&sc->sc_amrr_ch);
 	ieee80211_ifdetach(&sc->sc_ic);
 
 	for (i = 0; i < sc->sc_nmac; ++i)
@@ -581,7 +585,9 @@
 void
 bwi_suspend(struct bwi_softc *sc)
 {
+	BWI_LOCK(sc);
 	bwi_stop(sc);
+	BWI_UNLOCK(sc);
 }
 
 void
@@ -599,7 +605,9 @@
 int
 bwi_shutdown(struct bwi_softc *sc)
 {
+	BWI_LOCK(sc);
 	bwi_stop(sc);
+	BWI_UNLOCK(sc);
 	return 0;
 }
 
@@ -1216,6 +1224,9 @@
 	if (error)
 		goto back;
 
+	/* Clear stop flag before enabling interrupt */
+	sc->sc_flags &= ~BWI_F_STOP;
+
 	/* Enable intrs */
 	bwi_enable_intrs(sc, BWI_INIT_INTRS);
 
@@ -1418,8 +1429,9 @@
 	struct bwi_mac *mac;
 	int i, error, pwr_off = 0;
 
-	BWI_LOCK(sc);
+	BWI_ASSERT_LOCKED(sc);
 
+	sc->sc_flags |= BWI_F_STOP;
 	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
 
 	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
@@ -1455,7 +1467,6 @@
 	sc->sc_tx_timer = 0;
 	ifp->if_timer = 0;
 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
-	BWI_UNLOCK(sc);
 }
 
 void
@@ -1469,7 +1480,8 @@
 
 	BWI_LOCK(sc);
 
-	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 ||
+	    (sc->sc_flags & BWI_F_STOP)) {
 		BWI_UNLOCK(sc);
 		return;
 	}
@@ -1552,8 +1564,13 @@
 	if (intr_status & BWI_INTR_NOISE)
 		if_printf(ifp, "intr noise\n");
 
-	if (txrx_intr_status[0] & BWI_TXRX_INTR_RX)
+	if (txrx_intr_status[0] & BWI_TXRX_INTR_RX) {
 		rx_data = sc->sc_rxeof(sc);
+		if (sc->sc_flags & BWI_F_STOP) {
+			BWI_UNLOCK(sc);
+			return;
+		}
+	}
 
 	if (txrx_intr_status[3] & BWI_TXRX_INTR_RX) {
 		sc->sc_txeof_status(sc);
@@ -1716,13 +1733,12 @@
 	struct bwi_softc *sc = arg;
 	struct ieee80211com *ic = &sc->sc_ic;
 
-	BWI_LOCK(sc);
+	BWI_ASSERT_LOCKED(sc);
+
 	if (ic->ic_opmode == IEEE80211_M_STA)
 		bwi_iter_func(sc, ic->ic_bss);
 	else
 		ieee80211_iterate_nodes(&ic->ic_sta, bwi_iter_func, sc);
-	BWI_UNLOCK(sc);
-
 	callout_reset(&sc->sc_amrr_ch, hz / 2, bwi_amrr_timeout, sc);
 }
 
@@ -2617,6 +2633,8 @@
 
 		m_adj(m, -IEEE80211_CRC_LEN);
 
+		BWI_UNLOCK(sc);
+
 		wh = mtod(m, struct ieee80211_frame_min *);
 		ni = ieee80211_find_rxnode(ic, wh);
 
@@ -2627,8 +2645,18 @@
 			rx_data = 1;
 			sc->sc_rx_rate = rate;
 		}
+
+		BWI_LOCK(sc);
 next:
 		idx = (idx + 1) % BWI_RX_NDESC;
+
+		if (sc->sc_flags & BWI_F_STOP) {
+			/*
+			 * Take the fast lane, don't do
+			 * any damage to softc
+			 */
+			return -1;
+		}
 	}
 
 	rbd->rbd_idx = idx;
@@ -2651,10 +2679,10 @@
 		  sizeof(struct bwi_desc32);
 
 	rx_data = bwi_rxeof(sc, end_idx);
-
-	CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_INDEX,
-		    end_idx * sizeof(struct bwi_desc32));
-
+	if (rx_data >= 0) {
+		CSR_WRITE_4(sc, rx_ctrl + BWI_RX32_INDEX,
+			    end_idx * sizeof(struct bwi_desc32));
+	}
 	return rx_data;
 }
 
@@ -3530,6 +3558,8 @@
 	struct bwi_softc *sc = xsc;
 	struct ieee80211com *ic = &sc->sc_ic;
 
+	BWI_ASSERT_LOCKED(sc);
+
 	if (ic->ic_state == IEEE80211_S_RUN) {
 		struct bwi_mac *mac;
 

==== //depot/projects/wifi/sys/dev/bwi/if_bwivar.h#10 (text+ko) ====

@@ -637,6 +637,7 @@
 
 #define BWI_F_BUS_INITED	0x1
 #define BWI_F_PROMISC		0x2
+#define BWI_F_STOP		0x4
 
 #define BWI_DBG_MAC		0x00000001
 #define BWI_DBG_RF		0x00000002



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200802131345.m1DDjfp5079227>