Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 5 Mar 2008 01:18:30 GMT
From:      Andrew Thompson <thompsa@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 136876 for review
Message-ID:  <200803050118.m251IU0C080806@repoman.freebsd.org>

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

Change 136876 by thompsa@thompsa_burger on 2008/03/05 01:18:00

	Checkpoint work
	 - locking fixes
	 - net80211 state fixes
	 - ditch second taskq 
	 - hook up hw kill switch
	 - dont config firmware between each scan
	 - consolidate timers
	
	Parts of this are from bensjc and sam.

Affected files ...

.. //depot/projects/wifi/sys/dev/wpi/if_wpi.c#14 edit
.. //depot/projects/wifi/sys/dev/wpi/if_wpireg.h#3 edit
.. //depot/projects/wifi/sys/dev/wpi/if_wpivar.h#5 edit

Differences ...

==== //depot/projects/wifi/sys/dev/wpi/if_wpi.c#14 (text+ko) ====

@@ -16,10 +16,10 @@
  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  */
 
-#define VERSION "20071218-p4"
+#define VERSION "20071127"
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD: src/sys/dev/wpi/if_wpi.c,v 1.8 2008/02/01 19:36:25 phk Exp $");
+__FBSDID("$FreeBSD: src/sys/dev/wpi/if_wpi.c,v 1.5.2.2 2008/02/02 06:49:57 sam Exp $");
 
 /*
  * Driver for Intel PRO/Wireless 3945ABG 802.11 network adapters.
@@ -75,15 +75,8 @@
 #include <sys/linker.h>
 #include <sys/firmware.h>
 
-#if (__FreeBSD_version > 700000)
-#define WPI_CURRENT
-#endif
-
 #include <machine/bus.h>
 #include <machine/resource.h>
-#ifndef WPI_CURRENT
-#include <machine/clock.h>
-#endif
 #include <sys/rman.h>
 
 #include <dev/pci/pcireg.h>
@@ -129,7 +122,6 @@
 	WPI_DEBUG_TEMP		= 0x00000200,   /* TXPower/Temp Calibration */
 	WPI_DEBUG_OPS		= 0x00000400,   /* wpi_ops taskq debug */
 	WPI_DEBUG_WATCHDOG	= 0x00000800,   /* Watch dog debug */
-	WPI_DEBUG_HWSWITCH	= 0x00001000,   /* Watch hwswitch callout */
 	WPI_DEBUG_ANY		= 0xffffffff
 };
 
@@ -200,8 +192,8 @@
 static void	wpi_intr(void *);
 static void	wpi_ops(void *, int);
 static uint8_t	wpi_plcp_signal(int);
-static int	wpi_queue_cmd(struct wpi_softc *, int);
-static void	wpi_tick(void *);
+static int	wpi_queue_cmd(struct wpi_softc *, int, int);
+static void	wpi_watchdog(void *);
 static int	wpi_tx_data(struct wpi_softc *, struct mbuf *,
 		    struct ieee80211_node *, int);
 static void	wpi_start(struct ifnet *);
@@ -210,9 +202,7 @@
 static void	wpi_set_channel(struct ieee80211com *);
 static void	wpi_scan_curchan(struct ieee80211com *, unsigned long);
 static void	wpi_scan_mindwell(struct ieee80211com *);
-static void	wpi_watchdog(struct ifnet *);
 static int	wpi_ioctl(struct ifnet *, u_long, caddr_t);
-static void	wpi_restart(void *, int);
 static void	wpi_read_eeprom(struct wpi_softc *);
 static void	wpi_read_eeprom_channels(struct wpi_softc *, int);
 static void	wpi_read_eeprom_group(struct wpi_softc *, int);
@@ -232,6 +222,7 @@
 static int	wpi_reset(struct wpi_softc *);
 static void	wpi_hw_config(struct wpi_softc *);
 static void	wpi_init(void *);
+static void	wpi_init_locked(struct wpi_softc *, int);
 static void	wpi_stop(struct wpi_softc *);
 static void	wpi_stop_locked(struct wpi_softc *);
 static void	wpi_iter_func(void *, struct ieee80211_node *);
@@ -243,7 +234,6 @@
 static void	wpi_power_calibration(struct wpi_softc *, int);
 static int	wpi_get_power_index(struct wpi_softc *,
 		    struct wpi_power_group *, struct ieee80211_channel *, int);
-static void	wpi_radio(void *);
 static const char *wpi_cmd_str(int);
 static int wpi_probe(device_t);
 static int wpi_attach(device_t);
