PERFORCE change 136876 for review
Andrew Thompson
thompsa at FreeBSD.org
Wed Mar 5 01:18:31 UTC 2008
http://perforce.freebsd.org/chv.cgi?CH=136876
Change 136876 by thompsa at 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) <<<
More information about the p4-projects
mailing list