From owner-p4-projects@FreeBSD.ORG Wed Mar 5 01:18:30 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id C4D2F1065674; Wed, 5 Mar 2008 01:18:30 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 82AD41065671 for ; Wed, 5 Mar 2008 01:18:30 +0000 (UTC) (envelope-from thompsa@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 6E7158FC14 for ; Wed, 5 Mar 2008 01:18:30 +0000 (UTC) (envelope-from thompsa@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m251IU4t080808 for ; Wed, 5 Mar 2008 01:18:30 GMT (envelope-from thompsa@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m251IU0C080806 for perforce@freebsd.org; Wed, 5 Mar 2008 01:18:30 GMT (envelope-from thompsa@freebsd.org) Date: Wed, 5 Mar 2008 01:18:30 GMT Message-Id: <200803050118.m251IU0C080806@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to thompsa@freebsd.org using -f From: Andrew Thompson To: Perforce Change Reviews Cc: Subject: PERFORCE change 136876 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 05 Mar 2008 01:18:31 -0000 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 -__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 #include -#if (__FreeBSD_version > 700000) -#define WPI_CURRENT -#endif - #include #include -#ifndef WPI_CURRENT -#include -#endif #include #include @@ -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) <<<