@@ -314,17 +304,12 @@
 static int
 wpi_load_firmware(struct wpi_softc *sc)
 {
-#ifdef WPI_CURRENT
 	const struct firmware *fp ;
-#else
-	struct firmware *fp;
-#endif
 	struct wpi_dma_info *dma = &sc->fw_dma;
 	const struct wpi_firmware_hdr *hdr;
 	const uint8_t *itext, *idata, *rtext, *rdata, *btext;
 	uint32_t itextsz, idatasz, rtextsz, rdatasz, btextsz;
 	int error;
-	WPI_LOCK_DECL;
 
 	DPRINTFN(WPI_DEBUG_FIRMWARE,
 	    ("Attempting Loading Firmware from wpi_fw module\n"));
@@ -480,7 +465,6 @@
 static void
 wpi_unload_firmware(struct wpi_softc *sc)
 {
-	WPI_LOCK_DECL;
 
 	if (sc->fw_fp) {
 		WPI_UNLOCK(sc);
@@ -527,23 +511,16 @@
 	    taskqueue_thread_enqueue, &sc->sc_tq);
 	taskqueue_start_threads(&sc->sc_tq, 1, PI_NET, "%s taskq",
 	    device_get_nameunit(dev));
-
-	sc->sc_tq2 = taskqueue_create("wpi_taskq2", M_NOWAIT | M_ZERO,
-	    taskqueue_thread_enqueue, &sc->sc_tq2);
-	taskqueue_start_threads(&sc->sc_tq2, 1, PI_NET, "%s taskq2",
-	    device_get_nameunit(dev));
 #else
 #error "Sorry, this driver is not yet ready for FreeBSD < 7.0"
 #endif
 
 	/* Create the tasks that can be queued */
 	TASK_INIT(&sc->sc_opstask, 0, wpi_ops, sc);
-	TASK_INIT(&sc->sc_restarttask, 0, wpi_restart, sc);
 
 	WPI_LOCK_INIT(sc);
 	WPI_CMD_LOCK_INIT(sc);
 
-	callout_init_mtx(&sc->hwswitch_to, &sc->sc_mtx, 0);
 	callout_init_mtx(&sc->calib_to, &sc->sc_mtx, 0);
 	callout_init_mtx(&sc->watchdog_to, &sc->sc_mtx, 0);
 
@@ -739,17 +716,15 @@
 	/*
 	 * Hook our interrupt after all initialization is complete.
 	 */
-	error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET |INTR_MPSAFE ,
-#ifdef WPI_CURRENT
-	    NULL,
-#endif
-	    wpi_intr, sc, &sc->sc_ih);
+	error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET |INTR_MPSAFE,
+	    NULL, wpi_intr, sc, &sc->sc_ih);
 	if (error != 0) {
 		device_printf(dev, "could not set up interrupt\n");
 		goto fail;
 	}
 
-	ieee80211_announce(ic);
+	if (bootverbose)
+		ieee80211_announce(ic);
 #ifdef XXX_DEBUG
 	ieee80211_announce_channels(ic);
 #endif
@@ -767,13 +742,11 @@
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ifnet *ifp = ic->ic_ifp;
 	int ac;
-	WPI_LOCK_DECL;
 
 	if (ifp != NULL) {
 		wpi_stop(sc);
 		callout_drain(&sc->watchdog_to);
 		callout_drain(&sc->calib_to);
-		callout_drain(&sc->hwswitch_to);
 		bpfdetach(ifp);
 		ieee80211_ifdetach(ic);
 	}
@@ -809,7 +782,6 @@
 		if_free(ifp);
 
 	taskqueue_free(sc->sc_tq);
-	taskqueue_free(sc->sc_tq2);
 
 	WPI_LOCK_DESTROY(sc);
 	WPI_CMD_LOCK_DESTROY(sc);
@@ -983,14 +955,18 @@
 {
 	struct wpi_rbuf *rbuf = arg;
 	struct wpi_softc *sc = rbuf->sc;
-	WPI_LOCK_DECL;
+	int waslocked;
 
-	WPI_LOCK(sc);
+	/* XXX Horrible! use busdma? */
+	waslocked = WPI_LOCK_OWNED(sc);
+	if (!waslocked)
+		WPI_LOCK(sc);
 
 	/* put the buffer back in the free list */
 	SLIST_INSERT_HEAD(&sc->rxq.freelist, rbuf, next);
 
-	WPI_UNLOCK(sc);
+	if (!waslocked)
+		WPI_UNLOCK(sc);
 }
 
 static int
@@ -1129,7 +1105,9 @@
 
 	for (i = 0; i < WPI_RX_RING_COUNT; i++) {
 		if (ring->data[i].m != NULL) {
+			WPI_UNLOCK(sc);
 			m_freem(ring->data[i].m);
+			WPI_LOCK(sc);
 			ring->data[i].m = NULL;
 		}
 	}
