Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 16 Feb 2008 08:00:43 GMT
From:      Sepherosa Ziehau <sephe@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 135480 for review
Message-ID:  <200802160800.m1G80hVf099479@repoman.freebsd.org>

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

Change 135480 by sephe@sephe_zealot:sam_wifi on 2008/02/16 08:00:42

	For MAC rev >= 5, if PHY error interrupt comes then reset the device
	but leave 802.11 state machine untouched.

Affected files ...

.. //depot/projects/wifi/sys/dev/bwi/bwimac.c#7 edit
.. //depot/projects/wifi/sys/dev/bwi/if_bwi.c#20 edit
.. //depot/projects/wifi/sys/dev/bwi/if_bwivar.h#12 edit

Differences ...

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

@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/dev/netif/bwi/bwimac.c,v 1.11 2008/01/15 09:01:13 sephe Exp $
+ * $DragonFly: src/sys/dev/netif/bwi/bwimac.c,v 1.13 2008/02/15 11:15:38 sephe Exp $
  */
 
 #include <sys/cdefs.h>
@@ -1649,6 +1649,8 @@
 		mac->mac_flags |= BWI_MAC_F_HAS_TXSTATS;
 		DPRINTF(sc, BWI_DBG_MAC | BWI_DBG_ATTACH, "%s\n",
 			"has TX stats");
+	} else {
+		mac->mac_flags |= BWI_MAC_F_PHYE_RESET;
 	}
 
 	device_printf(sc->sc_dev, "MAC: rev %u\n", rev);

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

@@ -31,8 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/dev/netif/bwi/if_bwi.c,v 1.18 2008/01/15 09:01:13 sephe Exp $
- * 1.8 is not merged
+ * $DragonFly: src/sys/dev/netif/bwi/if_bwi.c,v 1.19 2008/02/15 11:15:38 sephe Exp $
  */
 
 #include <sys/cdefs.h>
@@ -51,6 +50,7 @@
 #include <sys/sockio.h>
 #include <sys/sysctl.h>
 #include <sys/systm.h>
+#include <sys/taskqueue.h>
  
 #include <net/if.h>
 #include <net/if_dl.h>
@@ -96,6 +96,7 @@
 static void	bwi_init(void *);
 static int	bwi_ioctl(struct ifnet *, u_long, caddr_t);
 static void	bwi_start(struct ifnet *);
+static void	bwi_start_locked(struct ifnet *);
 static void	bwi_watchdog(struct ifnet *);
 static void	bwi_scan_start(struct ieee80211com *);
 static void	bwi_set_channel(struct ieee80211com *);
@@ -115,7 +116,10 @@
 static void	bwi_rx_radiotap(struct bwi_softc *, struct mbuf *,
 			struct bwi_rxbuf_hdr *, const void *, int, int);
 
-static void	bwi_stop(struct bwi_softc *);
+static void	bwi_restart(void *, int);
+static void	bwi_newstate_begin(struct bwi_softc *, enum ieee80211_state);
+static void	bwi_init_statechg(struct bwi_softc *, int);
+static void	bwi_stop(struct bwi_softc *, int);
 static int	bwi_newbuf(struct bwi_softc *, int, int);
 static int	bwi_encap(struct bwi_softc *, int, struct mbuf *,
 			  struct ieee80211_node *);
@@ -348,6 +352,15 @@
 	BWI_LOCK_INIT(sc);
 
 	/*
+	 * Initialize taskq and various tasks
+	 */
+	sc->sc_tq = taskqueue_create("bwi_taskq", M_NOWAIT | M_ZERO,
+		taskqueue_thread_enqueue, &sc->sc_tq);
+	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq",
+		device_get_nameunit(dev));
+	TASK_INIT(&sc->sc_restart_task, 0, bwi_restart, sc);
+
+	/*
 	 * Initialize sysctl variables
 	 */
 	sc->sc_fw_version = BWI_FW_VERSION3;
@@ -565,7 +578,7 @@
 	int i;
 
 	BWI_LOCK(sc);
-	bwi_stop(sc);
+	bwi_stop(sc, 1);
 	BWI_UNLOCK(sc);
 
 	callout_drain(&sc->sc_calib_ch);
@@ -576,6 +589,7 @@
 		bwi_mac_detach(&sc->sc_mac[i]);
 	bwi_dma_free(sc);
 	if_free(ifp);
+	taskqueue_free(sc->sc_tq);
 
 	BWI_LOCK_DESTROY(sc);
 