@@ -1274,7 +1252,6 @@
 wpi_shutdown(device_t dev)
 {
 	struct wpi_softc *sc = device_get_softc(dev);
-	WPI_LOCK_DECL;
 
 	WPI_LOCK(sc);
 	wpi_stop_locked(sc);
@@ -1362,19 +1339,12 @@
 		wpi_set_led(sc, WPI_LED_LINK, 20, 2);
 		break;
 
-	case IEEE80211_S_ASSOC:
-		DPRINTF(("NEWSTATE:ASSOC\n"));
-		if (ic->ic_state != IEEE80211_S_RUN)
-			break;
-		/* FALLTHROUGH */
-
 	case IEEE80211_S_AUTH:
-		sc->flags |= WPI_FLAG_AUTH;
+		sc->sc_autharg = arg;
 		sc->config.associd = 0;
 		sc->config.filter &= ~htole32(WPI_FILTER_BSS);
-		wpi_queue_cmd(sc,WPI_AUTH);
-		DPRINTF(("END AUTH\n"));
-		break;
+		/* Delay the auth transition until we can update the firmware */
+		return (wpi_queue_cmd(sc, WPI_AUTH, 0));
 
 	case IEEE80211_S_RUN:
 		if (ic->ic_opmode == IEEE80211_M_MONITOR) {
@@ -1438,7 +1408,6 @@
 		wpi_set_led(sc, WPI_LED_LINK, 0, 1);
 		break;
 
-	case IEEE80211_S_INIT:
 	default:
 		break;
 	}
@@ -1605,7 +1574,6 @@
 	struct wpi_rbuf *rbuf;
 	struct ieee80211_node *ni;
 	struct mbuf *m, *mnew;
-	WPI_LOCK_DECL;
 
 	stat = (struct wpi_rx_stat *)(desc + 1);
 
@@ -1655,11 +1623,7 @@
 		}
 	}
 
-#ifndef WPI_CURRENT
-	if (sc->sc_drvbpf != NULL) {
-#else
 	if (bpf_peers_present(sc->sc_drvbpf)) {
-#endif
 		struct wpi_rx_radiotap_header *tap = &sc->sc_rxtap;
 
 		tap->wr_flags = 0;
@@ -1752,7 +1716,6 @@
 	ring->queued--;
 
 	sc->sc_tx_timer = 0;
-	callout_stop(&sc->watchdog_to);
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 	wpi_start(ifp);
 }
@@ -1788,6 +1751,7 @@
 wpi_notif_intr(struct wpi_softc *sc)
 {
 	struct ieee80211com *ic = &sc->sc_ic;
+	struct ifnet *ifp = ic->ic_ifp;
 	struct wpi_rx_desc *desc;
 	struct wpi_rx_data *data;
 	uint32_t hw;
@@ -1847,10 +1811,10 @@
 				device_printf(sc->sc_dev,
 				    "Radio transmitter is switched off\n");
 				sc->flags |= WPI_FLAG_HW_RADIO_OFF;
-				/* XXX Do something? */
-				break;
+				ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+				/* Disable firmware commands */
+				WPI_WRITE(sc, WPI_UCODE_SET, WPI_DISABLE_CMD);
 			}
-			sc->flags &= ~WPI_FLAG_HW_RADIO_OFF;
 			break;
 		}
 		case WPI_START_SCAN:
@@ -1872,7 +1836,8 @@
 			    ("scan finished nchan=%d status=%d chan=%d\n",
 			     scan->nchan, scan->status, scan->chan));
 
-			wpi_queue_cmd(sc, WPI_SCAN_NEXT);
+			sc->sc_scan_timer = 0;
+			ieee80211_scan_next(ic);
 			break;
 		}
 		case WPI_MISSED_BEACON:
@@ -1887,6 +1852,7 @@
 				 ic->ic_bmissthreshold));
 			ieee80211_beacon_miss(ic);
 		    }
+		    break;
 		}
 		}
 
@@ -1903,7 +1869,6 @@
 {
 	struct wpi_softc *sc = arg;
 	uint32_t r;
-	WPI_LOCK_DECL;
 
 	WPI_LOCK(sc);
 
@@ -1922,7 +1887,7 @@
 		device_printf(sc->sc_dev, "fatal firmware error\n");
 		DPRINTFN(6,("(%s)\n", (r & WPI_SW_ERROR) ? "(Software Error)" :
 				"(Hardware Error)"));
-		taskqueue_enqueue(sc->sc_tq2, &sc->sc_restarttask);
+		wpi_queue_cmd(sc, WPI_RESTART, 1);
 		sc->flags &= ~WPI_FLAG_BUSY;
 		WPI_UNLOCK(sc);
 		return;
@@ -2002,7 +1967,7 @@
 
 	if (wh->i_fc[1] & IEEE80211_FC1_WEP) {
 		k = ieee80211_crypto_encap(ic, ni, m0);
-		if (k == NULL){
+		if (k == NULL) {
 			m_freem(m0);
 			return ENOBUFS;
 		}
@@ -2023,7 +1988,7 @@
 	tx->cck_mask = 0x0f;
 	tx->lifetime = htole32(WPI_LIFETIME_INFINITE);
 	tx->id = ismcast ? WPI_ID_BROADCAST : WPI_ID_BSS;
-	tx->len = htole16( m0->m_pkthdr.len);
+	tx->len = htole16(m0->m_pkthdr.len);
 
 	if (ismcast) {
 		if ((ni->ni_flags & IEEE80211_NODE_QOS) == 0 ||
@@ -2036,47 +2001,42 @@
 	}
 
 	/* pick a rate */
-	if((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_MASK){
+	if ((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == IEEE80211_FC0_TYPE_MASK) {
 		uint8_t subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
 		/* tell h/w to set timestamp in probe responses */
 		if (subtype == IEEE80211_FC0_SUBTYPE_PROBE_RESP)
 			tx->flags |= htole32(WPI_TX_INSERT_TSTAMP);
 
 		if (subtype == IEEE80211_FC0_SUBTYPE_ASSOC_REQ ||
-			subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ)
+		    subtype == IEEE80211_FC0_SUBTYPE_REASSOC_REQ)
 			tx->timeout = htole16(3);
 		else
 			tx->timeout = htole16(2);
 
 		rate = ni->ni_rates.rs_rates[0] & IEEE80211_RATE_VAL;
-	} else if (ismcast ){
-	    rate = ic->ic_mcast_rate;
-	} else if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE){
-	    rate = ic->ic_fixed_rate;
+	} else if (ismcast) {
+		rate = ic->ic_mcast_rate;
+	} else if (ic->ic_fixed_rate != IEEE80211_FIXED_RATE_NONE) {
+		rate = ic->ic_fixed_rate;
 	} else {
-	    rate = ni->ni_rates.rs_rates[ni->ni_txrate];
-	    rate &= IEEE80211_RATE_VAL;
+		rate = ni->ni_rates.rs_rates[ni->ni_txrate];
+		rate &= IEEE80211_RATE_VAL;
 	}
 	tx->rate = wpi_plcp_signal(rate);
 
 	/* be very persistant at sending frames out */
 	tx->data_ntries = 15;	/* XXX Way too high */
 
-#ifndef WPI_CURRENT
-	if (sc->sc_drvbpf != NULL ){
-#else
-	if (bpf_peers_present(sc->sc_drvbpf)){
-#endif
-	    struct wpi_tx_radiotap_header *tap = &sc->sc_txtap;
-	    tap->wt_flags = 0;
-	    tap->wt_chan_freq = htole16(ni->ni_chan->ic_freq);
-	    tap->wt_chan_flags = htole16(ni->ni_chan->ic_flags);
-	    tap->wt_rate = rate;
-	    tap->wt_hwqueue = ac;
-	    if (wh->i_fc[1] & IEEE80211_FC1_WEP)
-		tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
-
-	    bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0);
+	if (bpf_peers_present(sc->sc_drvbpf)) {
+		struct wpi_tx_radiotap_header *tap = &sc->sc_txtap;
+		tap->wt_flags = 0;
+		tap->wt_chan_freq = htole16(ni->ni_chan->ic_freq);
+		tap->wt_chan_flags = htole16(ni->ni_chan->ic_flags);
+		tap->wt_rate = rate;
+		tap->wt_hwqueue = ac;
+		if (wh->i_fc[1] & IEEE80211_FC1_WEP)
+			tap->wt_flags |= IEEE80211_RADIOTAP_F_WEP;
+		bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_txtap_len, m0);
 	}
 
 	/* save and trim IEEE802.11 header */
@@ -2153,16 +2113,18 @@
 	struct ieee80211_node *ni;
 	struct ether_header *eh;
 	struct mbuf *m0;
-	int ac;
-	WPI_LOCK_DECL;
+	int ac, waslocked;
+
+	if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0)
+		return;
 
-	WPI_LOCK(sc);
+	waslocked = WPI_LOCK_OWNED(sc);
+	if (!waslocked)
+		WPI_LOCK(sc);
 
 	for (;;) {
-		IF_POLL(&ic->ic_mgtq, m0);
+		IF_DEQUEUE(&ic->ic_mgtq, m0);
 		if (m0 != NULL) {
-			IF_DEQUEUE(&ic->ic_mgtq, m0);
-
 			ni = (struct ieee80211_node *)m0->m_pkthdr.rcvif;
 			m0->m_pkthdr.rcvif = NULL;
 
@@ -2228,11 +2190,7 @@
 				continue;
 			}
 
-#ifndef WPI_CURRENT
-			if (ic->ic_rawbpf != NULL)
-#else
 			if (bpf_peers_present(ic->ic_rawbpf))
-#endif
 				bpf_mtap(ic->ic_rawbpf, m0);
 
 			if (wpi_tx_data(sc, m0, ni, ac) != 0) {
@@ -2246,24 +2204,8 @@
 		ic->ic_lastdata = ticks;
 	}
 
-	WPI_UNLOCK(sc);
-}
-
-static void
-wpi_watchdog(struct ifnet *ifp)
-{
-	struct wpi_softc *sc = ifp->if_softc;
-	WPI_LOCK_DECL;
-
-	WPI_LOCK(sc);
-
-	DPRINTFN(WPI_DEBUG_WATCHDOG, ("tx_timer: %d\n", sc->sc_tx_timer));
-	if (sc->sc_tx_timer && --sc->sc_tx_timer != 0) {
-		device_printf(sc->sc_dev,"device timeout\n");
-		ifp->if_oerrors++;
-		taskqueue_enqueue(sc->sc_tq2, &sc->sc_restarttask);
-	}
-	WPI_UNLOCK(sc);
+	if (!waslocked)
+		WPI_UNLOCK(sc);
 }
 
 static int
@@ -2272,7 +2214,6 @@
 	struct wpi_softc *sc = ifp->if_softc;
 	struct ieee80211com *ic = &sc->sc_ic;
 	int error = 0;
-	WPI_LOCK_DECL;
 
 	WPI_LOCK(sc);
 
@@ -2280,8 +2221,9 @@
 	case SIOCSIFFLAGS:
 		if ((ifp->if_flags & IFF_UP)) {
 			if (!(ifp->if_drv_flags & IFF_DRV_RUNNING))
-				wpi_init(sc);
-		} else if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+				wpi_init_locked(sc, 0);
+		} else if ((ifp->if_drv_flags & IFF_DRV_RUNNING) ||
+			   (sc->flags & WPI_FLAG_HW_RADIO_OFF))
 			wpi_stop_locked(sc);
 		break;
 	default:
@@ -2294,7 +2236,7 @@
 		if ((ifp->if_flags & IFF_UP) &&
 		    (ifp->if_drv_flags & IFF_DRV_RUNNING) &&
 		    ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
-			wpi_init(sc);
+			wpi_init_locked(sc, 0);
 		error = 0;
 	}
 
@@ -2638,14 +2580,10 @@
 	node.action = htole32(WPI_ACTION_SET_RATE);
 	node.antenna = WPI_ANTENNA_BOTH;
 	error = wpi_cmd(sc, WPI_CMD_ADD_NODE, &node, sizeof node, 1);
-	if (error != 0) {
+	if (error != 0)
 		device_printf(sc->sc_dev, "could not add BSS node\n");
-		return error;
-	}
 
-	sc->flags &= ~WPI_FLAG_AUTH;
-
-	return 0;
+	return (error);
 }
 
 /*
@@ -2721,18 +2659,18 @@
 	/*XXX Need to cater for multiple essids */
 	memset(&hdr->scan_essids, 0, sizeof(hdr->scan_essids));
 	nssid = MIN(ss->ss_nssid, WPI_SCAN_MAX_ESSIDS);
-	for(i = 0; i < nssid; i++ ){
-	    hdr->scan_essids[i].id = IEEE80211_ELEMID_SSID;
-	    hdr->scan_essids[i].esslen = MIN(ss->ss_ssid[i].len, 32);
-	    memcpy(hdr->scan_essids[i].essid, ss->ss_ssid[i].ssid,
-		   hdr->scan_essids[i].esslen);
+	for (i = 0; i < nssid; i++ ){
+		hdr->scan_essids[i].id = IEEE80211_ELEMID_SSID;
+		hdr->scan_essids[i].esslen = MIN(ss->ss_ssid[i].len, 32);
+		memcpy(hdr->scan_essids[i].essid, ss->ss_ssid[i].ssid,
+		    hdr->scan_essids[i].esslen);
 #ifdef WPI_DEBUG
-	    if (wpi_debug & WPI_DEBUG_SCANNING) {
-		printf("Scanning Essid: ");
-		ieee80211_print_essid(ic->ic_des_ssid[i].ssid,
-				      ic->ic_des_ssid[i].len);
-		printf("\n");
-	    }
+		if (wpi_debug & WPI_DEBUG_SCANNING) {
+			printf("Scanning Essid: ");
+			ieee80211_print_essid(ic->ic_des_ssid[i].ssid,
+			    ic->ic_des_ssid[i].len);
+			printf("\n");
+		}
 #endif
 	}
 
@@ -2875,6 +2813,7 @@
 	ring->cur = (ring->cur + 1) % WPI_CMD_RING_COUNT;
 	WPI_WRITE(sc, WPI_TX_WIDX, ring->qid << 8 | ring->cur);
 
+	sc->sc_scan_timer = 5;
 	return 0;	/* will be notified async. of failure/success */
 }
 
@@ -2956,7 +2895,7 @@
 	}
 
 	/* configuration has changed, set Tx power accordingly */
-	if ((error = wpi_set_txpower(sc, ic->ic_curchan,0)) != 0) {
+	if ((error = wpi_set_txpower(sc, ic->ic_curchan, 0)) != 0) {
 	    device_printf(sc->sc_dev, "could not set Tx power\n");
 	    return error;
 	}
@@ -3104,16 +3043,83 @@
 }
 
 static void
+wpi_rfkill_resume(struct wpi_softc *sc)
+{
+	struct ifnet *ifp = sc->sc_ifp;
+	struct ieee80211com *ic = &sc->sc_ic;
+	int ntries;
+
+	/* enable firmware again */
+	WPI_WRITE(sc, WPI_UCODE_CLR, WPI_RADIO_OFF);
+	WPI_WRITE(sc, WPI_UCODE_CLR, WPI_DISABLE_CMD);
+
+	/* wait for thermal sensors to calibrate */
+	for (ntries = 0; ntries < 1000; ntries++) {
+		if ((sc->temp = (int)WPI_READ(sc, WPI_TEMPERATURE)) != 0)
+			break;
+		DELAY(10);
+	}
+
+	if (ntries == 1000) {
+		device_printf(sc->sc_dev,
+		    "timeout waiting for thermal calibration\n");
+		WPI_UNLOCK(sc);
+		return;
+	}
+	DPRINTFN(WPI_DEBUG_TEMP,("temperature %d\n", sc->temp));
+
+	if (wpi_config(sc) != 0) {
+		device_printf(sc->sc_dev, "device config failed\n");
+		WPI_UNLOCK(sc);
+		return;
+	}
+
+	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+	ifp->if_drv_flags |= IFF_DRV_RUNNING;
+	sc->flags &= ~WPI_FLAG_HW_RADIO_OFF;
+
+	if (ic->ic_flags & IEEE80211_F_SCAN)
+		ieee80211_scan_next(ic);
+
+	ieee80211_beacon_miss(ic);
+
+	/* reset the led sequence */
+	switch (ic->ic_state) {
+		case IEEE80211_S_SCAN:
+			wpi_set_led(sc, WPI_LED_LINK, 20, 2);
+			break;
+
+		case IEEE80211_S_RUN:
+			if (ic->ic_opmode == IEEE80211_M_MONITOR)
+				wpi_set_led(sc, WPI_LED_LINK, 5, 5);
+			else
+				wpi_set_led(sc, WPI_LED_LINK, 0, 1);
+			break;
+
+		default:
+			break;	/* please compiler */
+	}
+
+	callout_reset(&sc->watchdog_to, hz, wpi_watchdog, sc);
+}
+
+static void
 wpi_init(void *arg)
 {
 	struct wpi_softc *sc = arg;
+
+	WPI_LOCK(sc);
+	wpi_init_locked(sc, 0);
+	WPI_UNLOCK(sc);
+}
+
+static void
+wpi_init_locked(struct wpi_softc *sc, int force)
+{
 	struct ieee80211com *ic = &sc->sc_ic;
 	struct ifnet *ifp = ic->ic_ifp;
 	uint32_t tmp;
 	int ntries, qid;
-	WPI_LOCK_DECL;
-
-	WPI_LOCK(sc);
 
 	wpi_stop_locked(sc);
 	(void)wpi_reset(sc);
@@ -3174,7 +3180,7 @@
 	if ((wpi_load_firmware(sc)) != 0) {
 	    device_printf(sc->sc_dev,
 		"A problem occurred loading the firmware to the driver\n");
-	    goto fail;
+	    return;
 	}
 
 	/* At this point the firmware is up and running. If the hardware
@@ -3188,11 +3194,8 @@
 
 	if (!(tmp & 0x1)) {
 		sc->flags |= WPI_FLAG_HW_RADIO_OFF;
-		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-		ifp->if_drv_flags |= IFF_DRV_RUNNING;
 		device_printf(sc->sc_dev,"Radio Transmitter is switched off\n");
-		callout_reset(&sc->hwswitch_to, hz, wpi_tick, sc);
-		goto fail;
+		goto out;
 	}
 
 	/* wait for thermal sensors to calibrate */
@@ -3205,29 +3208,30 @@
 	if (ntries == 1000) {
 		device_printf(sc->sc_dev,
 		    "timeout waiting for thermal sensors calibration\n");
-		goto fail;
+		return;
 	}
 	DPRINTFN(WPI_DEBUG_TEMP,("temperature %d\n", sc->temp));
 
+	if (wpi_config(sc) != 0) {
+		device_printf(sc->sc_dev, "device config failed\n");
+		return;
+	}
+
 	ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
 	ifp->if_drv_flags |= IFF_DRV_RUNNING;
-	callout_reset(&sc->watchdog_to, hz, wpi_tick, sc);
-	WPI_UNLOCK(sc);
+out:
+	callout_reset(&sc->watchdog_to, hz, wpi_watchdog, sc);
 
 	if (ic->ic_opmode == IEEE80211_M_MONITOR)
 		ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
 	else if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
 		ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
 	return;
-
-fail:
-	WPI_UNLOCK(sc);
 }
 
 static void
 wpi_stop(struct wpi_softc *sc)
 {
-	WPI_LOCK_DECL;
 
 	WPI_LOCK(sc);
 	wpi_stop_locked(sc);
@@ -3244,8 +3248,13 @@
 	int ac;
 
 	sc->sc_tx_timer = 0;
+	sc->sc_scan_timer = 0;
 	ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+	sc->flags &= ~WPI_FLAG_HW_RADIO_OFF;
+	callout_stop(&sc->watchdog_to);
+	callout_stop(&sc->calib_to);
 
+
 	/* disable interrupts */
 	WPI_WRITE(sc, WPI_MASK, 0);
 	WPI_WRITE(sc, WPI_INTR, WPI_INTR_MASK);
@@ -3254,6 +3263,8 @@
 
 	/* Clear any commands left in the command buffer */
 	memset(sc->sc_cmd, 0, sizeof(sc->sc_cmd));
+	sc->sc_cmd_cur = 0;
+	sc->sc_cmd_next = 0;
 
 	wpi_mem_lock(sc);
 	wpi_mem_write(sc, WPI_MEM_MODE, 0);
@@ -3600,42 +3611,6 @@
 }
 
 /**
- * Called from a callout, wpi_radio checks the state of hw switch and
- * if it's enabled restarts the device. The hardware doesn't give us an
- * interupt when the hw switch is toggled on, only off hence we poll
- * the device checking. Calling callout locks mtx;
- */
-static void
-wpi_radio(void *arg)
-{
-	struct wpi_softc *sc = arg;
-	struct ieee80211com *ic = &sc->sc_ic;
-	struct ifnet *ifp = ic->ic_ifp;
-	int tmp;
-
-	wpi_mem_lock(sc);
-	tmp = wpi_mem_read(sc, WPI_MEM_HW_RADIO_OFF);
-	wpi_mem_unlock(sc);
-
-	DPRINTFN(WPI_DEBUG_HWSWITCH,
-		 ("wpi_radio callout: radio %d\n",tmp&0x1));
-
-	if (tmp & 0x1) {
-		// Radio enabled
-		device_printf(sc->sc_dev, "Hardware Switch Enabled\n");
-		ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
-		ifp->if_drv_flags |= IFF_DRV_RUNNING;
-
-		callout_reset(&sc->watchdog_to, hz, wpi_tick, sc);
-		if (ic->ic_opmode == IEEE80211_M_MONITOR)
-			ieee80211_new_state(ic, IEEE80211_S_RUN, -1);
-		else if (ic->ic_roaming != IEEE80211_ROAMING_MANUAL)
-			ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
-	} else
-		callout_reset(&sc->hwswitch_to, hz, wpi_radio, sc);
-}
-
-/**
  * Called by net80211 framework to indicate that a scan
  * is starting. This function doesn't actually do the scan,
  * wpi_scan_curchan starts things off. This function is more
@@ -3648,7 +3623,7 @@
 	struct ifnet *ifp = ic->ic_ifp;
 	struct wpi_softc *sc = ifp->if_softc;
 
-	wpi_queue_cmd(sc, WPI_SCAN_START);
+	wpi_queue_cmd(sc, WPI_SCAN_START, 0);
 }
 
 /**
@@ -3662,7 +3637,7 @@
 	struct ifnet *ifp = ic->ic_ifp;
 	struct wpi_softc *sc = ifp->if_softc;
 
-	wpi_queue_cmd(sc, WPI_SCAN_STOP);
+	wpi_queue_cmd(sc, WPI_SCAN_STOP, 0);
 }
 
 /**
@@ -3675,7 +3650,7 @@
 	struct ifnet *ifp = ic->ic_ifp;
 	struct wpi_softc *sc = ifp->if_softc;
 
-	wpi_queue_cmd(sc, WPI_SET_CHAN);
+	wpi_queue_cmd(sc, WPI_SET_CHAN, 0);
 }
 
 /**
@@ -3691,7 +3666,7 @@
 
 	sc->maxdwell = maxdwell;
 
-	wpi_queue_cmd(sc, WPI_SCAN_CURCHAN);
+	wpi_queue_cmd(sc, WPI_SCAN_CURCHAN, 0);
 }
 
 /**
@@ -3717,7 +3692,6 @@
 {
 	struct wpi_softc *sc = arg;
 	struct ieee80211com *ic = &sc->sc_ic;
-	WPI_LOCK_DECL;
 	int cmd;
 
 again:
@@ -3734,60 +3708,46 @@
 	WPI_CMD_UNLOCK(sc);
 	WPI_LOCK(sc);
 
-	if (!(sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+	DPRINTFN(WPI_DEBUG_OPS,("wpi_ops: command: %d\n", cmd));
+
+	switch (cmd) {
+	case WPI_RESTART:
+		wpi_init_locked(sc, 0);
+		WPI_UNLOCK(sc);
+		return;
+
+	case WPI_RF_RESTART:
+		wpi_rfkill_resume(sc);
 		WPI_UNLOCK(sc);
 		return;
 	}
 
-	{
-	const char *name[]={"SCAN_START", "SCAN_CURCHAN",0,"STOP",0,0,0,"CHAN",
-		0,0,0,0,0,0,"AUTH",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,"NEXT"};
-	DPRINTFN(WPI_DEBUG_OPS,("wpi_ops: command: %d %s\n", cmd, name[cmd-1]));
+	if (!(sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)) {
+		WPI_UNLOCK(sc);
+		return;
 	}
 
 	switch (cmd) {
 	case WPI_SCAN_START:
-		if (sc->flags & WPI_FLAG_HW_RADIO_OFF) {
-			DPRINTF(("HERER\n"));
-			ieee80211_cancel_scan(ic);
-		} else
-			sc->flags |= WPI_FLAG_SCANNING;
+		sc->flags |= WPI_FLAG_SCANNING;
 		break;
 
 	case WPI_SCAN_STOP:
 		sc->flags &= ~WPI_FLAG_SCANNING;
 		break;
 
-	case WPI_SCAN_NEXT:
-		DPRINTF(("NEXT\n"));
-		WPI_UNLOCK(sc);
-		ieee80211_scan_next(ic);
-		WPI_LOCK(sc);
-		break;
-
 	case WPI_SCAN_CURCHAN:
 		if (wpi_scan(sc))
 			ieee80211_cancel_scan(ic);
 		break;
 
 	case WPI_SET_CHAN:
-		if (sc->flags&WPI_FLAG_AUTH) {
-			DPRINTF(("Authenticating, not changing channel\n"));
-			break;
-		}
-		if (wpi_config(sc)) {
-			DPRINTF(("Scan cancelled\n"));
-			WPI_UNLOCK(sc);
-			ieee80211_cancel_scan(ic);
-			WPI_LOCK(sc);
-			sc->flags &= ~WPI_FLAG_SCANNING;
-			wpi_restart(sc,0);
-			WPI_UNLOCK(sc);
-			return;
-		}
+		/* XXX Is this needed ? */
+		DPRINTF(("Ignoring WPI_SET_CHAN\n"));
 		break;
 
 	case WPI_AUTH:
+		/* The node must be registered in the firmware before auth */
 		if (wpi_auth(sc) != 0) {
 			device_printf(sc->sc_dev,
 			    "could not send authentication request\n");
@@ -3795,10 +3755,8 @@
 			WPI_UNLOCK(sc);
 			return;
 		}
-		WPI_UNLOCK(sc);
-		ieee80211_node_authorize(ic->ic_bss);
-		ieee80211_new_state(ic, IEEE80211_S_ASSOC, -1);
-		WPI_LOCK(sc);
+		/* Send the auth frame now */
+		sc->sc_newstate(ic, IEEE80211_S_AUTH, sc->sc_autharg);
 		break;
 	}
 	WPI_UNLOCK(sc);