@@ -586,7 +600,7 @@
 bwi_suspend(struct bwi_softc *sc)
 {
 	BWI_LOCK(sc);
-	bwi_stop(sc);
+	bwi_stop(sc, 1);
 	BWI_UNLOCK(sc);
 }
 
@@ -606,7 +620,7 @@
 bwi_shutdown(struct bwi_softc *sc)
 {
 	BWI_LOCK(sc);
-	bwi_stop(sc);
+	bwi_stop(sc, 1);
 	BWI_UNLOCK(sc);
 	return 0;
 }
@@ -1166,7 +1180,12 @@
 static void
 bwi_init(void *xsc)
 {
-	struct bwi_softc *sc = xsc;
+	bwi_init_statechg(xsc, 1);
+}
+
+static void
+bwi_init_statechg(struct bwi_softc *sc, int statechg)
+{
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ifnet *ifp = ic->ic_ifp;
 	struct bwi_mac *mac;
@@ -1174,7 +1193,7 @@
 
 	BWI_LOCK(sc);
 
-	bwi_stop(sc);
+	bwi_stop(sc, statechg);
 
 	bwi_bbp_power_on(sc, BWI_CLOCK_MODE_FAST);
 
@@ -1233,15 +1252,24 @@
 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 
-	if (ic->ic_opmode != IEEE80211_M_MONITOR) {
-		if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
-			ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
+	if (statechg) {
+		if (ic->ic_opmode != IEEE80211_M_MONITOR) {
+			if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
+				ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
+		} else {
+			ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
+		}
 	} else {
-		ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
+		/* XXX */
+		if (ic->ic_state != IEEE80211_S_INIT)
+			bwi_set_channel(ic);
+		ieee80211_new_state(ic, ic->ic_state, -1);
 	}
 back:
 	if (error)
-		bwi_stop(sc);
+		bwi_stop(sc, 1);
+	else
+		bwi_start_locked(ifp);
 	BWI_UNLOCK(sc);
 }
 
@@ -1285,7 +1313,7 @@
 				bwi_init(sc);
 		} else {
 			if (ifp->if_drv_flags & IFF_DRV_RUNNING)
-				bwi_stop(sc);
+				bwi_stop(sc, 1);
 		}
 		break;
 	default:
@@ -1308,6 +1336,16 @@
 bwi_start(struct ifnet *ifp)
 {
 	struct bwi_softc *sc = ifp->if_softc;
+
+	BWI_LOCK(sc);
+	bwi_start_locked(ifp);
+	BWI_UNLOCK(sc);
+}
+
+static void
+bwi_start_locked(struct ifnet *ifp)
+{
+	struct bwi_softc *sc = ifp->if_softc;
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct bwi_txbuf_data *tbd = &sc->sc_tx_bdata[BWI_TX_DATA_RING];
 	struct ieee80211_frame *wh;
@@ -1317,12 +1355,9 @@
 	struct mbuf *m;
 	int trans, idx;
 
-	BWI_LOCK(sc);
 	if ((ifp->if_drv_flags & IFF_DRV_OACTIVE) ||
-	    (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
-		BWI_UNLOCK(sc);
+	    (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
 		return;
-	}
 
 	trans = 0;
 	idx = tbd->tbd_idx;
@@ -1404,7 +1439,6 @@
 
 	if (trans)
 		ifp->if_timer = 5;
-	BWI_UNLOCK(sc);
 }
 
 static void
@@ -1416,13 +1450,13 @@
 	if ((ifp->if_drv_flags & IFF_DRV_RUNNING)) {
 		if_printf(ifp, "watchdog timeout\n");
 		ifp->if_oerrors++;
-		/* TODO */
+		taskqueue_enqueue(sc->sc_tq, &sc->sc_restart_task);
 	}
 	BWI_UNLOCK(sc);
 }
 
 static void
-bwi_stop(struct bwi_softc *sc)
+bwi_stop(struct bwi_softc *sc, int statechg)
 {
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ifnet *ifp = ic->ic_ifp;
@@ -1432,7 +1466,10 @@
 	BWI_ASSERT_LOCKED(sc);
 
 	sc->sc_flags |= BWI_F_STOP;
-	ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
+	if (statechg)
+		ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
+	else
+		bwi_newstate_begin(sc, IEEE80211_S_INIT);
 
 	if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
 		KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
@@ -1473,6 +1510,7 @@
 bwi_intr(void *xsc)
 {
 	struct bwi_softc *sc = xsc;
+	struct bwi_mac *mac;
 	struct ifnet *ifp = sc->sc_ic.ic_ifp;
 	uint32_t intr_status;
 	uint32_t txrx_intr_status[BWI_TXRX_NRING];
@@ -1502,6 +1540,10 @@
 		return;
 	}
 
+	KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
+	    ("current regwin type %d", sc->sc_cur_regwin->rw_type));
+	mac = (struct bwi_mac *)sc->sc_cur_regwin;
+
 	txrx_error = 0;
 	DPRINTF(sc, BWI_DBG_INTR, "%s\n", "TX/RX intr");
 	for (i = 0; i < BWI_TXRX_NRING; ++i) {
@@ -1537,18 +1579,21 @@
 	/* Disable all interrupts */
 	bwi_disable_intrs(sc, BWI_ALL_INTRS);
 
-	if (intr_status & BWI_INTR_PHY_TXERR)
-		if_printf(ifp, "intr PHY TX error\n");
+	if (intr_status & BWI_INTR_PHY_TXERR) {
+		if (mac->mac_flags & BWI_MAC_F_PHYE_RESET) {
+			if_printf(ifp, "intr PHY TX error\n");
+			taskqueue_enqueue(sc->sc_tq, &sc->sc_restart_task);
+			BWI_UNLOCK(sc);
+			return;
+		}
+	}
 
 	if (txrx_error) {
 		/* TODO: reset device */
 	}
 
-	if (intr_status & BWI_INTR_TBTT) {
-		KASSERT(sc->sc_cur_regwin->rw_type == BWI_REGWIN_T_MAC,
-		    ("current regwin type %d", sc->sc_cur_regwin->rw_type));
-		bwi_mac_config_ps((struct bwi_mac *)sc->sc_cur_regwin);
-	}
+	if (intr_status & BWI_INTR_TBTT)
+		bwi_mac_config_ps(mac);
 
 	if (intr_status & BWI_INTR_EO_ATIM)
 		if_printf(ifp, "EO_ATIM\n");
@@ -1633,6 +1678,20 @@
 {
 }
 
+static void
+bwi_newstate_begin(struct bwi_softc *sc, enum ieee80211_state nstate)
+{
+	BWI_ASSERT_LOCKED(sc);
+
+	callout_stop(&sc->sc_calib_ch);
+	callout_stop(&sc->sc_amrr_ch);
+
+	bwi_led_newstate(sc, nstate);
+
+	if (nstate == IEEE80211_S_INIT)
+		sc->sc_txpwrcb_type = BWI_TXPWR_INIT;
+}
+
 static int
 bwi_newstate(struct ieee80211com *ic, enum ieee80211_state nstate, int arg)
 {
@@ -1644,10 +1703,7 @@
 
 	BWI_LOCK(sc);
 
-	callout_stop(&sc->sc_calib_ch);
-	callout_stop(&sc->sc_amrr_ch);
-
-	bwi_led_newstate(sc, nstate);
+	bwi_newstate_begin(sc, nstate);
 
 	if (nstate == IEEE80211_S_INIT)
 		goto back;
@@ -4041,3 +4097,12 @@
 	}
 	return txtime;
 }
+
+static void
+bwi_restart(void *xsc, int pending)
+{
+	struct bwi_softc *sc = xsc;
+
+	if_printf(sc->sc_ifp, "%s begin\n", __func__);
+	bwi_init_statechg(xsc, 0);
+}

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

@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  * 
- * $DragonFly: src/sys/dev/netif/bwi/if_bwivar.h,v 1.13 2008/01/15 09:01:13 sephe Exp $
+ * $DragonFly: src/sys/dev/netif/bwi/if_bwivar.h,v 1.14 2008/02/15 11:15:38 sephe Exp $
  * 1.9 is not merged
  */
 
@@ -476,6 +476,7 @@
 #define BWI_MAC_F_ENABLED	0x10
 #define BWI_MAC_F_LOCKED	0x20	/* for debug */
 #define BWI_MAC_F_TPCTL_ERROR	0x40
+#define BWI_MAC_F_PHYE_RESET	0x80
 
 #define BWI_CREATE_MAC(mac, sc, id, rev)	\
 do {						\
@@ -608,6 +609,9 @@
 	struct bwi_rx_radiotap_hdr sc_rx_th;
 	int			sc_rx_th_len;
 
+	struct taskqueue	*sc_tq;
+	struct task		sc_restart_task;
+
 	int			(*sc_newstate)
 				(struct ieee80211com *,
 				 enum ieee80211_state, int);



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