@@ -3815,10 +3773,16 @@
  * a sleep enabled thread.
  */
 static int
-wpi_queue_cmd(struct wpi_softc *sc, int cmd)
+wpi_queue_cmd(struct wpi_softc *sc, int cmd, int flush)
 {
 	WPI_CMD_LOCK(sc);
 
+	if (flush) {
+		memset(sc->sc_cmd, 0, sizeof (sc->sc_cmd));
+		sc->sc_cmd_cur = 0;
+		sc->sc_cmd_next = 0;
+	}
+
 	if (sc->sc_cmd[sc->sc_cmd_next] != 0) {
 		WPI_CMD_UNLOCK(sc);
 		DPRINTF(("%s: command %d dropped\n", __func__, cmd));
@@ -3835,23 +3799,6 @@
 	return 0;
 }
 
-static void
-wpi_restart(void * arg, int pending)
-{
-#if 0
-	struct wpi_softc *sc = arg;
-	struct ieee80211com *ic = &sc->sc_ic;
-	WPI_LOCK_DECL;
-
-	DPRINTF(("Device failed, restarting device\n"));
-	WPI_LOCK(sc);
-	wpi_stop(sc);
-	wpi_init(sc);
-	WPI_UNLOCK(sc);
-	ieee80211_new_state(ic, IEEE80211_S_SCAN, -1);
-#endif
-}
-
 /*
  * Allocate DMA-safe memory for firmware transfer.
  */
@@ -3871,18 +3818,50 @@
 }
 
 /**
- * Called every second, wpi_tick used by the watch dog timer
+ * Called every second, wpi_watchdog used by the watch dog timer
  * to check that the card is still alive
  */
 static void
-wpi_tick(void *arg)
+wpi_watchdog(void *arg)
 {
 	struct wpi_softc *sc = arg;
+	struct ifnet *ifp = sc->sc_ifp;
+	uint32_t tmp;
 
 	DPRINTFN(WPI_DEBUG_WATCHDOG,("Watchdog: tick\n"));
 
-	wpi_watchdog(sc->sc_ifp);
-	callout_reset(&sc->watchdog_to, hz, wpi_tick, sc);
+	if (sc->flags & WPI_FLAG_HW_RADIO_OFF) {
+		/* No need to lock firmware memory */
+		tmp = wpi_mem_read(sc, WPI_MEM_HW_RADIO_OFF);

>>> TRUNCATED FOR MAIL (1000 lines) <<<



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