summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/if_ndis/if_ndis.c145
-rw-r--r--sys/dev/if_ndis/if_ndisvar.h5
-rw-r--r--sys/dev/ipw/if_ipw.c138
-rw-r--r--sys/dev/ipw/if_ipwvar.h8
-rw-r--r--sys/dev/iwi/if_iwi.c315
-rw-r--r--sys/dev/iwi/if_iwivar.h33
-rw-r--r--sys/dev/iwn/if_iwn.c326
-rw-r--r--sys/dev/iwn/if_iwnvar.h35
-rw-r--r--sys/dev/usb/wlan/if_rum.c385
-rw-r--r--sys/dev/usb/wlan/if_rumvar.h23
-rw-r--r--sys/dev/usb/wlan/if_uath.c18
-rw-r--r--sys/dev/usb/wlan/if_uathvar.h1
-rw-r--r--sys/dev/usb/wlan/if_ural.c390
-rw-r--r--sys/dev/usb/wlan/if_uralvar.h20
-rw-r--r--sys/dev/usb/wlan/if_zyd.c361
-rw-r--r--sys/dev/usb/wlan/if_zydreg.h21
-rw-r--r--sys/dev/usb/wlan/usb_wlan.h56
-rw-r--r--sys/dev/wi/if_wi.c72
-rw-r--r--sys/dev/wi/if_wivar.h4
-rw-r--r--sys/dev/wpi/if_wpi.c252
-rw-r--r--sys/dev/wpi/if_wpivar.h41
-rw-r--r--sys/net80211/ieee80211.c23
-rw-r--r--sys/net80211/ieee80211_freebsd.h1
-rw-r--r--sys/net80211/ieee80211_ioctl.c4
-rw-r--r--sys/net80211/ieee80211_node.c18
-rw-r--r--sys/net80211/ieee80211_node.h2
-rw-r--r--sys/net80211/ieee80211_proto.c215
-rw-r--r--sys/net80211/ieee80211_scan.c407
-rw-r--r--sys/net80211/ieee80211_scan.h1
-rw-r--r--sys/net80211/ieee80211_scan_sta.c6
-rw-r--r--sys/net80211/ieee80211_var.h38
31 files changed, 1135 insertions, 2229 deletions
diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c
index dfff9e8..8f5054b 100644
--- a/sys/dev/if_ndis/if_ndis.c
+++ b/sys/dev/if_ndis/if_ndis.c
@@ -50,7 +50,6 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/kthread.h>
-#include <sys/taskqueue.h>
#include <net/if.h>
@@ -173,7 +172,7 @@ static int ndis_newstate (struct ieee80211vap *, enum ieee80211_state,
int);
static int ndis_nettype_chan (uint32_t);
static int ndis_nettype_mode (uint32_t);
-static void ndis_scan (void *, int);
+static void ndis_scan (void *);
static void ndis_scan_results (struct ndis_softc *);
static void ndis_scan_start (struct ieee80211com *);
static void ndis_scan_end (struct ieee80211com *);
@@ -184,8 +183,6 @@ static void ndis_init (void *);
static void ndis_stop (struct ndis_softc *);
static int ndis_ifmedia_upd (struct ifnet *);
static void ndis_ifmedia_sts (struct ifnet *, struct ifmediareq *);
-static void ndis_auth (void *, int);
-static void ndis_assoc (void *, int);
static int ndis_get_assoc (struct ndis_softc *, ndis_wlan_bssid_ex **);
static int ndis_probe_offload (struct ndis_softc *);
static int ndis_set_offload (struct ndis_softc *);
@@ -741,13 +738,7 @@ ndis_attach(dev)
uint32_t arg;
int r;
- sc->ndis_tq = taskqueue_create("nids_taskq", M_NOWAIT | M_ZERO,
- taskqueue_thread_enqueue, &sc->ndis_tq);
- taskqueue_start_threads(&sc->ndis_tq, 1, PI_NET, "%s taskq",
- device_get_nameunit(dev));
- TASK_INIT(&sc->ndis_scantask, 0, ndis_scan, sc);
- TASK_INIT(&sc->ndis_authtask, 0, ndis_auth, sc);
- TASK_INIT(&sc->ndis_assoctask, 0, ndis_assoc, sc);
+ callout_init(&sc->ndis_scan_callout, CALLOUT_MPSAFE);
ifp->if_ioctl = ndis_ioctl_80211;
ic->ic_ifp = ifp;
@@ -1054,12 +1045,6 @@ ndis_detach(dev)
} else
NDIS_UNLOCK(sc);
- if (sc->ndis_80211) {
- taskqueue_drain(sc->ndis_tq, &sc->ndis_scantask);
- taskqueue_drain(sc->ndis_tq, &sc->ndis_authtask);
- taskqueue_drain(sc->ndis_tq, &sc->ndis_assoctask);
- }
-
if (sc->ndis_tickitem != NULL)
IoFreeWorkItem(sc->ndis_tickitem);
if (sc->ndis_startitem != NULL)
@@ -1121,8 +1106,6 @@ ndis_detach(dev)
if (sc->ndis_iftype == PCIBus)
bus_dma_tag_destroy(sc->ndis_parent_tag);
- if (sc->ndis_80211)
- taskqueue_free(sc->ndis_tq);
return(0);
}
@@ -2419,30 +2402,6 @@ ndis_setstate_80211(sc)
}
static void
-ndis_auth(void *arg, int npending)
-{
- struct ndis_softc *sc = arg;
- struct ifnet *ifp = sc->ifp;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
-
- vap->iv_state = IEEE80211_S_AUTH;
- ndis_auth_and_assoc(sc, vap);
-}
-
-static void
-ndis_assoc(void *arg, int npending)
-{
- struct ndis_softc *sc = arg;
- struct ifnet *ifp = sc->ifp;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
-
- vap->iv_state = IEEE80211_S_ASSOC;
- ndis_auth_and_assoc(sc, vap);
-}
-
-static void
ndis_auth_and_assoc(sc, vap)
struct ndis_softc *sc;
struct ieee80211vap *vap;
@@ -2656,9 +2615,6 @@ ndis_auth_and_assoc(sc, vap)
if (rval)
device_printf (sc->ndis_dev, "set ssid failed: %d\n", rval);
- if (vap->iv_state == IEEE80211_S_AUTH)
- ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
-
return;
}
@@ -3304,13 +3260,18 @@ ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
return nvp->newstate(vap, nstate, arg);
case IEEE80211_S_ASSOC:
if (ostate != IEEE80211_S_AUTH) {
- taskqueue_enqueue(sc->ndis_tq, &sc->ndis_assoctask);
- return EINPROGRESS;
+ IEEE80211_UNLOCK(ic);
+ ndis_auth_and_assoc(sc, vap);
+ IEEE80211_LOCK(ic);
}
break;
case IEEE80211_S_AUTH:
- taskqueue_enqueue(sc->ndis_tq, &sc->ndis_authtask);
- return EINPROGRESS;
+ IEEE80211_UNLOCK(ic);
+ ndis_auth_and_assoc(sc, vap);
+ if (vap->iv_state == IEEE80211_S_AUTH) /* XXX */
+ ieee80211_new_state(vap, IEEE80211_S_ASSOC, 0);
+ IEEE80211_LOCK(ic);
+ break;
default:
break;
}
@@ -3318,54 +3279,18 @@ ndis_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
}
static void
-ndis_scan(void *arg, int npending)
+ndis_scan(void *arg)
{
struct ndis_softc *sc = arg;
struct ieee80211com *ic;
struct ieee80211vap *vap;
- struct ieee80211_scan_state *ss;
- ndis_80211_ssid ssid;
- int error, len;
ic = sc->ifp->if_l2com;
- ss = ic->ic_scan;
vap = TAILQ_FIRST(&ic->ic_vaps);
- if (!NDIS_INITIALIZED(sc)) {
- DPRINTF(("%s: scan aborted\n", __func__));
- ieee80211_cancel_scan(vap);
- return;
- }
-
- len = sizeof(ssid);
- bzero((char *)&ssid, len);
- if (ss->ss_nssid == 0)
- ssid.ns_ssidlen = 1;
- else {
- /* Perform a directed scan */
- ssid.ns_ssidlen = ss->ss_ssid[0].len;
- bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
- }
-
- error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
- if (error)
- DPRINTF(("%s: set ESSID failed\n", __func__));
-
- len = 0;
- error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN,
- NULL, &len);
- if (error) {
- DPRINTF(("%s: scan command failed\n", __func__));
- ieee80211_cancel_scan(vap);
- return;
- }
-
- pause("ssidscan", hz * 3);
- if (!NDIS_INITIALIZED(sc))
- /* The interface was downed while we were sleeping */
- return;
-
+ NDIS_LOCK(sc);
ndis_scan_results(sc);
+ NDIS_UNLOCK(sc);
ieee80211_scan_done(vap);
}
@@ -3496,8 +3421,48 @@ ndis_scan_start(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct ndis_softc *sc = ifp->if_softc;
+ struct ieee80211vap *vap;
+ struct ieee80211_scan_state *ss;
+ ndis_80211_ssid ssid;
+ int error, len;
+
+ ss = ic->ic_scan;
+ vap = TAILQ_FIRST(&ic->ic_vaps);
+
+ NDIS_LOCK(sc);
+ if (!NDIS_INITIALIZED(sc)) {
+ DPRINTF(("%s: scan aborted\n", __func__));
+ NDIS_UNLOCK(sc);
+ ieee80211_cancel_scan(vap);
+ return;
+ }
- taskqueue_enqueue(sc->ndis_tq, &sc->ndis_scantask);
+ len = sizeof(ssid);
+ bzero((char *)&ssid, len);
+ if (ss->ss_nssid == 0)
+ ssid.ns_ssidlen = 1;
+ else {
+ /* Perform a directed scan */
+ ssid.ns_ssidlen = ss->ss_ssid[0].len;
+ bcopy(ss->ss_ssid[0].ssid, ssid.ns_ssid, ssid.ns_ssidlen);
+ }
+
+ error = ndis_set_info(sc, OID_802_11_SSID, &ssid, &len);
+ if (error)
+ DPRINTF(("%s: set ESSID failed\n", __func__));
+
+ len = 0;
+ error = ndis_set_info(sc, OID_802_11_BSSID_LIST_SCAN,
+ NULL, &len);
+ if (error) {
+ DPRINTF(("%s: scan command failed\n", __func__));
+ NDIS_UNLOCK(sc);
+ ieee80211_cancel_scan(vap);
+ return;
+ }
+ NDIS_UNLOCK(sc);
+ /* Set a timer to collect the results */
+ callout_reset(&sc->ndis_scan_callout, hz * 3, ndis_scan, sc);
}
static void
diff --git a/sys/dev/if_ndis/if_ndisvar.h b/sys/dev/if_ndis/if_ndisvar.h
index 6db48a6..fc7ae4c 100644
--- a/sys/dev/if_ndis/if_ndisvar.h
+++ b/sys/dev/if_ndis/if_ndisvar.h
@@ -180,6 +180,7 @@ struct ndis_softc {
ndis_miniport_block *ndis_block;
ndis_miniport_characteristics *ndis_chars;
interface_type ndis_type;
+ struct callout ndis_scan_callout;
struct callout ndis_stat_callout;
int ndis_maxpkts;
ndis_oid *ndis_oids;
@@ -219,10 +220,6 @@ struct ndis_softc {
struct ifqueue ndis_rxqueue;
kspin_lock ndis_rxlock;
- struct taskqueue *ndis_tq; /* private task queue */
- struct task ndis_scantask;
- struct task ndis_authtask;
- struct task ndis_assoctask;
int (*ndis_newstate)(struct ieee80211com *,
enum ieee80211_state, int);
int ndis_tx_timer;
diff --git a/sys/dev/ipw/if_ipw.c b/sys/dev/ipw/if_ipw.c
index 5463f0a..9d67724 100644
--- a/sys/dev/ipw/if_ipw.c
+++ b/sys/dev/ipw/if_ipw.c
@@ -118,10 +118,6 @@ static void ipw_media_status(struct ifnet *, struct ifmediareq *);
static int ipw_newstate(struct ieee80211vap *, enum ieee80211_state, int);
static uint16_t ipw_read_prom_word(struct ipw_softc *, uint8_t);
static void ipw_rx_cmd_intr(struct ipw_softc *, struct ipw_soft_buf *);
-static void ipw_assocsuccess(void *, int);
-static void ipw_assocfailed(void *, int);
-static void ipw_scandone(void *, int);
-static void ipw_bmiss(void *, int);
static void ipw_rx_newstate_intr(struct ipw_softc *, struct ipw_soft_buf *);
static void ipw_rx_data_intr(struct ipw_softc *, struct ipw_status *,
struct ipw_soft_bd *, struct ipw_soft_buf *);
@@ -147,8 +143,8 @@ static int ipw_reset(struct ipw_softc *);
static int ipw_load_ucode(struct ipw_softc *, const char *, int);
static int ipw_load_firmware(struct ipw_softc *, const char *, int);
static int ipw_config(struct ipw_softc *);
-static void ipw_assoc_task(void *, int);
-static void ipw_disassoc_task(void *, int);
+static void ipw_assoc(struct ieee80211com *, struct ieee80211vap *);
+static void ipw_disassoc(struct ieee80211com *, struct ieee80211vap *);
static void ipw_init_task(void *, int);
static void ipw_init(void *);
static void ipw_init_locked(struct ipw_softc *);
@@ -166,7 +162,6 @@ static void ipw_read_mem_1(struct ipw_softc *, bus_size_t, uint8_t *,
#endif
static void ipw_write_mem_1(struct ipw_softc *, bus_size_t,
const uint8_t *, bus_size_t);
-static void ipw_scan_task(void *, int);
static int ipw_scan(struct ipw_softc *);
static void ipw_scan_start(struct ieee80211com *);
static void ipw_scan_end(struct ieee80211com *);
@@ -239,8 +234,6 @@ ipw_attach(device_t dev)
MTX_DEF | MTX_RECURSE);
TASK_INIT(&sc->sc_init_task, 0, ipw_init_task, sc);
- TASK_INIT(&sc->sc_scan_task, 0, ipw_scan_task, sc);
- TASK_INIT(&sc->sc_bmiss_task, 0, ipw_bmiss, sc);
callout_init_mtx(&sc->sc_wdtimer, &sc->sc_mtx, 0);
if (pci_get_powerstate(dev) != PCI_POWERSTATE_D0) {
@@ -417,9 +410,7 @@ ipw_detach(device_t dev)
ieee80211_ifdetach(ic);
callout_drain(&sc->sc_wdtimer);
- taskqueue_drain(taskqueue_swi, &sc->sc_init_task);
- taskqueue_drain(taskqueue_swi, &sc->sc_scan_task);
- taskqueue_drain(taskqueue_swi, &sc->sc_bmiss_task);
+ ieee80211_draintask(ic, &sc->sc_init_task);
ipw_release(sc);
@@ -511,12 +502,6 @@ ipw_vap_create(struct ieee80211com *ic,
return NULL;
vap = &ivp->vap;
- TASK_INIT(&ivp->assoc_task, 0, ipw_assoc_task, vap);
- TASK_INIT(&ivp->disassoc_task, 0, ipw_disassoc_task, vap);
- TASK_INIT(&ivp->assoc_success_task, 0, ipw_assocsuccess, vap);
- TASK_INIT(&ivp->assoc_failed_task, 0, ipw_assocfailed, vap);
- TASK_INIT(&ivp->scandone_task, 0, ipw_scandone, vap);
-
ieee80211_vap_setup(ic, vap, name, unit, opmode, flags, bssid, mac);
/* override with driver methods */
ivp->newstate = vap->iv_newstate;
@@ -894,11 +879,15 @@ ipw_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
struct ieee80211com *ic = vap->iv_ic;
struct ifnet *ifp = ic->ic_ifp;
struct ipw_softc *sc = ifp->if_softc;
+ enum ieee80211_state ostate;
DPRINTF(("%s: %s -> %s flags 0x%x\n", __func__,
ieee80211_state_name[vap->iv_state],
ieee80211_state_name[nstate], sc->flags));
+ ostate = vap->iv_state;
+ IEEE80211_UNLOCK(ic);
+
switch (nstate) {
case IEEE80211_S_RUN:
if (ic->ic_opmode == IEEE80211_M_IBSS) {
@@ -910,39 +899,33 @@ ipw_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
* AUTH -> RUN transition and we want to do nothing.
* This is all totally bogus and needs to be redone.
*/
- if (vap->iv_state == IEEE80211_S_SCAN) {
- taskqueue_enqueue(taskqueue_swi,
- &IPW_VAP(vap)->assoc_task);
- return EINPROGRESS;
- }
+ if (ostate == IEEE80211_S_SCAN)
+ ipw_assoc(ic, vap);
}
break;
case IEEE80211_S_INIT:
if (sc->flags & IPW_FLAG_ASSOCIATED)
- taskqueue_enqueue(taskqueue_swi,
- &IPW_VAP(vap)->disassoc_task);
+ ipw_disassoc(ic, vap);
break;
case IEEE80211_S_AUTH:
- taskqueue_enqueue(taskqueue_swi, &IPW_VAP(vap)->assoc_task);
- return EINPROGRESS;
+ ipw_assoc(ic, vap);
+ break;
case IEEE80211_S_ASSOC:
/*
* If we are not transitioning from AUTH the resend the
* association request.
*/
- if (vap->iv_state != IEEE80211_S_AUTH) {
- taskqueue_enqueue(taskqueue_swi,
- &IPW_VAP(vap)->assoc_task);
- return EINPROGRESS;
- }
+ if (ostate != IEEE80211_S_AUTH)
+ ipw_assoc(ic, vap);
break;
default:
break;
}
+ IEEE80211_LOCK(ic);
return ivp->newstate(vap, nstate, arg);
}
@@ -1020,38 +1003,6 @@ ipw_rx_cmd_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
}
static void
-ipw_assocsuccess(void *arg, int npending)
-{
- struct ieee80211vap *vap = arg;
-
- ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
-}
-
-static void
-ipw_assocfailed(void *arg, int npending)
-{
- struct ieee80211vap *vap = arg;
-
- ieee80211_new_state(vap, IEEE80211_S_SCAN, -1);
-}
-
-static void
-ipw_scandone(void *arg, int npending)
-{
- struct ieee80211vap *vap = arg;
-
- ieee80211_scan_done(vap);
-}
-
-static void
-ipw_bmiss(void *arg, int npending)
-{
- struct ieee80211com *ic = arg;
-
- ieee80211_beacon_miss(ic);
-}
-
-static void
ipw_rx_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
{
#define IEEESTATE(vap) ieee80211_state_name[vap->iv_state]
@@ -1076,8 +1027,7 @@ ipw_rx_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
}
sc->flags &= ~IPW_FLAG_ASSOCIATING;
sc->flags |= IPW_FLAG_ASSOCIATED;
- taskqueue_enqueue(taskqueue_swi,
- &IPW_VAP(vap)->assoc_success_task);
+ ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
break;
case IPW_STATE_SCANNING:
@@ -1091,7 +1041,7 @@ ipw_rx_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
*/
if (sc->flags & IPW_FLAG_ASSOCIATED) {
/* XXX probably need to issue disassoc to fw */
- taskqueue_enqueue(taskqueue_swi, &sc->sc_bmiss_task);
+ ieee80211_beacon_miss(ic);
}
break;
@@ -1110,8 +1060,7 @@ ipw_rx_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
break;
}
if (sc->flags & IPW_FLAG_SCANNING) {
- taskqueue_enqueue(taskqueue_swi,
- &IPW_VAP(vap)->scandone_task);
+ ieee80211_scan_done(vap);
sc->flags &= ~IPW_FLAG_SCANNING;
sc->sc_scan_timer = 0;
}
@@ -1122,8 +1071,7 @@ ipw_rx_newstate_intr(struct ipw_softc *sc, struct ipw_soft_buf *sbuf)
IEEESTATE(vap), sc->flags));
sc->flags &= ~(IPW_FLAG_ASSOCIATING | IPW_FLAG_ASSOCIATED);
if (vap->iv_state == IEEE80211_S_RUN)
- taskqueue_enqueue(taskqueue_swi,
- &IPW_VAP(vap)->assoc_failed_task);
+ ieee80211_new_state(vap, IEEE80211_S_SCAN, -1);
break;
case IPW_STATE_DISABLED:
@@ -1432,6 +1380,16 @@ ipw_tx_intr(struct ipw_softc *sc)
}
static void
+ipw_fatal_error_intr(struct ipw_softc *sc)
+{
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+
+ device_printf(sc->sc_dev, "firmware error\n");
+ ieee80211_runtask(ic, &sc->sc_init_task);
+}
+
+static void
ipw_intr(void *arg)
{
struct ipw_softc *sc = arg;
@@ -1440,10 +1398,9 @@ ipw_intr(void *arg)
IPW_LOCK(sc);
- if ((r = CSR_READ_4(sc, IPW_CSR_INTR)) == 0 || r == 0xffffffff) {
- IPW_UNLOCK(sc);
- return;
- }
+ r = CSR_READ_4(sc, IPW_CSR_INTR);
+ if (r == 0 || r == 0xffffffff)
+ goto done;
/* disable interrupts */
CSR_WRITE_4(sc, IPW_CSR_INTR_MASK, 0);
@@ -1452,9 +1409,8 @@ ipw_intr(void *arg)
CSR_WRITE_4(sc, IPW_CSR_INTR, r);
if (r & (IPW_INTR_FATAL_ERROR | IPW_INTR_PARITY_ERROR)) {
- device_printf(sc->sc_dev, "firmware error\n");
- taskqueue_enqueue(taskqueue_swi, &sc->sc_init_task);
- r = 0; /* don't process more interrupts */
+ ipw_fatal_error_intr(sc);
+ goto done;
}
if (r & IPW_INTR_FW_INIT_DONE)
@@ -1468,7 +1424,7 @@ ipw_intr(void *arg)
/* re-enable interrupts */
CSR_WRITE_4(sc, IPW_CSR_INTR_MASK, IPW_INTR_MASK);
-
+done:
IPW_UNLOCK(sc);
}
@@ -2181,20 +2137,6 @@ ipw_setscanopts(struct ipw_softc *sc, uint32_t chanmask, uint32_t flags)
return ipw_cmd(sc, IPW_CMD_SET_SCAN_OPTIONS, &opts, sizeof(opts));
}
-/*
- * Handler for sc_scan_task. This is a simple wrapper around ipw_scan().
- */
-static void
-ipw_scan_task(void *context, int pending)
-{
- struct ipw_softc *sc = context;
- IPW_LOCK_DECL;
-
- IPW_LOCK(sc);
- ipw_scan(sc);
- IPW_UNLOCK(sc);
-}
-
static int
ipw_scan(struct ipw_softc *sc)
{
@@ -2258,11 +2200,9 @@ ipw_setchannel(struct ipw_softc *sc, struct ieee80211_channel *chan)
}
static void
-ipw_assoc_task(void *context, int pending)
+ipw_assoc(struct ieee80211com *ic, struct ieee80211vap *vap)
{
- struct ieee80211vap *vap = context;
struct ifnet *ifp = vap->iv_ic->ic_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
struct ipw_softc *sc = ifp->if_softc;
struct ieee80211_node *ni = vap->iv_bss;
struct ipw_security security;
@@ -2353,9 +2293,8 @@ done:
}
static void
-ipw_disassoc_task(void *context, int pending)
+ipw_disassoc(struct ieee80211com *ic, struct ieee80211vap *vap)
{
- struct ieee80211vap *vap = context;
struct ifnet *ifp = vap->iv_ic->ic_ifp;
struct ieee80211_node *ni = vap->iv_bss;
struct ipw_softc *sc = ifp->if_softc;
@@ -2729,8 +2668,7 @@ ipw_scan_start(struct ieee80211com *ic)
IPW_LOCK_DECL;
IPW_LOCK(sc);
- if (!(sc->flags & IPW_FLAG_SCANNING))
- taskqueue_enqueue(taskqueue_swi, &sc->sc_scan_task);
+ ipw_scan(sc);
IPW_UNLOCK(sc);
}
diff --git a/sys/dev/ipw/if_ipwvar.h b/sys/dev/ipw/if_ipwvar.h
index de35019..24fb8e8 100644
--- a/sys/dev/ipw/if_ipwvar.h
+++ b/sys/dev/ipw/if_ipwvar.h
@@ -78,11 +78,6 @@ struct ipw_tx_radiotap_header {
struct ipw_vap {
struct ieee80211vap vap;
- struct task assoc_task;
- struct task disassoc_task;
- struct task assoc_success_task;
- struct task assoc_failed_task;
- struct task scandone_task;
int (*newstate)(struct ieee80211vap *,
enum ieee80211_state, int);
@@ -95,9 +90,6 @@ struct ipw_softc {
struct mtx sc_mtx;
struct task sc_init_task;
- struct task sc_scan_task;
- struct task sc_chan_task;
- struct task sc_bmiss_task;
struct callout sc_wdtimer; /* watchdog timer */
uint32_t flags;
diff --git a/sys/dev/iwi/if_iwi.c b/sys/dev/iwi/if_iwi.c
index 83ab3e5..6957f9b 100644
--- a/sys/dev/iwi/if_iwi.c
+++ b/sys/dev/iwi/if_iwi.c
@@ -158,9 +158,6 @@ static int iwi_wme_update(struct ieee80211com *);
static uint16_t iwi_read_prom_word(struct iwi_softc *, uint8_t);
static void iwi_frame_intr(struct iwi_softc *, struct iwi_rx_data *, int,
struct iwi_frame *);
-static void iwi_authsuccess(void *, int);
-static void iwi_assocsuccess(void *, int);
-static void iwi_assocfailed(void *, int);
static void iwi_notification_intr(struct iwi_softc *, struct iwi_notif *);
static void iwi_rx_intr(struct iwi_softc *);
static void iwi_tx_intr(struct iwi_softc *, struct iwi_tx_ring *);
@@ -186,16 +183,11 @@ static void iwi_put_firmware(struct iwi_softc *);
static int iwi_scanchan(struct iwi_softc *, unsigned long, int);
static void iwi_scan_start(struct ieee80211com *);
static void iwi_scan_end(struct ieee80211com *);
-static void iwi_scanabort(void *, int);
static void iwi_set_channel(struct ieee80211com *);
static void iwi_scan_curchan(struct ieee80211_scan_state *, unsigned long maxdwell);
-#if 0
-static void iwi_scan_allchan(struct ieee80211com *, unsigned long maxdwell);
-#endif
static void iwi_scan_mindwell(struct ieee80211_scan_state *);
-static void iwi_ops(void *, int);
-static int iwi_queue_cmd(struct iwi_softc *, int, unsigned long);
static int iwi_auth_and_assoc(struct iwi_softc *, struct ieee80211vap *);
+static void iwi_disassoc(void *, int);
static int iwi_disassociate(struct iwi_softc *, int quiet);
static void iwi_init_locked(struct iwi_softc *);
static void iwi_init(void *);
@@ -292,24 +284,14 @@ iwi_attach(device_t dev)
ic = ifp->if_l2com;
IWI_LOCK_INIT(sc);
- IWI_CMD_LOCK_INIT(sc);
sc->sc_unr = new_unrhdr(1, IWI_MAX_IBSSNODE-1, &sc->sc_mtx);
- sc->sc_tq = taskqueue_create("iwi_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));
- sc->sc_tq2 = taskqueue_create("iwi_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));
-
TASK_INIT(&sc->sc_radiontask, 0, iwi_radio_on, sc);
TASK_INIT(&sc->sc_radiofftask, 0, iwi_radio_off, sc);
TASK_INIT(&sc->sc_restarttask, 0, iwi_restart, sc);
- TASK_INIT(&sc->sc_opstask, 0, iwi_ops, sc);
- TASK_INIT(&sc->sc_scanaborttask, 0, iwi_scanabort, sc);
+ TASK_INIT(&sc->sc_disassoctask, 0, iwi_disassoc, sc);
+
callout_init_mtx(&sc->sc_wdtimer, &sc->sc_mtx, 0);
callout_init_mtx(&sc->sc_rftimer, &sc->sc_mtx, 0);
@@ -483,8 +465,10 @@ iwi_detach(device_t dev)
ieee80211_ifdetach(ic);
/* NB: do early to drain any pending tasks */
- taskqueue_free(sc->sc_tq);
- taskqueue_free(sc->sc_tq2);
+ ieee80211_draintask(ic, &sc->sc_radiontask);
+ ieee80211_draintask(ic, &sc->sc_radiofftask);
+ ieee80211_draintask(ic, &sc->sc_restarttask);
+ ieee80211_draintask(ic, &sc->sc_disassoctask);
iwi_put_firmware(sc);
iwi_release_fw_dma(sc);
@@ -504,7 +488,6 @@ iwi_detach(device_t dev)
delete_unrhdr(sc->sc_unr);
IWI_LOCK_DESTROY(sc);
- IWI_CMD_LOCK_DESTROY(sc);
if_free(ifp);
@@ -552,10 +535,6 @@ iwi_vap_create(struct ieee80211com *ic,
ivp->iwi_newstate = vap->iv_newstate;
vap->iv_newstate = iwi_newstate;
- TASK_INIT(&ivp->iwi_authsuccess_task, 0, iwi_authsuccess, vap);
- TASK_INIT(&ivp->iwi_assocsuccess_task, 0, iwi_assocsuccess, vap);
- TASK_INIT(&ivp->iwi_assocfailed_task, 0, iwi_assocfailed, vap);
-
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change, iwi_media_status);
ic->ic_opmode = opmode;
@@ -987,21 +966,21 @@ iwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ieee80211_state_name[vap->iv_state],
ieee80211_state_name[nstate], sc->flags));
+ IEEE80211_UNLOCK(ic);
+ IWI_LOCK(sc);
switch (nstate) {
case IEEE80211_S_INIT:
- IWI_LOCK(sc);
/*
* NB: don't try to do this if iwi_stop_master has
* shutdown the firmware and disabled interrupts.
*/
if (vap->iv_state == IEEE80211_S_RUN &&
(sc->flags & IWI_FLAG_FW_INITED))
- iwi_queue_cmd(sc, IWI_DISASSOC, 1);
- IWI_UNLOCK(sc);
+ iwi_disassociate(sc, 0);
break;
case IEEE80211_S_AUTH:
- iwi_queue_cmd(sc, IWI_AUTH, arg);
- return EINPROGRESS;
+ iwi_auth_and_assoc(sc, vap);
+ break;
case IEEE80211_S_RUN:
if (vap->iv_opmode == IEEE80211_M_IBSS &&
vap->iv_state == IEEE80211_S_SCAN) {
@@ -1013,8 +992,7 @@ iwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
* AUTH -> RUN transition and we want to do nothing.
* This is all totally bogus and needs to be redone.
*/
- iwi_queue_cmd(sc, IWI_ASSOC, 0);
- return EINPROGRESS;
+ iwi_auth_and_assoc(sc, vap);
}
break;
case IEEE80211_S_ASSOC:
@@ -1025,11 +1003,13 @@ iwi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
*/
if (vap->iv_state == IEEE80211_S_AUTH)
break;
- iwi_queue_cmd(sc, IWI_ASSOC, arg);
- return EINPROGRESS;
+ iwi_auth_and_assoc(sc, vap);
+ break;
default:
break;
}
+ IWI_UNLOCK(sc);
+ IEEE80211_LOCK(ic);
return ivp->iwi_newstate(vap, nstate, arg);
}
@@ -1106,6 +1086,7 @@ static int
iwi_wme_update(struct ieee80211com *ic)
{
struct iwi_softc *sc = ic->ic_ifp->if_softc;
+ struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
/*
* We may be called to update the WME parameters in
@@ -1115,7 +1096,9 @@ iwi_wme_update(struct ieee80211com *ic)
* will get sent down to the adapter as part of the
* work iwi_auth_and_assoc does.
*/
- return iwi_queue_cmd(sc, IWI_SET_WME, 0);
+ if (vap->iv_state == IEEE80211_S_RUN)
+ (void) iwi_wme_setparams(sc, ic);
+ return (0);
}
static int
@@ -1389,30 +1372,6 @@ iwi_checkforqos(struct ieee80211vap *vap,
*/
static void
-iwi_authsuccess(void *arg, int npending)
-{
- struct ieee80211vap *vap = arg;
-
- ieee80211_new_state(vap, IEEE80211_S_ASSOC, -1);
-}
-
-static void
-iwi_assocsuccess(void *arg, int npending)
-{
- struct ieee80211vap *vap = arg;
-
- ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
-}
-
-static void
-iwi_assocfailed(void *arg, int npending)
-{
- struct ieee80211vap *vap = arg;
-
- ieee80211_new_state(vap, IEEE80211_S_SCAN, -1);
-}
-
-static void
iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif)
{
struct ifnet *ifp = sc->sc_ifp;
@@ -1454,8 +1413,7 @@ iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif)
switch (auth->state) {
case IWI_AUTH_SUCCESS:
DPRINTFN(2, ("Authentication succeeeded\n"));
- taskqueue_enqueue(taskqueue_swi,
- &IWI_VAP(vap)->iwi_authsuccess_task);
+ ieee80211_new_state(vap, IEEE80211_S_ASSOC, -1);
break;
case IWI_AUTH_FAIL:
/*
@@ -1472,8 +1430,7 @@ iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif)
DPRINTFN(2, ("Deauthenticated\n"));
vap->iv_stats.is_rx_deauth++;
}
- taskqueue_enqueue(taskqueue_swi,
- &IWI_VAP(vap)->iwi_assocfailed_task);
+ ieee80211_new_state(vap, IEEE80211_S_SCAN, -1);
break;
case IWI_AUTH_SENT_1:
case IWI_AUTH_RECV_2:
@@ -1506,8 +1463,7 @@ iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif)
iwi_checkforqos(vap,
(const struct ieee80211_frame *)(assoc+1),
le16toh(notif->len) - sizeof(*assoc));
- taskqueue_enqueue(taskqueue_swi,
- &IWI_VAP(vap)->iwi_assocsuccess_task);
+ ieee80211_new_state(vap, IEEE80211_S_RUN, -1);
break;
case IWI_ASSOC_INIT:
sc->flags &= ~IWI_FLAG_ASSOCIATED;
@@ -1515,16 +1471,14 @@ iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif)
case IWI_FW_ASSOCIATING:
DPRINTFN(2, ("Association failed\n"));
IWI_STATE_END(sc, IWI_FW_ASSOCIATING);
- taskqueue_enqueue(taskqueue_swi,
- &IWI_VAP(vap)->iwi_assocfailed_task);
+ ieee80211_new_state(vap, IEEE80211_S_SCAN, -1);
break;
case IWI_FW_DISASSOCIATING:
DPRINTFN(2, ("Dissassociated\n"));
IWI_STATE_END(sc, IWI_FW_DISASSOCIATING);
vap->iv_stats.is_rx_disassoc++;
- taskqueue_enqueue(taskqueue_swi,
- &IWI_VAP(vap)->iwi_assocfailed_task);
+ ieee80211_new_state(vap, IEEE80211_S_SCAN, -1);
break;
}
break;
@@ -1563,7 +1517,7 @@ iwi_notification_intr(struct iwi_softc *sc, struct iwi_notif *notif)
* to disassociate and then on completion we'll
* kick the state machine to scan.
*/
- iwi_queue_cmd(sc, IWI_DISASSOC, 1);
+ ieee80211_runtask(ic, &sc->sc_disassoctask);
}
}
break;
@@ -1664,6 +1618,29 @@ iwi_tx_intr(struct iwi_softc *sc, struct iwi_tx_ring *txq)
}
static void
+iwi_fatal_error_intr(struct iwi_softc *sc)
+{
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+
+ device_printf(sc->sc_dev, "firmware error\n");
+ ieee80211_runtask(ic, &sc->sc_restarttask);
+
+ sc->flags &= ~IWI_FLAG_BUSY;
+ sc->sc_busy_timer = 0;
+ wakeup(sc);
+}
+
+static void
+iwi_radio_off_intr(struct iwi_softc *sc)
+{
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+
+ ieee80211_runtask(ic, &sc->sc_radiofftask);
+}
+
+static void
iwi_intr(void *arg)
{
struct iwi_softc *sc = arg;
@@ -1681,12 +1658,8 @@ iwi_intr(void *arg)
CSR_WRITE_4(sc, IWI_CSR_INTR, r);
if (r & IWI_INTR_FATAL_ERROR) {
- device_printf(sc->sc_dev, "firmware error\n");
- taskqueue_enqueue(sc->sc_tq2, &sc->sc_restarttask);
-
- sc->flags &= ~IWI_FLAG_BUSY;
- sc->sc_busy_timer = 0;
- wakeup(sc);
+ iwi_fatal_error_intr(sc);
+ goto done;
}
if (r & IWI_INTR_FW_INITED) {
@@ -1695,7 +1668,7 @@ iwi_intr(void *arg)
}
if (r & IWI_INTR_RADIO_OFF)
- taskqueue_enqueue(sc->sc_tq, &sc->sc_radiofftask);
+ iwi_radio_off_intr(sc);
if (r & IWI_INTR_CMD_DONE) {
sc->flags &= ~IWI_FLAG_BUSY;
@@ -1722,7 +1695,7 @@ iwi_intr(void *arg)
/* XXX rate-limit */
device_printf(sc->sc_dev, "parity error\n");
}
-
+done:
IWI_UNLOCK(sc);
}
@@ -2008,6 +1981,7 @@ iwi_watchdog(void *arg)
{
struct iwi_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
IWI_LOCK_ASSERT(sc);
@@ -2015,25 +1989,25 @@ iwi_watchdog(void *arg)
if (--sc->sc_tx_timer == 0) {
if_printf(ifp, "device timeout\n");
ifp->if_oerrors++;
- taskqueue_enqueue(sc->sc_tq2, &sc->sc_restarttask);
+ ieee80211_runtask(ic, &sc->sc_restarttask);
}
}
if (sc->sc_state_timer > 0) {
if (--sc->sc_state_timer == 0) {
if_printf(ifp, "firmware stuck in state %d, resetting\n",
sc->fw_state);
- taskqueue_enqueue(sc->sc_tq2, &sc->sc_restarttask);
if (sc->fw_state == IWI_FW_SCANNING) {
struct ieee80211com *ic = ifp->if_l2com;
ieee80211_cancel_scan(TAILQ_FIRST(&ic->ic_vaps));
}
+ ieee80211_runtask(ic, &sc->sc_restarttask);
sc->sc_state_timer = 3;
}
}
if (sc->sc_busy_timer > 0) {
if (--sc->sc_busy_timer == 0) {
if_printf(ifp, "firmware command timeout, resetting\n");
- taskqueue_enqueue(sc->sc_tq2, &sc->sc_restarttask);
+ ieee80211_runtask(ic, &sc->sc_restarttask);
}
}
callout_reset(&sc->sc_wdtimer, hz, iwi_watchdog, sc);
@@ -2665,7 +2639,7 @@ scan_band(const struct ieee80211_channel *c)
* Start a scan on the current channel or all channels.
*/
static int
-iwi_scanchan(struct iwi_softc *sc, unsigned long maxdwell, int mode)
+iwi_scanchan(struct iwi_softc *sc, unsigned long maxdwell, int allchan)
{
struct ieee80211com *ic;
struct ieee80211_channel *chan;
@@ -2712,7 +2686,7 @@ iwi_scanchan(struct iwi_softc *sc, unsigned long maxdwell, int mode)
return (error);
}
- if (mode == IWI_SCAN_ALLCHAN) {
+ if (allchan) {
int i, next, band, b, bstart;
/*
* Convert scan list to run-length encoded channel list
@@ -2781,20 +2755,6 @@ iwi_scanchan(struct iwi_softc *sc, unsigned long maxdwell, int mode)
return (iwi_cmd(sc, IWI_CMD_SCAN_EXT, &scan, sizeof scan));
}
-static void
-iwi_scanabort(void *arg, int npending)
-{
- struct iwi_softc *sc = arg;
- IWI_LOCK_DECL;
-
- IWI_LOCK(sc);
- sc->flags &= ~IWI_FLAG_CHANNEL_SCAN;
- /* NB: make sure we're still scanning */
- if (sc->fw_state == IWI_FW_SCANNING)
- iwi_cmd(sc, IWI_CMD_ABORT_SCAN, NULL, 0);
- IWI_UNLOCK(sc);
-}
-
static int
iwi_set_sensitivity(struct iwi_softc *sc, int8_t rssi_dbm)
{
@@ -2986,6 +2946,17 @@ done:
return (error);
}
+static void
+iwi_disassoc(void *arg, int pending)
+{
+ struct iwi_softc *sc = arg;
+ IWI_LOCK_DECL;
+
+ IWI_LOCK(sc);
+ iwi_disassociate(sc, 0);
+ IWI_UNLOCK(sc);
+}
+
static int
iwi_disassociate(struct iwi_softc *sc, int quiet)
{
@@ -3086,9 +3057,6 @@ iwi_init_locked(struct iwi_softc *sc)
IWI_STATE_BEGIN(sc, IWI_FW_LOADING);
- taskqueue_unblock(sc->sc_tq);
- taskqueue_unblock(sc->sc_tq2);
-
if (iwi_reset(sc) != 0) {
device_printf(sc->sc_dev, "could not reset adapter\n");
goto fail;
@@ -3183,8 +3151,6 @@ iwi_stop_locked(void *priv)
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
- taskqueue_block(sc->sc_tq);
- taskqueue_block(sc->sc_tq2);
if (sc->sc_softled) {
callout_stop(&sc->sc_ledtimer);
sc->sc_blinking = 0;
@@ -3204,7 +3170,6 @@ iwi_stop_locked(void *priv)
iwi_reset_tx_ring(sc, &sc->txq[3]);
iwi_reset_rx_ring(sc, &sc->rxq);
- memset(sc->sc_cmd, 0, sizeof(sc->sc_cmd));
sc->sc_tx_timer = 0;
sc->sc_state_timer = 0;
sc->sc_busy_timer = 0;
@@ -3266,8 +3231,10 @@ iwi_rfkill_poll(void *arg)
* it is enabled so we must poll for the latter.
*/
if (!iwi_getrfkill(sc)) {
- taskqueue_unblock(sc->sc_tq);
- taskqueue_enqueue(sc->sc_tq, &sc->sc_radiontask);
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+
+ ieee80211_runtask(ic, &sc->sc_radiontask);
return;
}
callout_reset(&sc->sc_rftimer, 2*hz, iwi_rfkill_poll, sc);
@@ -3533,114 +3500,9 @@ iwi_ledattach(struct iwi_softc *sc)
}
static void
-iwi_ops(void *arg0, int npending)
-{
- static const char *opnames[] = {
- [IWI_CMD_FREE] = "FREE",
- [IWI_SCAN_START] = "SCAN_START",
- [IWI_SET_CHANNEL] = "SET_CHANNEL",
- [IWI_AUTH] = "AUTH",
- [IWI_ASSOC] = "ASSOC",
- [IWI_DISASSOC] = "DISASSOC",
- [IWI_SCAN_CURCHAN] = "SCAN_CURCHAN",
- [IWI_SCAN_ALLCHAN] = "SCAN_ALLCHAN",
- [IWI_SET_WME] = "SET_WME",
- };
- struct iwi_softc *sc = arg0;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
- IWI_LOCK_DECL;
- int cmd;
- unsigned long arg;
-
-again:
- IWI_CMD_LOCK(sc);
- cmd = sc->sc_cmd[sc->sc_cmd_cur];
- if (cmd == IWI_CMD_FREE) {
- /* No more commands to process */
- IWI_CMD_UNLOCK(sc);
- return;
- }
- arg = sc->sc_arg[sc->sc_cmd_cur];
- sc->sc_cmd[sc->sc_cmd_cur] = IWI_CMD_FREE; /* free the slot */
- sc->sc_cmd_cur = (sc->sc_cmd_cur + 1) % IWI_CMD_MAXOPS;
- IWI_CMD_UNLOCK(sc);
-
- IWI_LOCK(sc);
- while (sc->fw_state != IWI_FW_IDLE || (sc->flags & IWI_FLAG_BUSY)) {
- msleep(sc, &sc->sc_mtx, 0, "iwicmd", hz/10);
- }
-
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- IWI_UNLOCK(sc);
- return;
- }
-
- DPRINTF(("%s: %s arg %lu\n", __func__, opnames[cmd], arg));
- switch (cmd) {
- case IWI_AUTH:
- case IWI_ASSOC:
- if (cmd == IWI_AUTH)
- vap->iv_state = IEEE80211_S_AUTH;
- else
- vap->iv_state = IEEE80211_S_ASSOC;
- iwi_auth_and_assoc(sc, vap);
- /* NB: completion done in iwi_notification_intr */
- break;
- case IWI_DISASSOC:
- iwi_disassociate(sc, 0);
- break;
- case IWI_SET_WME:
- if (vap->iv_state == IEEE80211_S_RUN)
- (void) iwi_wme_setparams(sc, ic);
- break;
- case IWI_SCAN_START:
- sc->flags |= IWI_FLAG_CHANNEL_SCAN;
- break;
- case IWI_SCAN_CURCHAN:
- case IWI_SCAN_ALLCHAN:
- if (!(sc->flags & IWI_FLAG_CHANNEL_SCAN)) {
- DPRINTF(("%s: ic_scan_curchan while not scanning\n",
- __func__));
- goto done;
- }
- if (iwi_scanchan(sc, arg, cmd))
- ieee80211_cancel_scan(vap);
- break;
- }
-done:
- IWI_UNLOCK(sc);
-
- /* Take another pass */
- goto again;
-}
-
-static int
-iwi_queue_cmd(struct iwi_softc *sc, int cmd, unsigned long arg)
-{
- IWI_CMD_LOCK(sc);
- if (sc->sc_cmd[sc->sc_cmd_next] != 0) {
- IWI_CMD_UNLOCK(sc);
- DPRINTF(("%s: command %d dropped\n", __func__, cmd));
- return (EBUSY);
- }
-
- sc->sc_cmd[sc->sc_cmd_next] = cmd;
- sc->sc_arg[sc->sc_cmd_next] = arg;
- sc->sc_cmd_next = (sc->sc_cmd_next + 1) % IWI_CMD_MAXOPS;
- taskqueue_enqueue(sc->sc_tq, &sc->sc_opstask);
- IWI_CMD_UNLOCK(sc);
- return (0);
-}
-
-static void
iwi_scan_start(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct iwi_softc *sc = ifp->if_softc;
-
- iwi_queue_cmd(sc, IWI_SCAN_START, 0);
+ /* ignore */
}
static void
@@ -3658,20 +3520,13 @@ iwi_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
struct ieee80211vap *vap = ss->ss_vap;
struct ifnet *ifp = vap->iv_ic->ic_ifp;
struct iwi_softc *sc = ifp->if_softc;
+ IWI_LOCK_DECL;
- iwi_queue_cmd(sc, IWI_SCAN_CURCHAN, maxdwell);
-}
-
-#if 0
-static void
-iwi_scan_allchan(struct ieee80211com *ic, unsigned long maxdwell)
-{
- struct ifnet *ifp = ic->ic_ifp;
- struct iwi_softc *sc = ifp->if_softc;
-
- iwi_queue_cmd(sc, IWI_SCAN_ALLCHAN, maxdwell);
+ IWI_LOCK(sc);
+ if (iwi_scanchan(sc, maxdwell, 0))
+ ieee80211_cancel_scan(vap);
+ IWI_UNLOCK(sc);
}
-#endif
static void
iwi_scan_mindwell(struct ieee80211_scan_state *ss)
@@ -3684,6 +3539,12 @@ iwi_scan_end(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct iwi_softc *sc = ifp->if_softc;
+ IWI_LOCK_DECL;
- taskqueue_enqueue(sc->sc_tq2, &sc->sc_scanaborttask);
+ IWI_LOCK(sc);
+ sc->flags &= ~IWI_FLAG_CHANNEL_SCAN;
+ /* NB: make sure we're still scanning */
+ if (sc->fw_state == IWI_FW_SCANNING)
+ iwi_cmd(sc, IWI_CMD_ABORT_SCAN, NULL, 0);
+ IWI_UNLOCK(sc);
}
diff --git a/sys/dev/iwi/if_iwivar.h b/sys/dev/iwi/if_iwivar.h
index abc6f9c..25db9cf 100644
--- a/sys/dev/iwi/if_iwivar.h
+++ b/sys/dev/iwi/if_iwivar.h
@@ -116,9 +116,6 @@ struct iwi_fw {
struct iwi_vap {
struct ieee80211vap iwi_vap;
- struct task iwi_authsuccess_task;
- struct task iwi_assocsuccess_task;
- struct task iwi_assocfailed_task;
int (*iwi_newstate)(struct ieee80211vap *,
enum ieee80211_state, int);
@@ -131,12 +128,8 @@ struct iwi_softc {
device_t sc_dev;
struct mtx sc_mtx;
- struct mtx sc_cmdlock;
- char sc_cmdname[12]; /* e.g. "iwi0_cmd" */
uint8_t sc_mcast[IEEE80211_ADDR_LEN];
struct unrhdr *sc_unr;
- struct taskqueue *sc_tq; /* private task queue */
- struct taskqueue *sc_tq2; /* reset task queue */
uint32_t flags;
#define IWI_FLAG_FW_INITED (1 << 0)
@@ -195,9 +188,8 @@ struct iwi_softc {
struct task sc_radiontask; /* radio on processing */
struct task sc_radiofftask; /* radio off processing */
- struct task sc_scanaborttask; /* cancel active scan */
struct task sc_restarttask; /* restart adapter processing */
- struct task sc_opstask; /* scan / auth processing */
+ struct task sc_disassoctask;
unsigned int sc_softled : 1, /* enable LED gpio status */
sc_ledstate: 1, /* LED on/off state */
@@ -219,21 +211,6 @@ struct iwi_softc {
int sc_state_timer; /* firmware state timer */
int sc_busy_timer; /* firmware cmd timer */
-#define IWI_CMD_MAXOPS 10
- int sc_cmd[IWI_CMD_MAXOPS];
- unsigned long sc_arg[IWI_CMD_MAXOPS];
- int sc_cmd_cur; /* current queued scan task */
- int sc_cmd_next; /* last queued scan task */
-#define IWI_CMD_FREE 0 /* for marking slots unused */
-#define IWI_SCAN_START 1
-#define IWI_SET_CHANNEL 2
-#define IWI_AUTH 3
-#define IWI_ASSOC 4
-#define IWI_DISASSOC 5
-#define IWI_SCAN_CURCHAN 6
-#define IWI_SCAN_ALLCHAN 7
-#define IWI_SET_WME 8
-
struct iwi_rx_radiotap_header sc_rxtap;
int sc_rxtap_len;
@@ -277,11 +254,3 @@ struct iwi_softc {
if (!__waslocked) \
mtx_unlock(&(sc)->sc_mtx); \
} while (0)
-#define IWI_CMD_LOCK_INIT(sc) do { \
- snprintf((sc)->sc_cmdname, sizeof((sc)->sc_cmdname), "%s_cmd", \
- device_get_nameunit((sc)->sc_dev)); \
- mtx_init(&(sc)->sc_cmdlock, (sc)->sc_cmdname, NULL, MTX_DEF); \
-} while (0)
-#define IWI_CMD_LOCK_DESTROY(sc) mtx_destroy(&(sc)->sc_cmdlock)
-#define IWI_CMD_LOCK(sc) mtx_lock(&(sc)->sc_cmdlock)
-#define IWI_CMD_UNLOCK(sc) mtx_unlock(&(sc)->sc_cmdlock)
diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c
index 2928c0f..f32bdaa 100644
--- a/sys/dev/iwn/if_iwn.c
+++ b/sys/dev/iwn/if_iwn.c
@@ -129,7 +129,6 @@ void iwn_rx_intr(struct iwn_softc *, struct iwn_rx_desc *,
void iwn_rx_statistics(struct iwn_softc *, struct iwn_rx_desc *);
void iwn_tx_intr(struct iwn_softc *, struct iwn_rx_desc *);
void iwn_cmd_intr(struct iwn_softc *, struct iwn_rx_desc *);
-static void iwn_bmiss(void *, int);
void iwn_notif_intr(struct iwn_softc *);
void iwn_intr(void *);
void iwn_read_eeprom(struct iwn_softc *,
@@ -166,8 +165,8 @@ void iwn_compute_differential_gain(struct iwn_softc *,
void iwn_tune_sensitivity(struct iwn_softc *,
const struct iwn_rx_stats *);
int iwn_send_sensitivity(struct iwn_softc *);
-int iwn_auth(struct iwn_softc *);
-int iwn_run(struct iwn_softc *);
+int iwn_auth(struct iwn_softc *, struct ieee80211vap *);
+int iwn_run(struct iwn_softc *, struct ieee80211vap *);
int iwn_scan(struct iwn_softc *);
int iwn_config(struct iwn_softc *);
void iwn_post_alive(struct iwn_softc *);
@@ -183,8 +182,9 @@ static void iwn_scan_end(struct ieee80211com *);
static void iwn_set_channel(struct ieee80211com *);
static void iwn_scan_curchan(struct ieee80211_scan_state *, unsigned long);
static void iwn_scan_mindwell(struct ieee80211_scan_state *);
-static void iwn_ops(void *, int);
-static int iwn_queue_cmd( struct iwn_softc *, int, int, int);
+static void iwn_hwreset(void *, int);
+static void iwn_radioon(void *, int);
+static void iwn_radiooff(void *, int);
static void iwn_bpfattach(struct iwn_softc *);
static void iwn_sysctlattach(struct iwn_softc *);
@@ -213,7 +213,6 @@ enum {
printf(fmt, __VA_ARGS__); \
} while (0)
-static const char *iwn_ops_str(int);
static const char *iwn_intr_str(uint8_t);
#else
#define DPRINTF(sc, m, fmt, ...) do { (void) sc; } while (0)
@@ -296,20 +295,10 @@ iwn_attach(device_t dev)
}
IWN_LOCK_INIT(sc);
- IWN_CMD_LOCK_INIT(sc);
callout_init_mtx(&sc->sc_timer_to, &sc->sc_mtx, 0);
-
- /*
- * Create the taskqueues used by the driver. Primarily
- * sc_tq handles most the task
- */
- sc->sc_tq = taskqueue_create("iwn_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_ops_task, 0, iwn_ops, sc );
- TASK_INIT(&sc->sc_bmiss_task, 0, iwn_bmiss, sc);
+ TASK_INIT(&sc->sc_reinit_task, 0, iwn_hwreset, sc );
+ TASK_INIT(&sc->sc_radioon_task, 0, iwn_radioon, sc );
+ TASK_INIT(&sc->sc_radiooff_task, 0, iwn_radiooff, sc );
/*
* Put adapter into a known state.
@@ -475,6 +464,10 @@ iwn_cleanup(device_t dev)
struct ieee80211com *ic = ifp->if_l2com;
int i;
+ ieee80211_draintask(ic, &sc->sc_reinit_task);
+ ieee80211_draintask(ic, &sc->sc_radioon_task);
+ ieee80211_draintask(ic, &sc->sc_radiooff_task);
+
if (ifp != NULL) {
iwn_stop(sc);
callout_drain(&sc->sc_timer_to);
@@ -499,8 +492,6 @@ iwn_cleanup(device_t dev)
bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem);
if (ifp != NULL)
if_free(ifp);
- taskqueue_free(sc->sc_tq);
- IWN_CMD_LOCK_DESTROY(sc);
IWN_LOCK_DESTROY(sc);
return 0;
}
@@ -983,20 +974,13 @@ iwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ieee80211_state_name[vap->iv_state],
ieee80211_state_name[nstate]);
+ IEEE80211_UNLOCK(ic);
IWN_LOCK(sc);
callout_stop(&sc->sc_timer_to);
- IWN_UNLOCK(sc);
- /*
- * Some state transitions require issuing a configure request
- * to the adapter. This must be done in a blocking context
- * so we toss control to the task q thread where the state
- * change will be finished after the command completes.
- */
if (nstate == IEEE80211_S_AUTH && vap->iv_state != IEEE80211_S_AUTH) {
/* !AUTH -> AUTH requires adapter config */
- error = iwn_queue_cmd(sc, IWN_AUTH, arg, IWN_QUEUE_NORMAL);
- return (error != 0 ? error : EINPROGRESS);
+ error = iwn_auth(sc, vap);
}
if (nstate == IEEE80211_S_RUN && vap->iv_state != IEEE80211_S_RUN) {
/*
@@ -1004,8 +988,7 @@ iwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
* which is done with a firmware cmd. We also defer
* starting the timers until that work is done.
*/
- error = iwn_queue_cmd(sc, IWN_RUN, arg, IWN_QUEUE_NORMAL);
- return (error != 0 ? error : EINPROGRESS);
+ error = iwn_run(sc, vap);
}
if (nstate == IEEE80211_S_RUN) {
/*
@@ -1013,6 +996,8 @@ iwn_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
*/
iwn_calib_reset(sc);
}
+ IWN_UNLOCK(sc);
+ IEEE80211_LOCK(ic);
return ivp->iv_newstate(vap, nstate, arg);
}
@@ -1657,15 +1642,6 @@ iwn_cmd_intr(struct iwn_softc *sc, struct iwn_rx_desc *desc)
wakeup(&ring->cmd[desc->idx]);
}
-static void
-iwn_bmiss(void *arg, int npending)
-{
- struct iwn_softc *sc = arg;
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
-
- ieee80211_beacon_miss(ic);
-}
-
void
iwn_notif_intr(struct iwn_softc *sc)
{
@@ -1726,8 +1702,7 @@ iwn_notif_intr(struct iwn_softc *sc)
if (vap->iv_state == IEEE80211_S_RUN && misses > 5)
(void) iwn_init_sensitivity(sc);
if (misses >= vap->iv_bmissthreshold)
- taskqueue_enqueue(taskqueue_swi,
- &sc->sc_bmiss_task);
+ ieee80211_beacon_miss(ic);
break;
}
case IWN_UC_READY: {
@@ -1780,7 +1755,7 @@ iwn_notif_intr(struct iwn_softc *sc)
"scan finished nchan=%d status=%d chan=%d\n",
scan->nchan, scan->status, scan->chan);
- iwn_queue_cmd(sc, IWN_SCAN_NEXT, 0, IWN_QUEUE_NORMAL);
+ ieee80211_scan_next(vap);
break;
}
}
@@ -1792,6 +1767,36 @@ iwn_notif_intr(struct iwn_softc *sc)
IWN_WRITE(sc, IWN_RX_WIDX, hw & ~7);
}
+static void
+iwn_rftoggle_intr(struct iwn_softc *sc)
+{
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+ uint32_t tmp = IWN_READ(sc, IWN_GPIO_CTL);
+
+ IWN_LOCK_ASSERT(sc);
+
+ device_printf(sc->sc_dev, "RF switch: radio %s\n",
+ (tmp & IWN_GPIO_RF_ENABLED) ? "enabled" : "disabled");
+ if (tmp & IWN_GPIO_RF_ENABLED)
+ ieee80211_runtask(ic, &sc->sc_radioon_task);
+ else
+ ieee80211_runtask(ic, &sc->sc_radiooff_task);
+}
+
+static void
+iwn_error_intr(struct iwn_softc *sc, uint32_t r1, uint32_t r2)
+{
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+
+ IWN_LOCK_ASSERT(sc);
+
+ device_printf(sc->sc_dev, "error, INTR=%b STATUS=0x%x\n",
+ r1, IWN_INTR_BITS, r2);
+ ieee80211_runtask(ic, &sc->sc_reinit_task);
+}
+
void
iwn_intr(void *arg)
{
@@ -1820,21 +1825,12 @@ iwn_intr(void *arg)
DPRINTF(sc, IWN_DEBUG_INTR, "interrupt reg1=%x reg2=%x\n", r1, r2);
- if (r1 & IWN_RF_TOGGLED) {
- uint32_t tmp = IWN_READ(sc, IWN_GPIO_CTL);
- device_printf(sc->sc_dev, "RF switch: radio %s\n",
- (tmp & IWN_GPIO_RF_ENABLED) ? "enabled" : "disabled");
- if (tmp & IWN_GPIO_RF_ENABLED)
- iwn_queue_cmd(sc, IWN_RADIO_ENABLE, 0, IWN_QUEUE_CLEAR);
- else
- iwn_queue_cmd(sc, IWN_RADIO_DISABLE, 0, IWN_QUEUE_CLEAR);
- }
+ if (r1 & IWN_RF_TOGGLED)
+ iwn_rftoggle_intr(sc);
if (r1 & IWN_CT_REACHED)
device_printf(sc->sc_dev, "critical temperature reached!\n");
if (r1 & (IWN_SW_ERROR | IWN_HW_ERROR)) {
- device_printf(sc->sc_dev, "error, INTR=%b STATUS=0x%x\n",
- r1, IWN_INTR_BITS, r2);
- iwn_queue_cmd(sc, IWN_REINIT, 0, IWN_QUEUE_CLEAR);
+ iwn_error_intr(sc, r1, r2);
goto done;
}
if ((r1 & (IWN_RX_INTR | IWN_SW_RX_INTR)) || (r2 & IWN_RX_STATUS_INTR))
@@ -2361,9 +2357,10 @@ iwn_watchdog(struct iwn_softc *sc)
{
if (sc->sc_tx_timer > 0 && --sc->sc_tx_timer == 0) {
struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
if_printf(ifp, "device timeout\n");
- iwn_queue_cmd(sc, IWN_REINIT, 0, IWN_QUEUE_CLEAR);
+ ieee80211_runtask(ic, &sc->sc_reinit_task);
}
}
@@ -3446,11 +3443,10 @@ iwn_send_sensitivity(struct iwn_softc *sc)
}
int
-iwn_auth(struct iwn_softc *sc)
+iwn_auth(struct iwn_softc *sc, struct ieee80211vap *vap)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); /*XXX*/
struct ieee80211_node *ni = vap->iv_bss;
struct iwn_node_info node;
int error;
@@ -3539,12 +3535,11 @@ iwn_auth(struct iwn_softc *sc)
* Configure the adapter for associated state.
*/
int
-iwn_run(struct iwn_softc *sc)
+iwn_run(struct iwn_softc *sc, struct ieee80211vap *vap)
{
#define MS(v,x) (((v) & x) >> x##_S)
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps); /*XXX*/
struct ieee80211_node *ni = vap->iv_bss;
struct iwn_node_info node;
int error, maxrxampdu, ampdudensity;
@@ -4270,9 +4265,6 @@ iwn_stop_locked(struct iwn_softc *sc)
IWN_WRITE(sc, IWN_INTR, 0xffffffff);
IWN_WRITE(sc, IWN_INTR_STATUS, 0xffffffff);
- /* Clear any commands left in the taskq command buffer */
- memset(sc->sc_cmd, 0, sizeof(sc->sc_cmd));
-
/* reset all Tx rings */
for (i = 0; i < IWN_NTXQUEUES; i++)
iwn_reset_tx_ring(sc, &sc->txq[i]);
@@ -4308,7 +4300,10 @@ iwn_scan_start(struct ieee80211com *ic)
struct ifnet *ifp = ic->ic_ifp;
struct iwn_softc *sc = ifp->if_softc;
- iwn_queue_cmd(sc, IWN_SCAN_START, 0, IWN_QUEUE_NORMAL);
+ IWN_LOCK(sc);
+ /* make the link LED blink while we're scanning */
+ iwn_set_led(sc, IWN_LED_LINK, 20, 2);
+ IWN_UNLOCK(sc);
}
/*
@@ -4317,10 +4312,7 @@ iwn_scan_start(struct ieee80211com *ic)
static void
iwn_scan_end(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct iwn_softc *sc = ifp->if_softc;
-
- iwn_queue_cmd(sc, IWN_SCAN_STOP, 0, IWN_QUEUE_NORMAL);
+ /* ignore */
}
/*
@@ -4331,15 +4323,29 @@ iwn_set_channel(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct iwn_softc *sc = ifp->if_softc;
+ struct ieee80211vap *vap;
const struct ieee80211_channel *c = ic->ic_curchan;
+ int error;
+
+ vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */
+ IWN_LOCK(sc);
if (c != sc->sc_curchan) {
sc->sc_rxtap.wr_chan_freq = htole16(c->ic_freq);
sc->sc_rxtap.wr_chan_flags = htole16(c->ic_flags);
sc->sc_txtap.wt_chan_freq = htole16(c->ic_freq);
sc->sc_txtap.wt_chan_flags = htole16(c->ic_flags);
- iwn_queue_cmd(sc, IWN_SET_CHAN, 0, IWN_QUEUE_NORMAL);
+
+ error = iwn_config(sc);
+ if (error != 0) {
+ DPRINTF(sc, IWN_DEBUG_STATE,
+ "%s: set chan failed, cancel scan\n",
+ __func__);
+ //XXX Handle failed scan correctly
+ ieee80211_cancel_scan(vap);
+ }
}
+ IWN_UNLOCK(sc);
}
/*
@@ -4350,8 +4356,13 @@ iwn_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
{
struct ieee80211vap *vap = ss->ss_vap;
struct iwn_softc *sc = vap->iv_ic->ic_ifp->if_softc;
+ int error;
- iwn_queue_cmd(sc, IWN_SCAN_CURCHAN, 0, IWN_QUEUE_NORMAL);
+ IWN_LOCK(sc);
+ error = iwn_scan(sc);
+ IWN_UNLOCK(sc);
+ if (error != 0)
+ ieee80211_cancel_scan(vap);
}
/*
@@ -4365,149 +4376,36 @@ iwn_scan_mindwell(struct ieee80211_scan_state *ss)
/* NB: don't try to abort scan; wait for firmware to finish */
}
-/*
- * Carry out work in the taskq context.
- */
static void
-iwn_ops(void *arg0, int pending)
+iwn_hwreset(void *arg0, int pending)
{
struct iwn_softc *sc = arg0;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap;
- int cmd, arg, error;
- enum ieee80211_state nstate;
- for (;;) {
- IWN_CMD_LOCK(sc);
- cmd = sc->sc_cmd[sc->sc_cmd_cur];
- if (cmd == 0) {
- /* No more commands to process */
- IWN_CMD_UNLOCK(sc);
- return;
- }
- if ((sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0 &&
- cmd != IWN_RADIO_ENABLE ) {
- IWN_CMD_UNLOCK(sc);
- return;
- }
- arg = sc->sc_cmd_arg[sc->sc_cmd_cur];
- sc->sc_cmd[sc->sc_cmd_cur] = 0; /* free the slot */
- sc->sc_cmd_cur = (sc->sc_cmd_cur + 1) % IWN_CMD_MAXOPS;
- IWN_CMD_UNLOCK(sc);
-
- IWN_LOCK(sc); /* NB: sync debug printfs on smp */
- DPRINTF(sc, IWN_DEBUG_OPS, "%s: %s (cmd 0x%x)\n",
- __func__, iwn_ops_str(cmd), cmd);
-
- vap = TAILQ_FIRST(&ic->ic_vaps); /* XXX */
- switch (cmd) {
- case IWN_SCAN_START:
- /* make the link LED blink while we're scanning */
- iwn_set_led(sc, IWN_LED_LINK, 20, 2);
- break;
- case IWN_SCAN_STOP:
- break;
- case IWN_SCAN_NEXT:
- ieee80211_scan_next(vap);
- break;
- case IWN_SCAN_CURCHAN:
- error = iwn_scan(sc);
- if (error != 0) {
- IWN_UNLOCK(sc);
- ieee80211_cancel_scan(vap);
- IWN_LOCK(sc);
- return;
- }
- break;
- case IWN_SET_CHAN:
- error = iwn_config(sc);
- if (error != 0) {
- DPRINTF(sc, IWN_DEBUG_STATE,
- "%s: set chan failed, cancel scan\n",
- __func__);
- IWN_UNLOCK(sc);
- //XXX Handle failed scan correctly
- ieee80211_cancel_scan(vap);
- return;
- }
- break;
- case IWN_AUTH:
- case IWN_RUN:
- if (cmd == IWN_AUTH) {
- error = iwn_auth(sc);
- nstate = IEEE80211_S_AUTH;
- } else {
- error = iwn_run(sc);
- nstate = IEEE80211_S_RUN;
- }
- if (error == 0) {
- IWN_UNLOCK(sc);
- IEEE80211_LOCK(ic);
- IWN_VAP(vap)->iv_newstate(vap, nstate, arg);
- if (vap->iv_newstate_cb != NULL)
- vap->iv_newstate_cb(vap, nstate, arg);
- IEEE80211_UNLOCK(ic);
- IWN_LOCK(sc);
- } else {
- device_printf(sc->sc_dev,
- "%s: %s state change failed, error %d\n",
- __func__, ieee80211_state_name[nstate],
- error);
- }
- break;
- case IWN_REINIT:
- IWN_UNLOCK(sc);
- iwn_init(sc);
- IWN_LOCK(sc);
- ieee80211_notify_radio(ic, 1);
- break;
- case IWN_RADIO_ENABLE:
- KASSERT(sc->fw_fp != NULL,
- ("Fware Not Loaded, can't load from tq"));
- IWN_UNLOCK(sc);
- iwn_init(sc);
- IWN_LOCK(sc);
- break;
- case IWN_RADIO_DISABLE:
- ieee80211_notify_radio(ic, 0);
- iwn_stop_locked(sc);
- break;
- }
- IWN_UNLOCK(sc);
- }
+ iwn_init(sc);
+ ieee80211_notify_radio(ic, 1);
}
-/*
- * Queue a command for execution in the taskq thread.
- * This is needed as the net80211 callbacks do not allow
- * sleeping, since we need to sleep to confirm commands have
- * been processed by the firmware, we must defer execution to
- * a sleep enabled thread.
- */
-static int
-iwn_queue_cmd(struct iwn_softc *sc, int cmd, int arg, int clear)
+static void
+iwn_radioon(void *arg0, int pending)
{
- IWN_CMD_LOCK(sc);
- if (clear) {
- sc->sc_cmd[0] = cmd;
- sc->sc_cmd_arg[0] = arg;
- sc->sc_cmd_cur = 0;
- sc->sc_cmd_next = 1;
- } else {
- if (sc->sc_cmd[sc->sc_cmd_next] != 0) {
- IWN_CMD_UNLOCK(sc);
- DPRINTF(sc, IWN_DEBUG_ANY, "%s: command %d dropped\n",
- __func__, cmd);
- return EBUSY;
- }
- sc->sc_cmd[sc->sc_cmd_next] = cmd;
- sc->sc_cmd_arg[sc->sc_cmd_next] = arg;
- sc->sc_cmd_next = (sc->sc_cmd_next + 1) % IWN_CMD_MAXOPS;
- }
- taskqueue_enqueue(sc->sc_tq, &sc->sc_ops_task);
- IWN_CMD_UNLOCK(sc);
- return 0;
+ struct iwn_softc *sc = arg0;
+
+ iwn_init(sc);
+}
+
+static void
+iwn_radiooff(void *arg0, int pending)
+{
+ struct iwn_softc *sc = arg0;
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+
+ IWN_LOCK(sc);
+ ieee80211_notify_radio(ic, 0);
+ iwn_stop_locked(sc);
+ IWN_UNLOCK(sc);
}
static void
@@ -4542,24 +4440,6 @@ iwn_sysctlattach(struct iwn_softc *sc)
#ifdef IWN_DEBUG
static const char *
-iwn_ops_str(int cmd)
-{
- switch (cmd) {
- case IWN_SCAN_START: return "SCAN_START";
- case IWN_SCAN_CURCHAN: return "SCAN_CURCHAN";
- case IWN_SCAN_STOP: return "SCAN_STOP";
- case IWN_SET_CHAN: return "SET_CHAN";
- case IWN_AUTH: return "AUTH";
- case IWN_SCAN_NEXT: return "SCAN_NEXT";
- case IWN_RUN: return "RUN";
- case IWN_RADIO_ENABLE: return "RADIO_ENABLE";
- case IWN_RADIO_DISABLE: return "RADIO_DISABLE";
- case IWN_REINIT: return "REINIT";
- }
- return "UNKNOWN COMMAND";
-}
-
-static const char *
iwn_intr_str(uint8_t cmd)
{
switch (cmd) {
diff --git a/sys/dev/iwn/if_iwnvar.h b/sys/dev/iwn/if_iwnvar.h
index 4620342..d956525 100644
--- a/sys/dev/iwn/if_iwnvar.h
+++ b/sys/dev/iwn/if_iwnvar.h
@@ -180,33 +180,10 @@ struct iwn_softc {
void *sc_ih;
bus_size_t sc_sz;
- /* command queue related variables */
-#define IWN_SCAN_START (1<<0)
-#define IWN_SCAN_CURCHAN (1<<1)
-#define IWN_SCAN_STOP (1<<2)
-#define IWN_SET_CHAN (1<<3)
-#define IWN_AUTH (1<<4)
-#define IWN_SCAN_NEXT (1<<5)
-#define IWN_RUN (1<<6)
-#define IWN_RADIO_ENABLE (1<<7)
-#define IWN_RADIO_DISABLE (1<<8)
-#define IWN_REINIT (1<<9)
-#define IWN_CMD_MAXOPS 10
- /* command queuing request type */
-#define IWN_QUEUE_NORMAL 0
-#define IWN_QUEUE_CLEAR 1
- int sc_cmd[IWN_CMD_MAXOPS];
- int sc_cmd_arg[IWN_CMD_MAXOPS];
- int sc_cmd_cur; /* current queued scan task */
- int sc_cmd_next; /* last queued scan task */
- struct mtx sc_cmdlock;
-
- /* Task queues used to control the driver */
- struct taskqueue *sc_tq; /* Main command task queue */
-
/* Tasks used by the driver */
- struct task sc_ops_task; /* deferred ops */
- struct task sc_bmiss_task; /* beacon miss */
+ struct task sc_reinit_task;
+ struct task sc_radioon_task;
+ struct task sc_radiooff_task;
/* Thermal calibration */
int calib_cnt;
@@ -234,9 +211,3 @@ struct iwn_softc {
#define IWN_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED)
#define IWN_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
#define IWN_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx)
-#define IWN_CMD_LOCK_INIT(_sc) \
- mtx_init(&(_sc)->sc_cmdlock, device_get_nameunit((_sc)->sc_dev), \
- NULL, MTX_DEF);
-#define IWN_CMD_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_cmdlock)
-#define IWN_CMD_LOCK(_sc) mtx_lock(&(_sc)->sc_cmdlock)
-#define IWN_CMD_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_cmdlock)
diff --git a/sys/dev/usb/wlan/if_rum.c b/sys/dev/usb/wlan/if_rum.c
index 856ed38..0c3012e 100644
--- a/sys/dev/usb/wlan/if_rum.c
+++ b/sys/dev/usb/wlan/if_rum.c
@@ -26,22 +26,58 @@ __FBSDID("$FreeBSD$");
* http://www.ralinktech.com.tw/
*/
-#include "usbdevs.h"
-#include <dev/usb/usb.h>
-#include <dev/usb/usb_mfunc.h>
-#include <dev/usb/usb_error.h>
+#include <sys/param.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kdb.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+#endif
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_regdomain.h>
+#include <net80211/ieee80211_radiotap.h>
+#include <net80211/ieee80211_amrr.h>
#define USB_DEBUG_VAR rum_debug
+#include <dev/usb/usb.h>
+#include <dev/usb/usb_error.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_lookup.h>
-#include <dev/usb/usb_process.h>
#include <dev/usb/usb_debug.h>
#include <dev/usb/usb_request.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_util.h>
+#include "usbdevs.h"
-#include <dev/usb/wlan/usb_wlan.h>
#include <dev/usb/wlan/if_rumreg.h>
#include <dev/usb/wlan/if_rumvar.h>
#include <dev/usb/wlan/if_rumfw.h>
@@ -116,16 +152,6 @@ static device_detach_t rum_detach;
static usb2_callback_t rum_bulk_read_callback;
static usb2_callback_t rum_bulk_write_callback;
-static usb2_proc_callback_t rum_command_wrapper;
-static usb2_proc_callback_t rum_attach_post;
-static usb2_proc_callback_t rum_task;
-static usb2_proc_callback_t rum_scantask;
-static usb2_proc_callback_t rum_promisctask;
-static usb2_proc_callback_t rum_amrr_task;
-static usb2_proc_callback_t rum_init_task;
-static usb2_proc_callback_t rum_stop_task;
-static usb2_proc_callback_t rum_flush_task;
-
static usb2_error_t rum_do_request(struct rum_softc *sc,
struct usb2_device_request *req, void *data);
static struct ieee80211vap *rum_vap_create(struct ieee80211com *,
@@ -174,10 +200,13 @@ static void rum_update_slot(struct ifnet *);
static void rum_set_bssid(struct rum_softc *, const uint8_t *);
static void rum_set_macaddr(struct rum_softc *, const uint8_t *);
static void rum_update_promisc(struct ifnet *);
+static void rum_setpromisc(struct rum_softc *);
static const char *rum_get_rf(int);
static void rum_read_eeprom(struct rum_softc *);
static int rum_bbp_init(struct rum_softc *);
+static void rum_init_locked(struct rum_softc *);
static void rum_init(void *);
+static void rum_stop(struct rum_softc *);
static void rum_load_microcode(struct rum_softc *, const uint8_t *,
size_t);
static int rum_prepare_beacon(struct rum_softc *,
@@ -194,10 +223,8 @@ static int rum_get_rssi(struct rum_softc *, uint8_t);
static void rum_amrr_start(struct rum_softc *,
struct ieee80211_node *);
static void rum_amrr_timeout(void *);
+static void rum_amrr_task(void *, int);
static int rum_pause(struct rum_softc *, int);
-static void rum_queue_command(struct rum_softc *,
- usb2_proc_callback_t *, struct usb2_proc_msg *,
- struct usb2_proc_msg *);
static const struct {
uint32_t reg;
@@ -398,8 +425,11 @@ rum_attach(device_t self)
{
struct usb2_attach_arg *uaa = device_get_ivars(self);
struct rum_softc *sc = device_get_softc(self);
- uint8_t iface_index;
- int error;
+ struct ieee80211com *ic;
+ struct ifnet *ifp;
+ uint8_t iface_index, bands;
+ uint32_t tmp;
+ int error, ntries;
device_set_usb2_desc(self);
sc->sc_udev = uaa->device;
@@ -408,8 +438,6 @@ rum_attach(device_t self)
mtx_init(&sc->sc_mtx, device_get_nameunit(self),
MTX_NETWORK_LOCK, MTX_DEF);
- cv_init(&sc->sc_cmd_cv, "wtxdone");
-
iface_index = RT2573_IFACE_INDEX;
error = usb2_transfer_setup(uaa->device, &iface_index,
sc->sc_xfer, rum_config, RUM_N_TRANSFER, sc, &sc->sc_mtx);
@@ -418,37 +446,8 @@ rum_attach(device_t self)
"err=%s\n", usb2_errstr(error));
goto detach;
}
- error = usb2_proc_create(&sc->sc_tq, &sc->sc_mtx,
- device_get_nameunit(self), USB_PRI_MED);
- if (error) {
- device_printf(self, "could not setup config thread!\n");
- goto detach;
- }
- /* fork rest of the attach code */
RUM_LOCK(sc);
- rum_queue_command(sc, rum_attach_post,
- &sc->sc_synctask[0].hdr,
- &sc->sc_synctask[1].hdr);
- RUM_UNLOCK(sc);
- return (0);
-
-detach:
- rum_detach(self);
- return (ENXIO); /* failure */
-}
-
-static void
-rum_attach_post(struct usb2_proc_msg *pm)
-{
- struct rum_task *task = (struct rum_task *)pm;
- struct rum_softc *sc = task->sc;
- struct ifnet *ifp;
- struct ieee80211com *ic;
- unsigned int ntries;
- uint32_t tmp;
- uint8_t bands;
-
/* retrieve RT2573 rev. no */
for (ntries = 0; ntries < 100; ntries++) {
if ((tmp = rum_read(sc, RT2573_MAC_CSR0)) != 0)
@@ -458,7 +457,8 @@ rum_attach_post(struct usb2_proc_msg *pm)
}
if (ntries == 100) {
device_printf(sc->sc_dev, "timeout waiting for chip to settle\n");
- return;
+ RUM_UNLOCK(sc);
+ goto detach;
}
/* retrieve MAC address and various other things from EEPROM */
@@ -468,18 +468,12 @@ rum_attach_post(struct usb2_proc_msg *pm)
tmp, rum_get_rf(sc->rf_rev));
rum_load_microcode(sc, rt2573_ucode, sizeof(rt2573_ucode));
-
- /* XXX Async attach race */
- if (usb2_proc_is_gone(&sc->sc_tq))
- return;
-
RUM_UNLOCK(sc);
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(sc->sc_dev, "can not if_alloc()\n");
- RUM_LOCK(sc);
- return;
+ goto detach;
}
ic = ifp->if_l2com;
@@ -542,7 +536,11 @@ rum_attach_post(struct usb2_proc_msg *pm)
if (bootverbose)
ieee80211_announce(ic);
- RUM_LOCK(sc);
+ return (0);
+
+detach:
+ rum_detach(self);
+ return (ENXIO); /* failure */
}
static int
@@ -552,12 +550,8 @@ rum_detach(device_t self)
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic;
- /* wait for any post attach or other command to complete */
- usb2_proc_drain(&sc->sc_tq);
-
/* stop all USB transfers */
usb2_transfer_unsetup(sc->sc_xfer, RUM_N_TRANSFER);
- usb2_proc_free(&sc->sc_tq);
/* free TX list, if any */
RUM_LOCK(sc);
@@ -570,7 +564,6 @@ rum_detach(device_t self)
ieee80211_ifdetach(ic);
if_free(ifp);
}
- cv_destroy(&sc->sc_cmd_cv);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -584,7 +577,7 @@ rum_do_request(struct rum_softc *sc,
int ntries = 10;
while (ntries--) {
- err = usb2_do_request_proc(sc->sc_udev, &sc->sc_tq,
+ err = usb2_do_request_flags(sc->sc_udev, &sc->sc_mtx,
req, data, 0, NULL, 250 /* ms */);
if (err == 0)
break;
@@ -622,8 +615,8 @@ rum_vap_create(struct ieee80211com *ic,
rvp->newstate = vap->iv_newstate;
vap->iv_newstate = rum_newstate;
- rvp->sc = sc;
usb2_callout_init_mtx(&rvp->amrr_ch, &sc->sc_mtx, 0);
+ TASK_INIT(&rvp->amrr_task, 0, rum_amrr_task, rvp);
ieee80211_amrr_init(&rvp->amrr, vap,
IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
@@ -636,25 +629,13 @@ rum_vap_create(struct ieee80211com *ic,
}
static void
-rum_flush_task(struct usb2_proc_msg *pm)
-{
- /* Nothing to do */
-}
-
-static void
rum_vap_delete(struct ieee80211vap *vap)
{
struct rum_vap *rvp = RUM_VAP(vap);
- struct rum_softc *sc = rvp->sc;
-
- RUM_LOCK(sc);
- /* wait for any pending tasks to complete */
- rum_queue_command(sc, rum_flush_task,
- &sc->sc_synctask[0].hdr,
- &sc->sc_synctask[1].hdr);
- RUM_UNLOCK(sc);
+ struct ieee80211com *ic = vap->iv_ic;
usb2_callout_drain(&rvp->amrr_ch);
+ ieee80211_draintask(ic, &rvp->amrr_task);
ieee80211_amrr_cleanup(&rvp->amrr);
ieee80211_vap_detach(vap);
free(rvp, M_80211_VAP);
@@ -724,23 +705,27 @@ rum_unsetup_tx_list(struct rum_softc *sc)
}
}
-static void
-rum_task(struct usb2_proc_msg *pm)
+static int
+rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
- struct rum_task *task = (struct rum_task *)pm;
- struct rum_softc *sc = task->sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct rum_vap *rvp = RUM_VAP(vap);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct rum_softc *sc = ic->ic_ifp->if_softc;
const struct ieee80211_txparam *tp;
enum ieee80211_state ostate;
struct ieee80211_node *ni;
uint32_t tmp;
ostate = vap->iv_state;
+ DPRINTF("%s -> %s\n",
+ ieee80211_state_name[ostate],
+ ieee80211_state_name[nstate]);
- switch (sc->sc_state) {
+ IEEE80211_UNLOCK(ic);
+ RUM_LOCK(sc);
+ usb2_callout_stop(&rvp->amrr_ch);
+
+ switch (nstate) {
case IEEE80211_S_INIT:
if (ostate == IEEE80211_S_RUN) {
/* abort TSF synchronization */
@@ -776,45 +761,9 @@ rum_task(struct usb2_proc_msg *pm)
default:
break;
}
-
RUM_UNLOCK(sc);
IEEE80211_LOCK(ic);
- rvp->newstate(vap, sc->sc_state, sc->sc_arg);
- if (vap->iv_newstate_cb != NULL)
- vap->iv_newstate_cb(vap, sc->sc_state, sc->sc_arg);
- IEEE80211_UNLOCK(ic);
- RUM_LOCK(sc);
-}
-
-static int
-rum_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
-{
- struct rum_vap *rvp = RUM_VAP(vap);
- struct ieee80211com *ic = vap->iv_ic;
- struct rum_softc *sc = ic->ic_ifp->if_softc;
-
- DPRINTF("%s -> %s\n",
- ieee80211_state_name[vap->iv_state],
- ieee80211_state_name[nstate]);
-
- RUM_LOCK(sc);
- usb2_callout_stop(&rvp->amrr_ch);
-
- /* do it in a process context */
- sc->sc_state = nstate;
- sc->sc_arg = arg;
- RUM_UNLOCK(sc);
-
- if (nstate == IEEE80211_S_INIT) {
- rvp->newstate(vap, nstate, arg);
- return 0;
- } else {
- RUM_LOCK(sc);
- rum_queue_command(sc, rum_task, &sc->sc_task[0].hdr,
- &sc->sc_task[1].hdr);
- RUM_UNLOCK(sc);
- return EINPROGRESS;
- }
+ return (rvp->newstate(vap, nstate, arg));
}
static void
@@ -828,10 +777,6 @@ rum_bulk_write_callback(struct usb2_xfer *xfer)
struct mbuf *m;
unsigned int len;
- /* wakeup waiting command, if any */
- if (sc->sc_last_task != NULL)
- cv_signal(&sc->sc_cmd_cv);
-
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
DPRINTFN(11, "transfer complete, %d bytes\n", xfer->actlen);
@@ -847,10 +792,6 @@ rum_bulk_write_callback(struct usb2_xfer *xfer)
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
- /* wait for command to complete, if any */
- if (sc->sc_last_task != NULL)
- break;
-
data = STAILQ_FIRST(&sc->tx_q);
if (data) {
STAILQ_REMOVE_HEAD(&sc->tx_q, next);
@@ -1377,20 +1318,13 @@ rum_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
RUM_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- rum_queue_command(sc, rum_init_task,
- &sc->sc_synctask[0].hdr,
- &sc->sc_synctask[1].hdr);
+ rum_init_locked(sc);
startall = 1;
} else
- rum_queue_command(sc, rum_promisctask,
- &sc->sc_promisctask[0].hdr,
- &sc->sc_promisctask[1].hdr);
+ rum_setpromisc(sc);
} else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- rum_queue_command(sc, rum_stop_task,
- &sc->sc_synctask[0].hdr,
- &sc->sc_synctask[1].hdr);
- }
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ rum_stop(sc);
}
RUM_UNLOCK(sc);
if (startall)
@@ -1844,10 +1778,8 @@ rum_set_macaddr(struct rum_softc *sc, const uint8_t *addr)
}
static void
-rum_promisctask(struct usb2_proc_msg *pm)
+rum_setpromisc(struct rum_softc *sc)
{
- struct rum_task *task = (struct rum_task *)pm;
- struct rum_softc *sc = task->sc;
struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
@@ -1872,9 +1804,7 @@ rum_update_promisc(struct ifnet *ifp)
return;
RUM_LOCK(sc);
- rum_queue_command(sc, rum_promisctask,
- &sc->sc_promisctask[0].hdr,
- &sc->sc_promisctask[1].hdr);
+ rum_setpromisc(sc);
RUM_UNLOCK(sc);
}
@@ -2008,11 +1938,9 @@ rum_bbp_init(struct rum_softc *sc)
}
static void
-rum_init_task(struct usb2_proc_msg *pm)
+rum_init_locked(struct rum_softc *sc)
{
#define N(a) (sizeof (a) / sizeof ((a)[0]))
- struct rum_task *task = (struct rum_task *)pm;
- struct rum_softc *sc = task->sc;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
uint32_t tmp;
@@ -2021,7 +1949,7 @@ rum_init_task(struct usb2_proc_msg *pm)
RUM_LOCK_ASSERT(sc, MA_OWNED);
- rum_stop_task(pm);
+ rum_stop(sc);
/* initialize MAC registers to default values */
for (i = 0; i < N(rum_def_mac); i++)
@@ -2086,7 +2014,7 @@ rum_init_task(struct usb2_proc_msg *pm)
usb2_transfer_start(sc->sc_xfer[RUM_BULK_RD]);
return;
-fail: rum_stop_task(pm);
+fail: rum_stop(sc);
#undef N
}
@@ -2098,9 +2026,7 @@ rum_init(void *priv)
struct ieee80211com *ic = ifp->if_l2com;
RUM_LOCK(sc);
- rum_queue_command(sc, rum_init_task,
- &sc->sc_synctask[0].hdr,
- &sc->sc_synctask[1].hdr);
+ rum_init_locked(sc);
RUM_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
@@ -2108,10 +2034,8 @@ rum_init(void *priv)
}
static void
-rum_stop_task(struct usb2_proc_msg *pm)
+rum_stop(struct rum_softc *sc)
{
- struct rum_task *task = (struct rum_task *)pm;
- struct rum_softc *sc = task->sc;
struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
@@ -2271,24 +2195,24 @@ static void
rum_amrr_timeout(void *arg)
{
struct rum_vap *rvp = arg;
- struct rum_softc *sc = rvp->sc;
+ struct ieee80211vap *vap = &rvp->vap;
+ struct ieee80211com *ic = vap->iv_ic;
- rum_queue_command(sc, rum_amrr_task,
- &rvp->amrr_task[0].hdr, &rvp->amrr_task[1].hdr);
+ ieee80211_runtask(ic, &rvp->amrr_task);
}
static void
-rum_amrr_task(struct usb2_proc_msg *pm)
+rum_amrr_task(void *arg, int pending)
{
- struct rum_task *task = (struct rum_task *)pm;
- struct rum_softc *sc = task->sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
- struct rum_vap *rvp = RUM_VAP(vap);
+ struct rum_vap *rvp = arg;
+ struct ieee80211vap *vap = &rvp->vap;
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct rum_softc *sc = ifp->if_softc;
struct ieee80211_node *ni = vap->iv_bss;
int ok, fail;
+ RUM_LOCK(sc);
/* read and clear statistic registers (STA_CSR0 to STA_CSR10) */
rum_read_multi(sc, RT2573_STA_CSR0, sc->sta, sizeof(sc->sta));
@@ -2303,6 +2227,7 @@ rum_amrr_task(struct usb2_proc_msg *pm)
ifp->if_oerrors += fail; /* count TX retry-fail as Tx errors */
usb2_callout_reset(&rvp->amrr_ch, hz, rum_amrr_timeout, rvp);
+ RUM_UNLOCK(sc);
}
/* ARGUSED */
@@ -2327,13 +2252,15 @@ rum_newassoc(struct ieee80211_node *ni, int isnew)
static void
rum_scan_start(struct ieee80211com *ic)
{
- struct rum_softc *sc = ic->ic_ifp->if_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct rum_softc *sc = ifp->if_softc;
+ uint32_t tmp;
RUM_LOCK(sc);
- /* do it in a process context */
- sc->sc_scan_action = RUM_SCAN_START;
- rum_queue_command(sc, rum_scantask,
- &sc->sc_scantask[0].hdr, &sc->sc_scantask[1].hdr);
+ /* abort TSF synchronization */
+ tmp = rum_read(sc, RT2573_TXRX_CSR9);
+ rum_write(sc, RT2573_TXRX_CSR9, tmp & ~0x00ffffff);
+ rum_set_bssid(sc, ifp->if_broadcastaddr);
RUM_UNLOCK(sc);
}
@@ -2344,10 +2271,8 @@ rum_scan_end(struct ieee80211com *ic)
struct rum_softc *sc = ic->ic_ifp->if_softc;
RUM_LOCK(sc);
- /* do it in a process context */
- sc->sc_scan_action = RUM_SCAN_END;
- rum_queue_command(sc, rum_scantask,
- &sc->sc_scantask[0].hdr, &sc->sc_scantask[1].hdr);
+ rum_enable_tsf_sync(sc);
+ rum_set_bssid(sc, sc->sc_bssid);
RUM_UNLOCK(sc);
}
@@ -2358,43 +2283,10 @@ rum_set_channel(struct ieee80211com *ic)
struct rum_softc *sc = ic->ic_ifp->if_softc;
RUM_LOCK(sc);
- /* do it in a process context */
- sc->sc_scan_action = RUM_SET_CHANNEL;
- rum_queue_command(sc, rum_scantask,
- &sc->sc_scantask[0].hdr, &sc->sc_scantask[1].hdr);
+ rum_set_chan(sc, ic->ic_curchan);
RUM_UNLOCK(sc);
}
-static void
-rum_scantask(struct usb2_proc_msg *pm)
-{
- struct rum_task *task = (struct rum_task *)pm;
- struct rum_softc *sc = task->sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
- uint32_t tmp;
-
- RUM_LOCK_ASSERT(sc, MA_OWNED);
-
- switch (sc->sc_scan_action) {
- case RUM_SCAN_START:
- /* abort TSF synchronization */
- tmp = rum_read(sc, RT2573_TXRX_CSR9);
- rum_write(sc, RT2573_TXRX_CSR9, tmp & ~0x00ffffff);
- rum_set_bssid(sc, ifp->if_broadcastaddr);
- break;
-
- case RUM_SET_CHANNEL:
- rum_set_chan(sc, ic->ic_curchan);
- break;
-
- default: /* RUM_SCAN_END */
- rum_enable_tsf_sync(sc);
- rum_set_bssid(sc, sc->sc_bssid);
- break;
- }
-}
-
static int
rum_get_rssi(struct rum_softc *sc, uint8_t raw)
{
@@ -2445,72 +2337,11 @@ rum_get_rssi(struct rum_softc *sc, uint8_t raw)
static int
rum_pause(struct rum_softc *sc, int timeout)
{
- if (usb2_proc_is_gone(&sc->sc_tq))
- return (1);
usb2_pause_mtx(&sc->sc_mtx, timeout);
return (0);
}
-static void
-rum_command_wrapper(struct usb2_proc_msg *pm)
-{
- struct rum_task *task = (struct rum_task *)pm;
- struct rum_softc *sc = task->sc;
- struct ifnet *ifp;
-
- /* wait for pending transfer, if any */
- while (usb2_transfer_pending(sc->sc_xfer[RUM_BULK_WR]))
- cv_wait(&sc->sc_cmd_cv, &sc->sc_mtx);
-
- /* make sure any hardware buffers are emptied */
- rum_pause(sc, hz / 1000);
-
- /* execute task */
- task->func(pm);
-
- /* check if this is the last task executed */
- if (sc->sc_last_task == task) {
- sc->sc_last_task = NULL;
- ifp = sc->sc_ifp;
- /* re-start TX, if any */
- if ((ifp != NULL) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
- usb2_transfer_start(sc->sc_xfer[RUM_BULK_WR]);
- }
-}
-
-static void
-rum_queue_command(struct rum_softc *sc, usb2_proc_callback_t *fn,
- struct usb2_proc_msg *t0, struct usb2_proc_msg *t1)
-{
- struct rum_task *task;
-
- RUM_LOCK_ASSERT(sc, MA_OWNED);
-
- /*
- * NOTE: The task cannot get executed before we drop the
- * "sc_mtx" mutex. It is safe to update fields in the message
- * structure after that the message got queued.
- */
- task = (struct rum_task *)
- usb2_proc_msignal(&sc->sc_tq, t0, t1);
-
- /* Setup callback and softc pointers */
- task->hdr.pm_callback = rum_command_wrapper;
- task->func = fn;
- task->sc = sc;
-
- /* Make sure that any TX operation will stop */
- sc->sc_last_task = task;
-
- /*
- * Init, stop and flush must be synchronous!
- */
- if ((fn == rum_init_task) || (fn == rum_stop_task) ||
- (fn == rum_flush_task))
- usb2_proc_mwait(&sc->sc_tq, t0, t1);
-}
-
static device_method_t rum_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, rum_match),
diff --git a/sys/dev/usb/wlan/if_rumvar.h b/sys/dev/usb/wlan/if_rumvar.h
index d6b8137..2ba4007 100644
--- a/sys/dev/usb/wlan/if_rumvar.h
+++ b/sys/dev/usb/wlan/if_rumvar.h
@@ -54,12 +54,6 @@ struct rum_tx_radiotap_header {
struct rum_softc;
-struct rum_task {
- struct usb2_proc_msg hdr;
- usb2_proc_callback_t *func;
- struct rum_softc *sc;
-};
-
struct rum_tx_data {
STAILQ_ENTRY(rum_tx_data) next;
struct rum_softc *sc;
@@ -78,11 +72,10 @@ struct rum_node {
struct rum_vap {
struct ieee80211vap vap;
- struct rum_softc *sc;
struct ieee80211_beacon_offsets bo;
struct ieee80211_amrr amrr;
struct usb2_callout amrr_ch;
- struct rum_task amrr_task[2];
+ struct task amrr_task;
int (*newstate)(struct ieee80211vap *,
enum ieee80211_state, int);
@@ -99,32 +92,18 @@ struct rum_softc {
struct ifnet *sc_ifp;
device_t sc_dev;
struct usb2_device *sc_udev;
- struct usb2_process sc_tq;
struct usb2_xfer *sc_xfer[RUM_N_TRANSFER];
- struct rum_task *sc_last_task;
uint8_t rf_rev;
uint8_t rffreq;
- enum ieee80211_state sc_state;
- int sc_arg;
- struct rum_task sc_synctask[2];
- struct rum_task sc_task[2];
- struct rum_task sc_promisctask[2];
- struct rum_task sc_scantask[2];
- int sc_scan_action;
-#define RUM_SCAN_START 0
-#define RUM_SCAN_END 1
-#define RUM_SET_CHANNEL 2
-
struct rum_tx_data tx_data[RUM_TX_LIST_COUNT];
rum_txdhead tx_q;
rum_txdhead tx_free;
int tx_nfree;
struct rum_rx_desc sc_rx_desc;
- struct cv sc_cmd_cv;
struct mtx sc_mtx;
uint32_t sta[6];
diff --git a/sys/dev/usb/wlan/if_uath.c b/sys/dev/usb/wlan/if_uath.c
index eb1c31c..8e65770 100644
--- a/sys/dev/usb/wlan/if_uath.c
+++ b/sys/dev/usb/wlan/if_uath.c
@@ -1602,6 +1602,7 @@ uath_tx_start(struct uath_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
+ struct ieee80211vap *vap = ni->ni_vap;
struct uath_chunk *chunk;
struct uath_tx_desc *desc;
const struct ieee80211_frame *wh;
@@ -1677,9 +1678,9 @@ uath_tx_start(struct uath_softc *sc, struct mbuf *m0, struct ieee80211_node *ni,
m_freem(m0);
return (EIO);
}
- if (sc->sc_state == IEEE80211_S_AUTH ||
- sc->sc_state == IEEE80211_S_ASSOC ||
- sc->sc_state == IEEE80211_S_RUN)
+ if (vap->iv_state == IEEE80211_S_AUTH ||
+ vap->iv_state == IEEE80211_S_ASSOC ||
+ vap->iv_state == IEEE80211_S_RUN)
desc->connid = htobe32(UATH_ID_BSS);
else
desc->connid = htobe32(UATH_ID_INVALID);
@@ -2061,11 +2062,10 @@ uath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
"%s: %s -> %s\n", __func__, ieee80211_state_name[vap->iv_state],
ieee80211_state_name[nstate]);
+ IEEE80211_UNLOCK(ic);
UATH_LOCK(sc);
-
callout_stop(&sc->stat_ch);
callout_stop(&sc->watchdog_ch);
- sc->sc_state = nstate;
switch (nstate) {
case IEEE80211_S_INIT:
@@ -2139,14 +2139,8 @@ uath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
break;
}
UATH_UNLOCK(sc);
-
IEEE80211_LOCK(ic);
- uvp->newstate(vap, nstate, arg);
- if (vap->iv_newstate_cb != NULL)
- vap->iv_newstate_cb(vap, nstate, arg);
- IEEE80211_UNLOCK(ic);
-
- return (0);
+ return (uvp->newstate(vap, nstate, arg));
}
static int
diff --git a/sys/dev/usb/wlan/if_uathvar.h b/sys/dev/usb/wlan/if_uathvar.h
index 2717399..2757ad4 100644
--- a/sys/dev/usb/wlan/if_uathvar.h
+++ b/sys/dev/usb/wlan/if_uathvar.h
@@ -183,7 +183,6 @@ struct uath_softc {
struct uath_stat sc_stat;
int (*sc_newstate)(struct ieee80211com *,
enum ieee80211_state, int);
- enum ieee80211_state sc_state;
struct usb2_xfer *sc_xfer[UATH_N_XFERS];
struct uath_cmd sc_cmd[UATH_CMD_LIST_COUNT];
diff --git a/sys/dev/usb/wlan/if_ural.c b/sys/dev/usb/wlan/if_ural.c
index b865a41..523cc61 100644
--- a/sys/dev/usb/wlan/if_ural.c
+++ b/sys/dev/usb/wlan/if_ural.c
@@ -28,22 +28,59 @@ __FBSDID("$FreeBSD$");
* http://www.ralinktech.com/
*/
-#include "usbdevs.h"
-#include <dev/usb/usb.h>
-#include <dev/usb/usb_mfunc.h>
-#include <dev/usb/usb_error.h>
+#include <sys/param.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kdb.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+#endif
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_regdomain.h>
+#include <net80211/ieee80211_radiotap.h>
+#include <net80211/ieee80211_amrr.h>
#define USB_DEBUG_VAR ural_debug
+#include <dev/usb/usb.h>
+#include <dev/usb/usb_error.h>
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_lookup.h>
-#include <dev/usb/usb_process.h>
#include <dev/usb/usb_debug.h>
#include <dev/usb/usb_request.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_util.h>
+#include "usbdevs.h"
+
-#include <dev/usb/wlan/usb_wlan.h>
#include <dev/usb/wlan/if_uralreg.h>
#include <dev/usb/wlan/if_uralvar.h>
@@ -95,16 +132,6 @@ static const struct usb2_device_id ural_devs[] = {
static usb2_callback_t ural_bulk_read_callback;
static usb2_callback_t ural_bulk_write_callback;
-static usb2_proc_callback_t ural_command_wrapper;
-static usb2_proc_callback_t ural_attach_post;
-static usb2_proc_callback_t ural_task;
-static usb2_proc_callback_t ural_scantask;
-static usb2_proc_callback_t ural_promisctask;
-static usb2_proc_callback_t ural_amrr_task;
-static usb2_proc_callback_t ural_init_task;
-static usb2_proc_callback_t ural_stop_task;
-static usb2_proc_callback_t ural_flush_task;
-
static usb2_error_t ural_do_request(struct ural_softc *sc,
struct usb2_device_request *req, void *data);
static struct ieee80211vap *ural_vap_create(struct ieee80211com *,
@@ -156,21 +183,22 @@ static void ural_set_basicrates(struct ural_softc *,
static void ural_set_bssid(struct ural_softc *, const uint8_t *);
static void ural_set_macaddr(struct ural_softc *, uint8_t *);
static void ural_update_promisc(struct ifnet *);
+static void ural_setpromisc(struct ural_softc *);
static const char *ural_get_rf(int);
static void ural_read_eeprom(struct ural_softc *);
static int ural_bbp_init(struct ural_softc *);
static void ural_set_txantenna(struct ural_softc *, int);
static void ural_set_rxantenna(struct ural_softc *, int);
+static void ural_init_locked(struct ural_softc *);
static void ural_init(void *);
+static void ural_stop(struct ural_softc *);
static int ural_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static void ural_amrr_start(struct ural_softc *,
struct ieee80211_node *);
static void ural_amrr_timeout(void *);
+static void ural_amrr_task(void *, int);
static int ural_pause(struct ural_softc *sc, int timeout);
-static void ural_queue_command(struct ural_softc *,
- usb2_proc_callback_t *, struct usb2_proc_msg *,
- struct usb2_proc_msg *);
/*
* Default values for MAC registers; values taken from the reference driver.
@@ -400,8 +428,10 @@ ural_attach(device_t self)
{
struct usb2_attach_arg *uaa = device_get_ivars(self);
struct ural_softc *sc = device_get_softc(self);
+ struct ifnet *ifp;
+ struct ieee80211com *ic;
+ uint8_t iface_index, bands;
int error;
- uint8_t iface_index;
device_set_usb2_desc(self);
sc->sc_udev = uaa->device;
@@ -410,8 +440,6 @@ ural_attach(device_t self)
mtx_init(&sc->sc_mtx, device_get_nameunit(self),
MTX_NETWORK_LOCK, MTX_DEF);
- cv_init(&sc->sc_cmd_cv, "wtxdone");
-
iface_index = RAL_IFACE_INDEX;
error = usb2_transfer_setup(uaa->device,
&iface_index, sc->sc_xfer, ural_config,
@@ -421,55 +449,22 @@ ural_attach(device_t self)
"err=%s\n", usb2_errstr(error));
goto detach;
}
- error = usb2_proc_create(&sc->sc_tq, &sc->sc_mtx,
- device_get_nameunit(self), USB_PRI_MED);
- if (error) {
- device_printf(self, "could not setup config thread!\n");
- goto detach;
- }
- /* fork rest of the attach code */
RAL_LOCK(sc);
- ural_queue_command(sc, ural_attach_post,
- &sc->sc_synctask[0].hdr,
- &sc->sc_synctask[1].hdr);
- RAL_UNLOCK(sc);
- return (0);
-
-detach:
- ural_detach(self);
- return (ENXIO); /* failure */
-}
-
-static void
-ural_attach_post(struct usb2_proc_msg *pm)
-{
- struct ural_task *task = (struct ural_task *)pm;
- struct ural_softc *sc = task->sc;
- struct ifnet *ifp;
- struct ieee80211com *ic;
- uint8_t bands;
-
/* retrieve RT2570 rev. no */
sc->asic_rev = ural_read(sc, RAL_MAC_CSR0);
/* retrieve MAC address and various other things from EEPROM */
ural_read_eeprom(sc);
-
- /* XXX Async attach race */
- if (usb2_proc_is_gone(&sc->sc_tq))
- return;
-
RAL_UNLOCK(sc);
- device_printf(sc->sc_dev, "MAC/BBP RT2570 (rev 0x%02x), RF %s\n",
+ device_printf(self, "MAC/BBP RT2570 (rev 0x%02x), RF %s\n",
sc->asic_rev, ural_get_rf(sc->rf_rev));
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(sc->sc_dev, "can not if_alloc()\n");
- RAL_LOCK(sc);
- return;
+ goto detach;
}
ic = ifp->if_l2com;
@@ -532,7 +527,11 @@ ural_attach_post(struct usb2_proc_msg *pm)
if (bootverbose)
ieee80211_announce(ic);
- RAL_LOCK(sc);
+ return (0);
+
+detach:
+ ural_detach(self);
+ return (ENXIO); /* failure */
}
static int
@@ -542,12 +541,8 @@ ural_detach(device_t self)
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic;
- /* wait for any post attach or other command to complete */
- usb2_proc_drain(&sc->sc_tq);
-
/* stop all USB transfers */
usb2_transfer_unsetup(sc->sc_xfer, URAL_N_TRANSFER);
- usb2_proc_free(&sc->sc_tq);
/* free TX list, if any */
RAL_LOCK(sc);
@@ -560,7 +555,6 @@ ural_detach(device_t self)
ieee80211_ifdetach(ic);
if_free(ifp);
}
- cv_destroy(&sc->sc_cmd_cv);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -574,7 +568,7 @@ ural_do_request(struct ural_softc *sc,
int ntries = 10;
while (ntries--) {
- err = usb2_do_request_proc(sc->sc_udev, &sc->sc_tq,
+ err = usb2_do_request_flags(sc->sc_udev, &sc->sc_mtx,
req, data, 0, NULL, 250 /* ms */);
if (err == 0)
break;
@@ -612,8 +606,8 @@ ural_vap_create(struct ieee80211com *ic,
uvp->newstate = vap->iv_newstate;
vap->iv_newstate = ural_newstate;
- uvp->sc = sc;
usb2_callout_init_mtx(&uvp->amrr_ch, &sc->sc_mtx, 0);
+ TASK_INIT(&uvp->amrr_task, 0, ural_amrr_task, uvp);
ieee80211_amrr_init(&uvp->amrr, vap,
IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
@@ -626,25 +620,13 @@ ural_vap_create(struct ieee80211com *ic,
}
static void
-ural_flush_task(struct usb2_proc_msg *pm)
-{
- /* nothing to do */
-}
-
-static void
ural_vap_delete(struct ieee80211vap *vap)
{
struct ural_vap *uvp = URAL_VAP(vap);
- struct ural_softc *sc = uvp->sc;
-
- RAL_LOCK(sc);
- /* wait for any pending tasks to complete */
- ural_queue_command(sc, ural_flush_task,
- &sc->sc_synctask[0].hdr,
- &sc->sc_synctask[1].hdr);
- RAL_UNLOCK(sc);
+ struct ieee80211com *ic = vap->iv_ic;
usb2_callout_drain(&uvp->amrr_ch);
+ ieee80211_draintask(ic, &uvp->amrr_task);
ieee80211_amrr_cleanup(&uvp->amrr);
ieee80211_vap_detach(vap);
free(uvp, M_80211_VAP);
@@ -714,25 +696,27 @@ ural_unsetup_tx_list(struct ural_softc *sc)
}
}
-static void
-ural_task(struct usb2_proc_msg *pm)
+static int
+ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
- struct ural_task *task = (struct ural_task *)pm;
- struct ural_softc *sc = task->sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
struct ural_vap *uvp = URAL_VAP(vap);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ural_softc *sc = ic->ic_ifp->if_softc;
const struct ieee80211_txparam *tp;
- enum ieee80211_state ostate;
struct ieee80211_node *ni;
struct mbuf *m;
- ostate = vap->iv_state;
+ DPRINTF("%s -> %s\n",
+ ieee80211_state_name[vap->iv_state],
+ ieee80211_state_name[nstate]);
+
+ IEEE80211_UNLOCK(ic);
+ RAL_LOCK(sc);
+ usb2_callout_stop(&uvp->amrr_ch);
- switch (sc->sc_state) {
+ switch (nstate) {
case IEEE80211_S_INIT:
- if (ostate == IEEE80211_S_RUN) {
+ if (vap->iv_state == IEEE80211_S_RUN) {
/* abort TSF synchronization */
ural_write(sc, RAL_TXRX_CSR19, 0);
@@ -758,13 +742,17 @@ ural_task(struct usb2_proc_msg *pm)
if (m == NULL) {
device_printf(sc->sc_dev,
"could not allocate beacon\n");
- return;
+ RAL_UNLOCK(sc);
+ IEEE80211_LOCK(ic);
+ return (-1);
}
ieee80211_ref_node(ni);
if (ural_tx_bcn(sc, m, ni) != 0) {
device_printf(sc->sc_dev,
"could not send beacon\n");
- return;
+ RAL_UNLOCK(sc);
+ IEEE80211_LOCK(ic);
+ return (-1);
}
}
@@ -784,75 +772,9 @@ ural_task(struct usb2_proc_msg *pm)
default:
break;
}
-
RAL_UNLOCK(sc);
IEEE80211_LOCK(ic);
- uvp->newstate(vap, sc->sc_state, sc->sc_arg);
- if (vap->iv_newstate_cb != NULL)
- vap->iv_newstate_cb(vap, sc->sc_state, sc->sc_arg);
- IEEE80211_UNLOCK(ic);
- RAL_LOCK(sc);
-}
-
-static void
-ural_scantask(struct usb2_proc_msg *pm)
-{
- struct ural_task *task = (struct ural_task *)pm;
- struct ural_softc *sc = task->sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
-
- RAL_LOCK_ASSERT(sc, MA_OWNED);
-
- switch (sc->sc_scan_action) {
- case URAL_SCAN_START:
- /* abort TSF synchronization */
- DPRINTF("starting scan\n");
- ural_write(sc, RAL_TXRX_CSR19, 0);
- ural_set_bssid(sc, ifp->if_broadcastaddr);
- break;
-
- case URAL_SET_CHANNEL:
- ural_set_chan(sc, ic->ic_curchan);
- break;
-
- default: /* URAL_SCAN_END */
- DPRINTF("stopping scan\n");
- ural_enable_tsf_sync(sc);
- ural_set_bssid(sc, sc->sc_bssid);
- break;
- }
-}
-
-static int
-ural_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
-{
- struct ural_vap *uvp = URAL_VAP(vap);
- struct ieee80211com *ic = vap->iv_ic;
- struct ural_softc *sc = ic->ic_ifp->if_softc;
-
- DPRINTF("%s -> %s\n",
- ieee80211_state_name[vap->iv_state],
- ieee80211_state_name[nstate]);
-
- RAL_LOCK(sc);
- usb2_callout_stop(&uvp->amrr_ch);
-
- /* do it in a process context */
- sc->sc_state = nstate;
- sc->sc_arg = arg;
- RAL_UNLOCK(sc);
-
- if (nstate == IEEE80211_S_INIT) {
- uvp->newstate(vap, nstate, arg);
- return 0;
- } else {
- RAL_LOCK(sc);
- ural_queue_command(sc, ural_task, &sc->sc_task[0].hdr,
- &sc->sc_task[1].hdr);
- RAL_UNLOCK(sc);
- return EINPROGRESS;
- }
+ return (uvp->newstate(vap, nstate, arg));
}
@@ -867,10 +789,6 @@ ural_bulk_write_callback(struct usb2_xfer *xfer)
struct mbuf *m;
unsigned int len;
- /* wakeup waiting command, if any */
- if (sc->sc_last_task != NULL)
- cv_signal(&sc->sc_cmd_cv);
-
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
DPRINTFN(11, "transfer complete, %d bytes\n", xfer->actlen);
@@ -886,10 +804,6 @@ ural_bulk_write_callback(struct usb2_xfer *xfer)
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
- /* wait for command to complete, if any */
- if (sc->sc_last_task != NULL)
- break;
-
data = STAILQ_FIRST(&sc->tx_q);
if (data) {
STAILQ_REMOVE_HEAD(&sc->tx_q, next);
@@ -1458,20 +1372,13 @@ ural_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
RAL_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
- ural_queue_command(sc, ural_init_task,
- &sc->sc_synctask[0].hdr,
- &sc->sc_synctask[1].hdr);
+ ural_init_locked(sc);
startall = 1;
} else
- ural_queue_command(sc, ural_promisctask,
- &sc->sc_promisctask[0].hdr,
- &sc->sc_promisctask[1].hdr);
+ ural_setpromisc(sc);
} else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- ural_queue_command(sc, ural_stop_task,
- &sc->sc_synctask[0].hdr,
- &sc->sc_synctask[1].hdr);
- }
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ ural_stop(sc);
}
RAL_UNLOCK(sc);
if (startall)
@@ -1699,15 +1606,13 @@ ural_newassoc(struct ieee80211_node *ni, int isnew)
static void
ural_scan_start(struct ieee80211com *ic)
{
- struct ural_softc *sc = ic->ic_ifp->if_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct ural_softc *sc = ifp->if_softc;
RAL_LOCK(sc);
- /* do it in a process context */
- sc->sc_scan_action = URAL_SCAN_START;
- ural_queue_command(sc, ural_scantask,
- &sc->sc_scantask[0].hdr, &sc->sc_scantask[1].hdr);
+ ural_write(sc, RAL_TXRX_CSR19, 0);
+ ural_set_bssid(sc, ifp->if_broadcastaddr);
RAL_UNLOCK(sc);
-
}
static void
@@ -1716,10 +1621,8 @@ ural_scan_end(struct ieee80211com *ic)
struct ural_softc *sc = ic->ic_ifp->if_softc;
RAL_LOCK(sc);
- /* do it in a process context */
- sc->sc_scan_action = URAL_SCAN_END;
- ural_queue_command(sc, ural_scantask,
- &sc->sc_scantask[0].hdr, &sc->sc_scantask[1].hdr);
+ ural_enable_tsf_sync(sc);
+ ural_set_bssid(sc, sc->sc_bssid);
RAL_UNLOCK(sc);
}
@@ -1730,10 +1633,7 @@ ural_set_channel(struct ieee80211com *ic)
struct ural_softc *sc = ic->ic_ifp->if_softc;
RAL_LOCK(sc);
- /* do it in a process context */
- sc->sc_scan_action = URAL_SET_CHANNEL;
- ural_queue_command(sc, ural_scantask,
- &sc->sc_scantask[0].hdr, &sc->sc_scantask[1].hdr);
+ ural_set_chan(sc, ic->ic_curchan);
RAL_UNLOCK(sc);
}
@@ -1994,10 +1894,8 @@ ural_set_macaddr(struct ural_softc *sc, uint8_t *addr)
}
static void
-ural_promisctask(struct usb2_proc_msg *pm)
+ural_setpromisc(struct ural_softc *sc)
{
- struct ural_task *task = (struct ural_task *)pm;
- struct ural_softc *sc = task->sc;
struct ifnet *ifp = sc->sc_ifp;
uint32_t tmp;
@@ -2022,9 +1920,7 @@ ural_update_promisc(struct ifnet *ifp)
return;
RAL_LOCK(sc);
- ural_queue_command(sc, ural_promisctask,
- &sc->sc_promisctask[0].hdr,
- &sc->sc_promisctask[1].hdr);
+ ural_setpromisc(sc);
RAL_UNLOCK(sc);
}
@@ -2152,11 +2048,9 @@ ural_set_rxantenna(struct ural_softc *sc, int antenna)
}
static void
-ural_init_task(struct usb2_proc_msg *pm)
+ural_init_locked(struct ural_softc *sc)
{
#define N(a) (sizeof (a) / sizeof ((a)[0]))
- struct ural_task *task = (struct ural_task *)pm;
- struct ural_softc *sc = task->sc;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
uint16_t tmp;
@@ -2167,7 +2061,7 @@ ural_init_task(struct usb2_proc_msg *pm)
ural_set_testmode(sc);
ural_write(sc, 0x308, 0x00f0); /* XXX magic */
- ural_stop_task(pm);
+ ural_stop(sc);
/* initialize MAC registers to default values */
for (i = 0; i < N(ural_def_mac); i++)
@@ -2229,7 +2123,7 @@ ural_init_task(struct usb2_proc_msg *pm)
usb2_transfer_start(sc->sc_xfer[URAL_BULK_RD]);
return;
-fail: ural_stop_task(pm);
+fail: ural_stop(sc);
#undef N
}
@@ -2241,9 +2135,7 @@ ural_init(void *priv)
struct ieee80211com *ic = ifp->if_l2com;
RAL_LOCK(sc);
- ural_queue_command(sc, ural_init_task,
- &sc->sc_synctask[0].hdr,
- &sc->sc_synctask[1].hdr);
+ ural_init_locked(sc);
RAL_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
@@ -2251,10 +2143,8 @@ ural_init(void *priv)
}
static void
-ural_stop_task(struct usb2_proc_msg *pm)
+ural_stop(struct ural_softc *sc)
{
- struct ural_task *task = (struct ural_task *)pm;
- struct ural_softc *sc = task->sc;
struct ifnet *ifp = sc->sc_ifp;
RAL_LOCK_ASSERT(sc, MA_OWNED);
@@ -2350,24 +2240,24 @@ static void
ural_amrr_timeout(void *arg)
{
struct ural_vap *uvp = arg;
- struct ural_softc *sc = uvp->sc;
+ struct ieee80211vap *vap = &uvp->vap;
+ struct ieee80211com *ic = vap->iv_ic;
- ural_queue_command(sc, ural_amrr_task,
- &uvp->amrr_task[0].hdr, &uvp->amrr_task[1].hdr);
+ ieee80211_runtask(ic, &uvp->amrr_task);
}
static void
-ural_amrr_task(struct usb2_proc_msg *pm)
+ural_amrr_task(void *arg, int pending)
{
- struct ural_task *task = (struct ural_task *)pm;
- struct ural_softc *sc = task->sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
- struct ural_vap *uvp = URAL_VAP(vap);
+ struct ural_vap *uvp = arg;
+ struct ieee80211vap *vap = &uvp->vap;
+ struct ieee80211com *ic = vap->iv_ic;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct ural_softc *sc = ifp->if_softc;
struct ieee80211_node *ni = vap->iv_bss;
int ok, fail;
+ RAL_LOCK(sc);
/* read and clear statistic registers (STA_CSR0 to STA_CSR10) */
ural_read_multi(sc, RAL_STA_CSR0, sc->sta, sizeof(sc->sta));
@@ -2382,73 +2272,13 @@ ural_amrr_task(struct usb2_proc_msg *pm)
ifp->if_oerrors += fail; /* count TX retry-fail as Tx errors */
usb2_callout_reset(&uvp->amrr_ch, hz, ural_amrr_timeout, uvp);
+ RAL_UNLOCK(sc);
}
static int
ural_pause(struct ural_softc *sc, int timeout)
{
- if (usb2_proc_is_gone(&sc->sc_tq))
- return (1);
usb2_pause_mtx(&sc->sc_mtx, timeout);
return (0);
}
-
-static void
-ural_command_wrapper(struct usb2_proc_msg *pm)
-{
- struct ural_task *task = (struct ural_task *)pm;
- struct ural_softc *sc = task->sc;
- struct ifnet *ifp;
-
- /* wait for pending transfer, if any */
- while (usb2_transfer_pending(sc->sc_xfer[URAL_BULK_WR]))
- cv_wait(&sc->sc_cmd_cv, &sc->sc_mtx);
-
- /* make sure any hardware FIFOs are emptied */
- ural_pause(sc, hz / 1000);
-
- /* execute task */
- task->func(pm);
-
- /* check if this is the last task executed */
- if (sc->sc_last_task == task) {
- sc->sc_last_task = NULL;
- ifp = sc->sc_ifp;
- /* re-start TX, if any */
- if ((ifp != NULL) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
- usb2_transfer_start(sc->sc_xfer[URAL_BULK_WR]);
- }
-}
-
-static void
-ural_queue_command(struct ural_softc *sc, usb2_proc_callback_t *fn,
- struct usb2_proc_msg *t0, struct usb2_proc_msg *t1)
-{
- struct ural_task *task;
-
- RAL_LOCK_ASSERT(sc, MA_OWNED);
-
- /*
- * NOTE: The task cannot get executed before we drop the
- * "sc_mtx" mutex. It is safe to update fields in the message
- * structure after that the message got queued.
- */
- task = (struct ural_task *)
- usb2_proc_msignal(&sc->sc_tq, t0, t1);
-
- /* Setup callback and softc pointers */
- task->hdr.pm_callback = ural_command_wrapper;
- task->func = fn;
- task->sc = sc;
-
- /* Make sure that any TX operation will stop */
- sc->sc_last_task = task;
-
- /*
- * Init, stop and flush must be synchronous!
- */
- if ((fn == ural_init_task) || (fn == ural_stop_task) ||
- (fn == ural_stop_task))
- usb2_proc_mwait(&sc->sc_tq, t0, t1);
-}
diff --git a/sys/dev/usb/wlan/if_uralvar.h b/sys/dev/usb/wlan/if_uralvar.h
index 13a3df8..5149f6b 100644
--- a/sys/dev/usb/wlan/if_uralvar.h
+++ b/sys/dev/usb/wlan/if_uralvar.h
@@ -59,12 +59,6 @@ struct ural_tx_radiotap_header {
struct ural_softc;
-struct ural_task {
- struct usb2_proc_msg hdr;
- usb2_proc_callback_t *func;
- struct ural_softc *sc;
-};
-
struct ural_tx_data {
STAILQ_ENTRY(ural_tx_data) next;
struct ural_softc *sc;
@@ -83,11 +77,10 @@ struct ural_node {
struct ural_vap {
struct ieee80211vap vap;
- struct ural_softc *sc;
struct ieee80211_beacon_offsets bo;
struct ieee80211_amrr amrr;
struct usb2_callout amrr_ch;
- struct ural_task amrr_task[2];
+ struct task amrr_task;
int (*newstate)(struct ieee80211vap *,
enum ieee80211_state, int);
@@ -104,21 +97,11 @@ struct ural_softc {
struct ifnet *sc_ifp;
device_t sc_dev;
struct usb2_device *sc_udev;
- struct usb2_process sc_tq;
uint32_t asic_rev;
uint8_t rf_rev;
struct usb2_xfer *sc_xfer[URAL_N_TRANSFER];
- struct ural_task *sc_last_task;
-
- enum ieee80211_state sc_state;
- int sc_arg;
- int sc_scan_action; /* should be an enum */
- struct ural_task sc_synctask[2];
- struct ural_task sc_task[2];
- struct ural_task sc_promisctask[2];
- struct ural_task sc_scantask[2];
struct ural_tx_data tx_data[RAL_TX_LIST_COUNT];
ural_txdhead tx_q;
@@ -127,7 +110,6 @@ struct ural_softc {
struct ural_rx_desc sc_rx_desc;
struct mtx sc_mtx;
- struct cv sc_cmd_cv;
uint16_t sta[11];
uint32_t rf_regs[4];
diff --git a/sys/dev/usb/wlan/if_zyd.c b/sys/dev/usb/wlan/if_zyd.c
index 6858d55..c386ea8 100644
--- a/sys/dev/usb/wlan/if_zyd.c
+++ b/sys/dev/usb/wlan/if_zyd.c
@@ -26,20 +26,56 @@ __FBSDID("$FreeBSD$");
* ZyDAS ZD1211/ZD1211B USB WLAN driver.
*/
-#include "usbdevs.h"
+#include <sys/param.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/mbuf.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/kdb.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <net/bpf.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/ethernet.h>
+#include <net/if_dl.h>
+#include <net/if_media.h>
+#include <net/if_types.h>
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/in_var.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip.h>
+#endif
+
+#include <net80211/ieee80211_var.h>
+#include <net80211/ieee80211_regdomain.h>
+#include <net80211/ieee80211_radiotap.h>
+#include <net80211/ieee80211_amrr.h>
+
#include <dev/usb/usb.h>
-#include <dev/usb/usb_mfunc.h>
#include <dev/usb/usb_error.h>
-
#include <dev/usb/usb_core.h>
#include <dev/usb/usb_lookup.h>
-#include <dev/usb/usb_process.h>
#include <dev/usb/usb_debug.h>
#include <dev/usb/usb_request.h>
#include <dev/usb/usb_busdma.h>
#include <dev/usb/usb_util.h>
+#include "usbdevs.h"
-#include <dev/usb/wlan/usb_wlan.h>
#include <dev/usb/wlan/if_zydreg.h>
#include <dev/usb/wlan/if_zydfw.h>
@@ -74,7 +110,7 @@ enum {
#endif
#define zyd_do_request(sc,req,data) \
- usb2_do_request_proc((sc)->sc_udev, &(sc)->sc_tq, req, data, 0, NULL, 5000)
+ usb2_do_request_flags((sc)->sc_udev, &(sc)->sc_mtx, req, data, 0, NULL, 5000)
static device_probe_t zyd_match;
static device_attach_t zyd_attach;
@@ -85,14 +121,6 @@ static usb2_callback_t zyd_intr_write_callback;
static usb2_callback_t zyd_bulk_read_callback;
static usb2_callback_t zyd_bulk_write_callback;
-static usb2_proc_callback_t zyd_attach_post;
-static usb2_proc_callback_t zyd_task;
-static usb2_proc_callback_t zyd_scantask;
-static usb2_proc_callback_t zyd_multitask;
-static usb2_proc_callback_t zyd_init_task;
-static usb2_proc_callback_t zyd_stop_task;
-static usb2_proc_callback_t zyd_flush_task;
-
static struct ieee80211vap *zyd_vap_create(struct ieee80211com *,
const char name[IFNAMSIZ], int unit, int opmode,
int flags, const uint8_t bssid[IEEE80211_ADDR_LEN],
@@ -137,7 +165,9 @@ static void zyd_start(struct ifnet *);
static int zyd_raw_xmit(struct ieee80211_node *, struct mbuf *,
const struct ieee80211_bpf_params *);
static int zyd_ioctl(struct ifnet *, u_long, caddr_t);
+static void zyd_init_locked(struct zyd_softc *);
static void zyd_init(void *);
+static void zyd_stop(struct zyd_softc *);
static int zyd_loadfirmware(struct zyd_softc *);
static void zyd_newassoc(struct ieee80211_node *, int);
static void zyd_scan_start(struct ieee80211com *);
@@ -166,8 +196,6 @@ static int zyd_maxim_set_channel(struct zyd_rf *, uint8_t);
static int zyd_maxim2_init(struct zyd_rf *);
static int zyd_maxim2_switch_radio(struct zyd_rf *, int);
static int zyd_maxim2_set_channel(struct zyd_rf *, uint8_t);
-static void zyd_queue_command(struct zyd_softc *, usb2_proc_callback_t *,
- struct usb2_proc_msg *, struct usb2_proc_msg *);
static const struct zyd_phy_pair zyd_def_phy[] = ZYD_DEF_PHY;
static const struct zyd_phy_pair zyd_def_phyB[] = ZYD_DEF_PHYB;
@@ -307,8 +335,10 @@ zyd_attach(device_t dev)
{
struct usb2_attach_arg *uaa = device_get_ivars(dev);
struct zyd_softc *sc = device_get_softc(dev);
+ struct ifnet *ifp;
+ struct ieee80211com *ic;
+ uint8_t iface_index, bands;
int error;
- uint8_t iface_index;
if (uaa->info.bcdDevice < 0x4330) {
device_printf(dev, "device version mismatch: 0x%X "
@@ -324,7 +354,6 @@ zyd_attach(device_t dev)
mtx_init(&sc->sc_mtx, device_get_nameunit(sc->sc_dev),
MTX_NETWORK_LOCK, MTX_DEF);
- cv_init(&sc->sc_cmd_cv, "wtxdone");
STAILQ_INIT(&sc->sc_rqh);
iface_index = ZYD_IFACE_INDEX;
@@ -336,52 +365,19 @@ zyd_attach(device_t dev)
"err=%s\n", usb2_errstr(error));
goto detach;
}
- error = usb2_proc_create(&sc->sc_tq, &sc->sc_mtx,
- device_get_nameunit(dev), USB_PRI_MED);
- if (error) {
- device_printf(dev, "could not setup config thread!\n");
- goto detach;
- }
- /* fork rest of the attach code */
ZYD_LOCK(sc);
- zyd_queue_command(sc, zyd_attach_post,
- &sc->sc_synctask[0].hdr,
- &sc->sc_synctask[1].hdr);
- ZYD_UNLOCK(sc);
- return (0);
-
-detach:
- zyd_detach(dev);
- return (ENXIO); /* failure */
-}
-
-static void
-zyd_attach_post(struct usb2_proc_msg *pm)
-{
- struct zyd_task *task = (struct zyd_task *)pm;
- struct zyd_softc *sc = task->sc;
- struct ifnet *ifp;
- struct ieee80211com *ic;
- int error;
- uint8_t bands;
-
if ((error = zyd_get_macaddr(sc)) != 0) {
device_printf(sc->sc_dev, "could not read EEPROM\n");
- return;
+ ZYD_UNLOCK(sc);
+ goto detach;
}
-
- /* XXX Async attach race */
- if (usb2_proc_is_gone(&sc->sc_tq))
- return;
-
ZYD_UNLOCK(sc);
ifp = sc->sc_ifp = if_alloc(IFT_IEEE80211);
if (ifp == NULL) {
device_printf(sc->sc_dev, "can not if_alloc()\n");
- ZYD_LOCK(sc);
- return;
+ goto detach;
}
ifp->if_softc = sc;
if_initname(ifp, "zyd", device_get_unit(sc->sc_dev));
@@ -437,7 +433,11 @@ zyd_attach_post(struct usb2_proc_msg *pm)
if (bootverbose)
ieee80211_announce(ic);
- ZYD_LOCK(sc);
+ return (0);
+
+detach:
+ zyd_detach(dev);
+ return (ENXIO); /* failure */
}
static int
@@ -447,12 +447,8 @@ zyd_detach(device_t dev)
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic;
- /* wait for any post attach or other command to complete */
- usb2_proc_drain(&sc->sc_tq);
-
/* stop all USB transfers */
usb2_transfer_unsetup(sc->sc_xfer, ZYD_N_TRANSFER);
- usb2_proc_free(&sc->sc_tq);
/* free TX list, if any */
zyd_unsetup_tx_list(sc);
@@ -463,7 +459,6 @@ zyd_detach(device_t dev)
ieee80211_ifdetach(ic);
if_free(ifp);
}
- cv_destroy(&sc->sc_cmd_cv);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -475,7 +470,6 @@ zyd_vap_create(struct ieee80211com *ic,
const uint8_t bssid[IEEE80211_ADDR_LEN],
const uint8_t mac[IEEE80211_ADDR_LEN])
{
- struct zyd_softc *sc = ic->ic_ifp->if_softc;
struct zyd_vap *zvp;
struct ieee80211vap *vap;
@@ -494,7 +488,6 @@ zyd_vap_create(struct ieee80211com *ic,
zvp->newstate = vap->iv_newstate;
vap->iv_newstate = zyd_newstate;
- zvp->sc = sc;
ieee80211_amrr_init(&zvp->amrr, vap,
IEEE80211_AMRR_MIN_SUCCESS_THRESHOLD,
IEEE80211_AMRR_MAX_SUCCESS_THRESHOLD,
@@ -508,23 +501,9 @@ zyd_vap_create(struct ieee80211com *ic,
}
static void
-zyd_flush_task(struct usb2_proc_msg *_pm)
-{
- /* nothing to do */
-}
-
-static void
zyd_vap_delete(struct ieee80211vap *vap)
{
struct zyd_vap *zvp = ZYD_VAP(vap);
- struct zyd_softc *sc = zvp->sc;
-
- ZYD_LOCK(sc);
- /* wait for any pending tasks to complete */
- zyd_queue_command(sc, zyd_flush_task,
- &sc->sc_synctask[0].hdr,
- &sc->sc_synctask[1].hdr);
- ZYD_UNLOCK(sc);
ieee80211_amrr_cleanup(&zvp->amrr);
ieee80211_vap_detach(vap);
@@ -606,34 +585,38 @@ zyd_node_alloc(struct ieee80211vap *vap __unused,
return (zn != NULL) ? (&zn->ni) : (NULL);
}
-static void
-zyd_task(struct usb2_proc_msg *pm)
+static int
+zyd_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
{
- struct zyd_task *task = (struct zyd_task *)pm;
- struct zyd_softc *sc = task->sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
- struct ieee80211_node *ni = vap->iv_bss;
struct zyd_vap *zvp = ZYD_VAP(vap);
+ struct ieee80211com *ic = vap->iv_ic;
+ struct zyd_softc *sc = ic->ic_ifp->if_softc;
+ struct ieee80211_node *ni;
int error;
- switch (sc->sc_state) {
+ DPRINTF(sc, ZYD_DEBUG_STATE, "%s: %s -> %s\n", __func__,
+ ieee80211_state_name[vap->iv_state],
+ ieee80211_state_name[nstate]);
+
+ IEEE80211_UNLOCK(ic);
+ ZYD_LOCK(sc);
+ switch (nstate) {
case IEEE80211_S_AUTH:
zyd_set_chan(sc, ic->ic_curchan);
break;
case IEEE80211_S_RUN:
+ ni = vap->iv_bss;
if (vap->iv_opmode == IEEE80211_M_MONITOR)
break;
/* turn link LED on */
error = zyd_set_led(sc, ZYD_LED1, 1);
if (error != 0)
- goto fail;
-
+ break;
+
/* make data LED blink upon Tx */
zyd_write32_m(sc, sc->sc_fwbase + ZYD_FW_LINK_STATUS, 1);
-
+
IEEE80211_ADDR_COPY(sc->sc_bssid, ni->ni_bssid);
zyd_set_bssid(sc, sc->sc_bssid);
break;
@@ -643,40 +626,7 @@ zyd_task(struct usb2_proc_msg *pm)
fail:
ZYD_UNLOCK(sc);
IEEE80211_LOCK(ic);
- zvp->newstate(vap, sc->sc_state, sc->sc_arg);
- if (vap->iv_newstate_cb != NULL)
- vap->iv_newstate_cb(vap, sc->sc_state, sc->sc_arg);
- IEEE80211_UNLOCK(ic);
- ZYD_LOCK(sc);
-}
-
-static int
-zyd_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
-{
- struct zyd_vap *zvp = ZYD_VAP(vap);
- struct ieee80211com *ic = vap->iv_ic;
- struct zyd_softc *sc = ic->ic_ifp->if_softc;
-
- DPRINTF(sc, ZYD_DEBUG_STATE, "%s: %s -> %s\n", __func__,
- ieee80211_state_name[vap->iv_state],
- ieee80211_state_name[nstate]);
-
- ZYD_LOCK(sc);
- /* do it in a process context */
- sc->sc_state = nstate;
- sc->sc_arg = arg;
- ZYD_UNLOCK(sc);
-
- if (nstate == IEEE80211_S_INIT) {
- zvp->newstate(vap, nstate, arg);
- return (0);
- } else {
- ZYD_LOCK(sc);
- zyd_queue_command(sc, zyd_task, &sc->sc_task[0].hdr,
- &sc->sc_task[1].hdr);
- ZYD_UNLOCK(sc);
- return (EINPROGRESS);
- }
+ return (zvp->newstate(vap, nstate, arg));
}
/*
@@ -845,9 +795,6 @@ zyd_cmd(struct zyd_softc *sc, uint16_t code, const void *idata, int ilen,
if (ilen > sizeof(cmd.data))
return (EINVAL);
- if (usb2_proc_is_gone(&sc->sc_tq))
- return (ENXIO);
-
cmd.code = htole16(code);
bcopy(idata, cmd.data, ilen);
DPRINTF(sc, ZYD_DEBUG_CMD, "sending cmd %p = %*D\n",
@@ -2012,15 +1959,6 @@ fail:
}
static void
-zyd_multitask(struct usb2_proc_msg *pm)
-{
- struct zyd_task *task = (struct zyd_task *)pm;
- struct zyd_softc *sc = task->sc;
-
- zyd_set_multi(sc);
-}
-
-static void
zyd_set_multi(struct zyd_softc *sc)
{
int error;
@@ -2073,8 +2011,7 @@ zyd_update_mcast(struct ifnet *ifp)
return;
ZYD_LOCK(sc);
- zyd_queue_command(sc, zyd_multitask,
- &sc->sc_mcasttask[0].hdr, &sc->sc_mcasttask[1].hdr);
+ zyd_set_multi(sc);
ZYD_UNLOCK(sc);
}
@@ -2502,10 +2439,6 @@ zyd_bulk_write_callback(struct usb2_xfer *xfer)
struct zyd_tx_data *data;
struct mbuf *m;
- /* wakeup any waiting command, if any */
- if (sc->sc_last_task != NULL)
- cv_signal(&sc->sc_cmd_cv);
-
switch (USB_GET_STATE(xfer)) {
case USB_ST_TRANSFERRED:
DPRINTF(sc, ZYD_DEBUG_ANY, "transfer complete, %u bytes\n",
@@ -2522,10 +2455,6 @@ zyd_bulk_write_callback(struct usb2_xfer *xfer)
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
- /* wait for command to complete, if any */
- if (sc->sc_last_task != NULL)
- break;
-
data = STAILQ_FIRST(&sc->tx_q);
if (data) {
STAILQ_REMOVE_HEAD(&sc->tx_q, next);
@@ -2757,22 +2686,14 @@ zyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCSIFFLAGS:
ZYD_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- zyd_queue_command(sc, zyd_multitask,
- &sc->sc_mcasttask[0].hdr,
- &sc->sc_mcasttask[1].hdr);
- } else {
- zyd_queue_command(sc, zyd_init_task,
- &sc->sc_synctask[0].hdr,
- &sc->sc_synctask[1].hdr);
+ if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ zyd_init_locked(sc);
startall = 1;
- }
+ } else
+ zyd_set_multi(sc);
} else {
- if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- zyd_queue_command(sc, zyd_stop_task,
- &sc->sc_synctask[0].hdr,
- &sc->sc_synctask[1].hdr);
- }
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING)
+ zyd_stop(sc);
}
ZYD_UNLOCK(sc);
if (startall)
@@ -2792,10 +2713,8 @@ zyd_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
static void
-zyd_init_task(struct usb2_proc_msg *pm)
+zyd_init_locked(struct zyd_softc *sc)
{
- struct zyd_task *task = (struct zyd_task *)pm;
- struct zyd_softc *sc = task->sc;
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct usb2_config_descriptor *cd;
@@ -2850,7 +2769,7 @@ zyd_init_task(struct usb2_proc_msg *pm)
}
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
- zyd_stop_task(pm);
+ zyd_stop(sc);
DPRINTF(sc, ZYD_DEBUG_INIT, "setting MAC address to %6D\n",
IF_LLADDR(ifp), ":");
@@ -2898,7 +2817,7 @@ zyd_init_task(struct usb2_proc_msg *pm)
return;
-fail: zyd_stop_task(pm);
+fail: zyd_stop(sc);
return;
}
@@ -2910,9 +2829,7 @@ zyd_init(void *priv)
struct ieee80211com *ic = ifp->if_l2com;
ZYD_LOCK(sc);
- zyd_queue_command(sc, zyd_init_task,
- &sc->sc_synctask[0].hdr,
- &sc->sc_synctask[1].hdr);
+ zyd_init_locked(sc);
ZYD_UNLOCK(sc);
if (ifp->if_drv_flags & IFF_DRV_RUNNING)
@@ -2920,10 +2837,8 @@ zyd_init(void *priv)
}
static void
-zyd_stop_task(struct usb2_proc_msg *pm)
+zyd_stop(struct zyd_softc *sc)
{
- struct zyd_task *task = (struct zyd_task *)pm;
- struct zyd_softc *sc = task->sc;
struct ifnet *ifp = sc->sc_ifp;
int error;
@@ -3029,13 +2944,12 @@ zyd_newassoc(struct ieee80211_node *ni, int isnew)
static void
zyd_scan_start(struct ieee80211com *ic)
{
- struct zyd_softc *sc = ic->ic_ifp->if_softc;
+ struct ifnet *ifp = ic->ic_ifp;
+ struct zyd_softc *sc = ifp->if_softc;
ZYD_LOCK(sc);
- /* do it in a process context */
- sc->sc_scan_action = ZYD_SCAN_START;
- zyd_queue_command(sc, zyd_scantask,
- &sc->sc_scantask[0].hdr, &sc->sc_scantask[1].hdr);
+ /* want broadcast address while scanning */
+ zyd_set_bssid(sc, ifp->if_broadcastaddr);
ZYD_UNLOCK(sc);
}
@@ -3045,10 +2959,8 @@ zyd_scan_end(struct ieee80211com *ic)
struct zyd_softc *sc = ic->ic_ifp->if_softc;
ZYD_LOCK(sc);
- /* do it in a process context */
- sc->sc_scan_action = ZYD_SCAN_END;
- zyd_queue_command(sc, zyd_scantask,
- &sc->sc_scantask[0].hdr, &sc->sc_scantask[1].hdr);
+ /* restore previous bssid */
+ zyd_set_bssid(sc, sc->sc_bssid);
ZYD_UNLOCK(sc);
}
@@ -3058,105 +2970,16 @@ zyd_set_channel(struct ieee80211com *ic)
struct zyd_softc *sc = ic->ic_ifp->if_softc;
ZYD_LOCK(sc);
- /* do it in a process context */
- sc->sc_scan_action = ZYD_SET_CHANNEL;
- zyd_queue_command(sc, zyd_scantask,
- &sc->sc_scantask[0].hdr, &sc->sc_scantask[1].hdr);
+ zyd_set_chan(sc, ic->ic_curchan);
ZYD_UNLOCK(sc);
}
-static void
-zyd_scantask(struct usb2_proc_msg *pm)
-{
- struct zyd_task *task = (struct zyd_task *)pm;
- struct zyd_softc *sc = task->sc;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
-
- ZYD_LOCK_ASSERT(sc, MA_OWNED);
-
- switch (sc->sc_scan_action) {
- case ZYD_SCAN_START:
- /* want broadcast address while scanning */
- zyd_set_bssid(sc, ifp->if_broadcastaddr);
- break;
-
- case ZYD_SET_CHANNEL:
- zyd_set_chan(sc, ic->ic_curchan);
- break;
-
- default: /* ZYD_SCAN_END */
- /* restore previous bssid */
- zyd_set_bssid(sc, sc->sc_bssid);
- break;
- }
-}
-
-static void
-zyd_command_wrapper(struct usb2_proc_msg *pm)
-{
- struct zyd_task *task = (struct zyd_task *)pm;
- struct zyd_softc *sc = task->sc;
- struct ifnet *ifp;
-
- /* wait for pending transfer, if any */
- while (usb2_transfer_pending(sc->sc_xfer[ZYD_BULK_WR]))
- cv_wait(&sc->sc_cmd_cv, &sc->sc_mtx);
-
- /* make sure any hardware FIFOs are emptied */
- usb2_pause_mtx(&sc->sc_mtx, hz / 1000);
-
- /* execute task */
- task->func(pm);
-
- /* check if this is the last task executed */
- if (sc->sc_last_task == task) {
- sc->sc_last_task = NULL;
- ifp = sc->sc_ifp;
- /* re-start TX, if any */
- if ((ifp != NULL) && (ifp->if_drv_flags & IFF_DRV_RUNNING))
- usb2_transfer_start(sc->sc_xfer[ZYD_BULK_WR]);
- }
-}
-
-static void
-zyd_queue_command(struct zyd_softc *sc, usb2_proc_callback_t *fn,
- struct usb2_proc_msg *t0, struct usb2_proc_msg *t1)
-{
- struct zyd_task *task;
-
- ZYD_LOCK_ASSERT(sc, MA_OWNED);
-
- /*
- * NOTE: The task cannot get executed before we drop the
- * "sc_mtx" mutex. It is safe to update fields in the message
- * structure after that the message got queued.
- */
- task = (struct zyd_task *)
- usb2_proc_msignal(&sc->sc_tq, t0, t1);
-
- /* Setup callback and softc pointers */
- task->hdr.pm_callback = zyd_command_wrapper;
- task->func = fn;
- task->sc = sc;
-
- /* Make sure that any TX operation will stop */
- sc->sc_last_task = task;
-
- /*
- * Init and stop must be synchronous!
- */
- if ((fn == zyd_init_task) || (fn == zyd_stop_task) ||
- (fn == zyd_flush_task))
- usb2_proc_mwait(&sc->sc_tq, t0, t1);
-}
-
static device_method_t zyd_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, zyd_match),
DEVMETHOD(device_attach, zyd_attach),
DEVMETHOD(device_detach, zyd_detach),
-
+
{ 0, 0 }
};
diff --git a/sys/dev/usb/wlan/if_zydreg.h b/sys/dev/usb/wlan/if_zydreg.h
index fabed61..cd60593 100644
--- a/sys/dev/usb/wlan/if_zydreg.h
+++ b/sys/dev/usb/wlan/if_zydreg.h
@@ -1163,12 +1163,6 @@ struct zyd_mac_pair {
uint32_t val;
};
-struct zyd_task {
- struct usb2_proc_msg hdr;
- usb2_proc_callback_t *func;
- struct zyd_softc *sc;
-};
-
struct zyd_tx_data {
STAILQ_ENTRY(zyd_tx_data) next;
struct zyd_softc *sc;
@@ -1248,7 +1242,6 @@ struct zyd_vap {
struct ieee80211vap vap;
int (*newstate)(struct ieee80211vap *,
enum ieee80211_state, int);
- struct zyd_softc *sc;
struct ieee80211_amrr amrr;
};
#define ZYD_VAP(vap) ((struct zyd_vap *)(vap))
@@ -1265,27 +1258,14 @@ struct zyd_softc {
struct ifnet *sc_ifp;
device_t sc_dev;
struct usb2_device *sc_udev;
- struct usb2_process sc_tq;
struct usb2_xfer *sc_xfer[ZYD_N_TRANSFER];
- struct zyd_task *sc_last_task;
- enum ieee80211_state sc_state;
- int sc_arg;
int sc_flags;
#define ZYD_FLAG_FWLOADED (1 << 0)
#define ZYD_FLAG_INITONCE (1 << 1)
#define ZYD_FLAG_INITDONE (1 << 2)
- struct zyd_task sc_synctask[2];
- struct zyd_task sc_mcasttask[2];
- struct zyd_task sc_scantask[2];
- int sc_scan_action;
-#define ZYD_SCAN_START 0
-#define ZYD_SCAN_END 1
-#define ZYD_SET_CHANNEL 2
- struct zyd_task sc_task[2];
-
struct zyd_rf sc_rf;
STAILQ_HEAD(, zyd_rq) sc_rtx;
@@ -1317,7 +1297,6 @@ struct zyd_softc {
uint8_t sc_ofdm54_cal[14];
struct mtx sc_mtx;
- struct cv sc_cmd_cv;
struct zyd_tx_data tx_data[ZYD_TX_LIST_CNT];
zyd_txdhead tx_q;
zyd_txdhead tx_free;
diff --git a/sys/dev/usb/wlan/usb_wlan.h b/sys/dev/usb/wlan/usb_wlan.h
deleted file mode 100644
index aa0f1c4..0000000
--- a/sys/dev/usb/wlan/usb_wlan.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* $FreeBSD$ */
-/*-
- * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef _USB2_WLAN_H_
-#define _USB2_WLAN_H_
-
-#include <sys/param.h>
-#include <sys/sockio.h>
-#include <sys/mbuf.h>
-#include <sys/kernel.h>
-#include <sys/socket.h>
-
-#include <net/bpf.h>
-#include <net/if.h>
-#include <net/if_arp.h>
-#include <net/ethernet.h>
-#include <net/if_dl.h>
-#include <net/if_media.h>
-#include <net/if_types.h>
-#include <net/if_clone.h>
-
-#include <net80211/ieee80211_var.h>
-#include <net80211/ieee80211_radiotap.h>
-#include <net80211/ieee80211_amrr.h>
-#include <net80211/ieee80211_regdomain.h>
-
-#include <netinet/in.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
-#include <netinet/if_ether.h>
-
-#endif /* _USB2_WLAN_H_ */
diff --git a/sys/dev/wi/if_wi.c b/sys/dev/wi/if_wi.c
index a4a74e4..3dce847 100644
--- a/sys/dev/wi/if_wi.c
+++ b/sys/dev/wi/if_wi.c
@@ -78,7 +78,6 @@ __FBSDID("$FreeBSD$");
#include <sys/random.h>
#include <sys/syslog.h>
#include <sys/sysctl.h>
-#include <sys/taskqueue.h>
#include <machine/bus.h>
#include <machine/resource.h>
@@ -134,10 +133,6 @@ static void wi_rx_intr(struct wi_softc *);
static void wi_tx_intr(struct wi_softc *);
static void wi_tx_ex_intr(struct wi_softc *);
-static void wi_status_connected(void *, int);
-static void wi_status_disconnected(void *, int);
-static void wi_status_oor(void *, int);
-static void wi_status_assoc_failed(void *, int);
static void wi_info_intr(struct wi_softc *);
static int wi_write_txrate(struct wi_softc *, struct ieee80211vap *);
@@ -451,7 +446,6 @@ wi_attach(device_t dev)
}
sc->sc_portnum = WI_DEFAULT_PORT;
- TASK_INIT(&sc->sc_oor_task, 0, wi_status_oor, ic);
ieee80211_ifattach(ic, macaddr);
ic->ic_raw_xmit = wi_raw_xmit;
@@ -574,10 +568,6 @@ wi_vap_create(struct ieee80211com *ic,
break;
}
- TASK_INIT(&wvp->wv_connected_task, 0, wi_status_connected, vap);
- TASK_INIT(&wvp->wv_disconnected_task, 0, wi_status_disconnected, vap);
- TASK_INIT(&wvp->wv_assoc_failed_task, 0, wi_status_assoc_failed, vap);
-
/* complete setup */
ieee80211_vap_attach(vap, ieee80211_media_change, wi_media_status);
ic->ic_opmode = opmode;
@@ -902,7 +892,7 @@ wi_newstate_sta(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
* notification we get on association.
*/
vap->iv_state = nstate;
- return EINPROGRESS;
+ return (0);
}
return WI_VAP(vap)->wv_newstate(vap, nstate, arg);
}
@@ -1512,55 +1502,12 @@ wi_tx_intr(struct wi_softc *sc)
}
}
-static void
-wi_status_connected(void *arg, int pending)
-{
- struct ieee80211vap *vap = arg;
- struct ieee80211com *ic = vap->iv_ic;
-
- IEEE80211_LOCK(ic);
- vap->iv_bss->ni_associd = 1 | 0xc000; /* NB: anything will do */
- WI_VAP(vap)->wv_newstate(vap, IEEE80211_S_RUN, 0);
- if (vap->iv_newstate_cb != NULL)
- vap->iv_newstate_cb(vap, IEEE80211_S_RUN, 0);
- IEEE80211_UNLOCK(ic);
-}
-
-static void
-wi_status_disconnected(void *arg, int pending)
-{
- struct ieee80211vap *vap = arg;
-
- if (vap->iv_state == IEEE80211_S_RUN) {
- vap->iv_bss->ni_associd = 0;
- vap->iv_stats.is_rx_deauth++;
- ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
- }
-}
-
-static void
-wi_status_oor(void *arg, int pending)
-{
- struct ieee80211com *ic = arg;
-
- ieee80211_beacon_miss(ic);
-}
-
-static void
-wi_status_assoc_failed(void *arg, int pending)
-{
- struct ieee80211vap *vap = arg;
-
- ieee80211_new_state(vap, IEEE80211_S_SCAN, IEEE80211_SCAN_FAIL_TIMEOUT);
-}
-
static __noinline void
wi_info_intr(struct wi_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
- struct wi_vap *wvp = WI_VAP(vap);
int i, fid, len, off;
u_int16_t ltbuf[2];
u_int16_t stat;
@@ -1580,22 +1527,29 @@ wi_info_intr(struct wi_softc *sc)
break;
/* fall thru... */
case WI_INFO_LINK_STAT_AP_CHG:
- taskqueue_enqueue(taskqueue_swi, &wvp->wv_connected_task);
+ IEEE80211_LOCK(ic);
+ vap->iv_bss->ni_associd = 1 | 0xc000; /* NB: anything will do */
+ ieee80211_new_state(vap, IEEE80211_S_RUN, 0);
+ IEEE80211_UNLOCK(ic);
break;
case WI_INFO_LINK_STAT_AP_INR:
break;
case WI_INFO_LINK_STAT_DISCONNECTED:
/* we dropped off the net; e.g. due to deauth/disassoc */
- taskqueue_enqueue(taskqueue_swi, &wvp->wv_disconnected_task);
+ IEEE80211_LOCK(ic);
+ vap->iv_bss->ni_associd = 0;
+ vap->iv_stats.is_rx_deauth++;
+ ieee80211_new_state(vap, IEEE80211_S_SCAN, 0);
+ IEEE80211_UNLOCK(ic);
break;
case WI_INFO_LINK_STAT_AP_OOR:
/* XXX does this need to be per-vap? */
- taskqueue_enqueue(taskqueue_swi, &sc->sc_oor_task);
+ ieee80211_beacon_miss(ic);
break;
case WI_INFO_LINK_STAT_ASSOC_FAILED:
if (vap->iv_opmode == IEEE80211_M_STA)
- taskqueue_enqueue(taskqueue_swi,
- &wvp->wv_assoc_failed_task);
+ ieee80211_new_state(vap, IEEE80211_S_SCAN,
+ IEEE80211_SCAN_FAIL_TIMEOUT);
break;
}
break;
diff --git a/sys/dev/wi/if_wivar.h b/sys/dev/wi/if_wivar.h
index a66c74b..fdcedd8 100644
--- a/sys/dev/wi/if_wivar.h
+++ b/sys/dev/wi/if_wivar.h
@@ -59,9 +59,6 @@
struct wi_vap {
struct ieee80211vap wv_vap;
struct ieee80211_beacon_offsets wv_bo;
- struct task wv_connected_task;
- struct task wv_disconnected_task;
- struct task wv_assoc_failed_task;
void (*wv_recv_mgmt)(struct ieee80211_node *,
struct mbuf *, int, int, int, u_int32_t);
@@ -75,7 +72,6 @@ struct wi_softc {
device_t sc_dev;
struct mtx sc_mtx;
struct callout sc_watchdog;
- struct task sc_oor_task;
int sc_unit;
int wi_gone;
int sc_enabled;
diff --git a/sys/dev/wpi/if_wpi.c b/sys/dev/wpi/if_wpi.c
index 1e980aa..0ab8680 100644
--- a/sys/dev/wpi/if_wpi.c
+++ b/sys/dev/wpi/if_wpi.c
@@ -192,12 +192,9 @@ static void wpi_rx_intr(struct wpi_softc *, struct wpi_rx_desc *,
struct wpi_rx_data *);
static void wpi_tx_intr(struct wpi_softc *, struct wpi_rx_desc *);
static void wpi_cmd_intr(struct wpi_softc *, struct wpi_rx_desc *);
-static void wpi_bmiss(void *, int);
static void wpi_notif_intr(struct wpi_softc *);
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, int, int);
static void wpi_watchdog(void *);
static int wpi_tx_data(struct wpi_softc *, struct mbuf *,
struct ieee80211_node *, int);
@@ -230,6 +227,8 @@ static int wpi_config(struct wpi_softc *);
static void wpi_stop_master(struct wpi_softc *);
static int wpi_power_up(struct wpi_softc *);
static int wpi_reset(struct wpi_softc *);
+static void wpi_hwreset(void *, int);
+static void wpi_rfreset(void *, int);
static void wpi_hw_config(struct wpi_softc *);
static void wpi_init(void *);
static void wpi_init_locked(struct wpi_softc *, int);
@@ -514,21 +513,11 @@ wpi_attach(device_t dev)
}
}
- /*
- * Create the taskqueues used by the driver. Primarily
- * sc_tq handles most the task
- */
- sc->sc_tq = taskqueue_create("wpi_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));
-
/* Create the tasks that can be queued */
- TASK_INIT(&sc->sc_opstask, 0, wpi_ops, sc);
- TASK_INIT(&sc->sc_bmiss_task, 0, wpi_bmiss, sc);
+ TASK_INIT(&sc->sc_restarttask, 0, wpi_hwreset, sc);
+ TASK_INIT(&sc->sc_radiotask, 0, wpi_rfreset, sc);
WPI_LOCK_INIT(sc);
- WPI_CMD_LOCK_INIT(sc);
callout_init_mtx(&sc->calib_to, &sc->sc_mtx, 0);
callout_init_mtx(&sc->watchdog_to, &sc->sc_mtx, 0);
@@ -732,6 +721,9 @@ wpi_detach(device_t dev)
struct ieee80211com *ic = ifp->if_l2com;
int ac;
+ ieee80211_draintask(ic, &sc->sc_restarttask);
+ ieee80211_draintask(ic, &sc->sc_radiotask);
+
if (ifp != NULL) {
wpi_stop(sc);
callout_drain(&sc->watchdog_to);
@@ -769,10 +761,7 @@ wpi_detach(device_t dev)
if (ifp != NULL)
if_free(ifp);
- taskqueue_free(sc->sc_tq);
-
WPI_LOCK_DESTROY(sc);
- WPI_CMD_LOCK_DESTROY(sc);
return 0;
}
@@ -1280,21 +1269,32 @@ wpi_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ieee80211_state_name[vap->iv_state],
ieee80211_state_name[nstate], sc->flags));
+ IEEE80211_UNLOCK(ic);
+ WPI_LOCK(sc);
if (nstate == IEEE80211_S_AUTH) {
- /* Delay the auth transition until we can update the firmware */
- error = wpi_queue_cmd(sc, WPI_AUTH, arg, WPI_QUEUE_NORMAL);
- return (error != 0 ? error : EINPROGRESS);
+ /* The node must be registered in the firmware before auth */
+ error = wpi_auth(sc, vap);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not move to auth state, error %d\n",
+ __func__, error);
+ }
}
if (nstate == IEEE80211_S_RUN && vap->iv_state != IEEE80211_S_RUN) {
- /* set the association id first */
- error = wpi_queue_cmd(sc, WPI_RUN, arg, WPI_QUEUE_NORMAL);
- return (error != 0 ? error : EINPROGRESS);
+ error = wpi_run(sc, vap);
+ if (error != 0) {
+ device_printf(sc->sc_dev,
+ "%s: could not move to run state, error %d\n",
+ __func__, error);
+ }
}
if (nstate == IEEE80211_S_RUN) {
/* RUN -> RUN transition; just restart the timers */
wpi_calib_timeout(sc);
/* XXX split out rate control timer */
}
+ WPI_UNLOCK(sc);
+ IEEE80211_LOCK(ic);
return wvp->newstate(vap, nstate, arg);
}
@@ -1642,15 +1642,6 @@ wpi_cmd_intr(struct wpi_softc *sc, struct wpi_rx_desc *desc)
}
static void
-wpi_bmiss(void *arg, int npending)
-{
- struct wpi_softc *sc = arg;
- struct ieee80211com *ic = sc->sc_ifp->if_l2com;
-
- ieee80211_beacon_miss(ic);
-}
-
-static void
wpi_notif_intr(struct wpi_softc *sc)
{
struct ifnet *ifp = sc->sc_ifp;
@@ -1759,8 +1750,7 @@ wpi_notif_intr(struct wpi_softc *sc)
DPRINTF(("Beacon miss: %u >= %u\n",
le32toh(beacon->consecutive),
vap->iv_bmissthreshold));
- taskqueue_enqueue(taskqueue_swi,
- &sc->sc_bmiss_task);
+ ieee80211_beacon_miss(ic);
}
break;
}
@@ -1794,10 +1784,13 @@ wpi_intr(void *arg)
WPI_WRITE(sc, WPI_INTR, r);
if (r & (WPI_SW_ERROR | WPI_HW_ERROR)) {
+ struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
+
device_printf(sc->sc_dev, "fatal firmware error\n");
DPRINTFN(6,("(%s)\n", (r & WPI_SW_ERROR) ? "(Software Error)" :
"(Hardware Error)"));
- wpi_queue_cmd(sc, WPI_RESTART, 0, WPI_QUEUE_CLEAR);
+ ieee80211_runtask(ic, &sc->sc_restarttask);
sc->flags &= ~WPI_FLAG_BUSY;
WPI_UNLOCK(sc);
return;
@@ -3030,8 +3023,7 @@ wpi_rfkill_resume(struct wpi_softc *sc)
if (vap != NULL) {
if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
if (vap->iv_opmode != IEEE80211_M_MONITOR) {
- taskqueue_enqueue(taskqueue_swi,
- &sc->sc_bmiss_task);
+ ieee80211_beacon_miss(ic);
wpi_set_led(sc, WPI_LED_LINK, 0, 1);
} else
wpi_set_led(sc, WPI_LED_LINK, 5, 5);
@@ -3189,12 +3181,6 @@ wpi_stop_locked(struct wpi_softc *sc)
WPI_WRITE(sc, WPI_INTR_STATUS, 0xff);
WPI_WRITE(sc, WPI_INTR_STATUS, 0x00070000);
- /* Clear any commands left in the command buffer */
- memset(sc->sc_cmd, 0, sizeof(sc->sc_cmd));
- memset(sc->sc_cmd_arg, 0, sizeof(sc->sc_cmd_arg));
- sc->sc_cmd_cur = 0;
- sc->sc_cmd_next = 0;
-
wpi_mem_lock(sc);
wpi_mem_write(sc, WPI_MEM_MODE, 0);
wpi_mem_unlock(sc);
@@ -3538,7 +3524,9 @@ wpi_scan_start(struct ieee80211com *ic)
struct ifnet *ifp = ic->ic_ifp;
struct wpi_softc *sc = ifp->if_softc;
- wpi_queue_cmd(sc, WPI_SCAN_START, 0, WPI_QUEUE_NORMAL);
+ WPI_LOCK(sc);
+ wpi_set_led(sc, WPI_LED_LINK, 20, 2);
+ WPI_UNLOCK(sc);
}
/**
@@ -3549,10 +3537,7 @@ wpi_scan_start(struct ieee80211com *ic)
static void
wpi_scan_end(struct ieee80211com *ic)
{
- struct ifnet *ifp = ic->ic_ifp;
- struct wpi_softc *sc = ifp->if_softc;
-
- wpi_queue_cmd(sc, WPI_SCAN_STOP, 0, WPI_QUEUE_NORMAL);
+ /* XXX ignore */
}
/**
@@ -3564,13 +3549,18 @@ wpi_set_channel(struct ieee80211com *ic)
{
struct ifnet *ifp = ic->ic_ifp;
struct wpi_softc *sc = ifp->if_softc;
+ int error;
/*
* Only need to set the channel in Monitor mode. AP scanning and auth
* are already taken care of by their respective firmware commands.
*/
- if (ic->ic_opmode == IEEE80211_M_MONITOR)
- wpi_queue_cmd(sc, WPI_SET_CHAN, 0, WPI_QUEUE_NORMAL);
+ if (ic->ic_opmode == IEEE80211_M_MONITOR) {
+ error = wpi_config(sc);
+ if (error != 0)
+ device_printf(sc->sc_dev,
+ "error %d settting channel\n", error);
+ }
}
/**
@@ -3585,7 +3575,10 @@ wpi_scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
struct ifnet *ifp = vap->iv_ic->ic_ifp;
struct wpi_softc *sc = ifp->if_softc;
- wpi_queue_cmd(sc, WPI_SCAN_CURCHAN, 0, WPI_QUEUE_NORMAL);
+ WPI_LOCK(sc);
+ if (wpi_scan(sc))
+ ieee80211_cancel_scan(vap);
+ WPI_UNLOCK(sc);
}
/**
@@ -3600,152 +3593,24 @@ wpi_scan_mindwell(struct ieee80211_scan_state *ss)
/* NB: don't try to abort scan; wait for firmware to finish */
}
-/**
- * The ops function is called to perform some actual work.
- * because we can't sleep from any of the ic callbacks, we queue an
- * op task with wpi_queue_cmd and have the taskqueue process that task.
- * The task that gets cued is a op task, which ends up calling this function.
- */
static void
-wpi_ops(void *arg0, int pending)
+wpi_hwreset(void *arg, int pending)
{
- struct wpi_softc *sc = arg0;
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
- int cmd, arg, error;
- struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
-
-again:
- WPI_CMD_LOCK(sc);
- cmd = sc->sc_cmd[sc->sc_cmd_cur];
- arg = sc->sc_cmd_arg[sc->sc_cmd_cur];
+ struct wpi_softc *sc = arg;
- if (cmd == 0) {
- /* No more commands to process */
- WPI_CMD_UNLOCK(sc);
- return;
- }
- sc->sc_cmd[sc->sc_cmd_cur] = 0; /* free the slot */
- sc->sc_cmd_arg[sc->sc_cmd_cur] = 0; /* free the slot */
- sc->sc_cmd_cur = (sc->sc_cmd_cur + 1) % WPI_CMD_MAXOPS;
- WPI_CMD_UNLOCK(sc);
WPI_LOCK(sc);
-
- 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;
- }
-
- if (!(sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- WPI_UNLOCK(sc);
- return;
- }
-
- switch (cmd) {
- case WPI_SCAN_START:
- /* make the link LED blink while we're scanning */
- wpi_set_led(sc, WPI_LED_LINK, 20, 2);
- sc->flags |= WPI_FLAG_SCANNING;
- break;
-
- case WPI_SCAN_STOP:
- sc->flags &= ~WPI_FLAG_SCANNING;
- break;
-
- case WPI_SCAN_CURCHAN:
- if (wpi_scan(sc))
- ieee80211_cancel_scan(vap);
- break;
-
- case WPI_SET_CHAN:
- error = wpi_config(sc);
- if (error != 0)
- device_printf(sc->sc_dev,
- "error %d settting channel\n", error);
- break;
-
- case WPI_AUTH:
- /* The node must be registered in the firmware before auth */
- error = wpi_auth(sc, vap);
- WPI_UNLOCK(sc);
- if (error != 0) {
- device_printf(sc->sc_dev,
- "%s: could not move to auth state, error %d\n",
- __func__, error);
- return;
- }
- IEEE80211_LOCK(ic);
- WPI_VAP(vap)->newstate(vap, IEEE80211_S_AUTH, arg);
- if (vap->iv_newstate_cb != NULL)
- vap->iv_newstate_cb(vap, IEEE80211_S_AUTH, arg);
- IEEE80211_UNLOCK(ic);
- goto again;
-
- case WPI_RUN:
- error = wpi_run(sc, vap);
- WPI_UNLOCK(sc);
- if (error != 0) {
- device_printf(sc->sc_dev,
- "%s: could not move to run state, error %d\n",
- __func__, error);
- return;
- }
- IEEE80211_LOCK(ic);
- WPI_VAP(vap)->newstate(vap, IEEE80211_S_RUN, arg);
- if (vap->iv_newstate_cb != NULL)
- vap->iv_newstate_cb(vap, IEEE80211_S_RUN, arg);
- IEEE80211_UNLOCK(ic);
- goto again;
- }
+ wpi_init_locked(sc, 0);
WPI_UNLOCK(sc);
-
- /* Take another pass */
- goto again;
}
-/**
- * queue a command for later execution in a different thread.
- * This is needed as the net80211 callbacks do not allow
- * sleeping, since we need to sleep to confirm commands have
- * been processed by the firmware, we must defer execution to
- * a sleep enabled thread.
- */
-static int
-wpi_queue_cmd(struct wpi_softc *sc, int cmd, int arg, int flush)
+static void
+wpi_rfreset(void *arg, int pending)
{
- WPI_CMD_LOCK(sc);
-
- if (flush) {
- memset(sc->sc_cmd, 0, sizeof (sc->sc_cmd));
- memset(sc->sc_cmd_arg, 0, sizeof (sc->sc_cmd_arg));
- 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));
- return (EBUSY);
- }
-
- sc->sc_cmd[sc->sc_cmd_next] = cmd;
- sc->sc_cmd_arg[sc->sc_cmd_next] = arg;
- sc->sc_cmd_next = (sc->sc_cmd_next + 1) % WPI_CMD_MAXOPS;
-
- taskqueue_enqueue(sc->sc_tq, &sc->sc_opstask);
-
- WPI_CMD_UNLOCK(sc);
+ struct wpi_softc *sc = arg;
- return 0;
+ WPI_LOCK(sc);
+ wpi_rfkill_resume(sc);
+ WPI_UNLOCK(sc);
}
/*
@@ -3775,6 +3640,7 @@ wpi_watchdog(void *arg)
{
struct wpi_softc *sc = arg;
struct ifnet *ifp = sc->sc_ifp;
+ struct ieee80211com *ic = ifp->if_l2com;
uint32_t tmp;
DPRINTFN(WPI_DEBUG_WATCHDOG,("Watchdog: tick\n"));
@@ -3790,7 +3656,7 @@ wpi_watchdog(void *arg)
}
device_printf(sc->sc_dev, "Hardware Switch Enabled\n");
- wpi_queue_cmd(sc, WPI_RF_RESTART, 0, WPI_QUEUE_CLEAR);
+ ieee80211_runtask(ic, &sc->sc_radiotask);
return;
}
@@ -3798,17 +3664,15 @@ wpi_watchdog(void *arg)
if (--sc->sc_tx_timer == 0) {
device_printf(sc->sc_dev,"device timeout\n");
ifp->if_oerrors++;
- wpi_queue_cmd(sc, WPI_RESTART, 0, WPI_QUEUE_CLEAR);
+ ieee80211_runtask(ic, &sc->sc_restarttask);
}
}
if (sc->sc_scan_timer > 0) {
- struct ifnet *ifp = sc->sc_ifp;
- struct ieee80211com *ic = ifp->if_l2com;
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
if (--sc->sc_scan_timer == 0 && vap != NULL) {
device_printf(sc->sc_dev,"scan timeout\n");
ieee80211_cancel_scan(vap);
- wpi_queue_cmd(sc, WPI_RESTART, 0, WPI_QUEUE_CLEAR);
+ ieee80211_runtask(ic, &sc->sc_restarttask);
}
}
diff --git a/sys/dev/wpi/if_wpivar.h b/sys/dev/wpi/if_wpivar.h
index a447fd3..36da3b1 100644
--- a/sys/dev/wpi/if_wpivar.h
+++ b/sys/dev/wpi/if_wpivar.h
@@ -144,9 +144,8 @@ struct wpi_softc {
*/
uint32_t flags;
#define WPI_FLAG_HW_RADIO_OFF (1 << 0)
-#define WPI_FLAG_SCANNING (1 << 1)
-#define WPI_FLAG_BUSY (1 << 2)
-#define WPI_FLAG_AUTH (1 << 3)
+#define WPI_FLAG_BUSY (1 << 1)
+#define WPI_FLAG_AUTH (1 << 2)
/* shared area */
struct wpi_dma_info shared_dma;
@@ -193,36 +192,9 @@ struct wpi_softc {
/* firmware DMA transfer */
struct wpi_dma_info fw_dma;
- /* command queue related variables */
-#define WPI_SCAN_START (1<<0)
-#define WPI_SCAN_CURCHAN (1<<1)
-#define WPI_SCAN_STOP (1<<2)
-#define WPI_SET_CHAN (1<<3)
-#define WPI_AUTH (1<<4)
-#define WPI_RUN (1<<5)
-#define WPI_SCAN_NEXT (1<<6)
-#define WPI_RESTART (1<<7)
-#define WPI_RF_RESTART (1<<8)
-#define WPI_CMD_MAXOPS 10
- /* command queuing request type */
-#define WPI_QUEUE_NORMAL 0
-#define WPI_QUEUE_CLEAR 1
- int sc_cmd[WPI_CMD_MAXOPS];
- int sc_cmd_arg[WPI_CMD_MAXOPS];
- int sc_cmd_cur; /* current queued scan task */
- int sc_cmd_next; /* last queued scan task */
- struct mtx sc_cmdlock;
-
- /* Task queues used to control the driver */
- struct taskqueue *sc_tq; /* Main command task queue */
- struct taskqueue *sc_tq2; /* firmware reset task queue */
-
/* Tasks used by the driver */
- struct task sc_radioontask; /* enable rf transmitter task*/
- struct task sc_radioofftask;/* disable rf transmitter task*/
- struct task sc_opstask; /* operation handling task */
struct task sc_restarttask; /* reset firmware task */
- struct task sc_bmiss_task; /* beacon miss */
+ struct task sc_radiotask; /* reset rf task */
/* Eeprom info */
uint8_t cap;
@@ -239,10 +211,3 @@ struct wpi_softc {
#define WPI_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
#define WPI_LOCK_ASSERT(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
#define WPI_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx)
-
-#define WPI_CMD_LOCK_INIT(_sc) \
- mtx_init(&(_sc)->sc_cmdlock, device_get_nameunit((_sc)->sc_dev), \
- NULL, MTX_DEF)
-#define WPI_CMD_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_cmdlock)
-#define WPI_CMD_LOCK(_sc) mtx_lock(&(_sc)->sc_cmdlock)
-#define WPI_CMD_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_cmdlock)
diff --git a/sys/net80211/ieee80211.c b/sys/net80211/ieee80211.c
index eb40f61..2e75965 100644
--- a/sys/net80211/ieee80211.c
+++ b/sys/net80211/ieee80211.c
@@ -33,7 +33,7 @@ __FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
-#include <sys/systm.h>
+#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/socket.h>
@@ -251,6 +251,12 @@ ieee80211_ifattach(struct ieee80211com *ic,
IEEE80211_LOCK_INIT(ic, ifp->if_xname);
TAILQ_INIT(&ic->ic_vaps);
+
+ /* Create a taskqueue for all state changes */
+ ic->ic_tq = taskqueue_create("ic_taskq", M_WAITOK | M_ZERO,
+ taskqueue_thread_enqueue, &ic->ic_tq);
+ taskqueue_start_threads(&ic->ic_tq, 1, PI_NET, "%s taskq",
+ ifp->if_xname);
/*
* Fill in 802.11 available channel set, mark all
* available channels as active, and pick a default
@@ -325,6 +331,7 @@ ieee80211_ifdetach(struct ieee80211com *ic)
ieee80211_node_detach(ic);
ifmedia_removeall(&ic->ic_media);
+ taskqueue_free(ic->ic_tq);
IEEE80211_LOCK_DESTROY(ic);
if_detach(ifp);
}
@@ -554,7 +561,17 @@ ieee80211_vap_detach(struct ieee80211vap *vap)
* while we cleanup internal state but that is hard.
*/
ieee80211_stop_locked(vap);
+ IEEE80211_UNLOCK(ic);
+
+ /*
+ * Flush any deferred vap tasks.
+ * NB: must be before ether_ifdetach() and removal from ic_vaps list
+ */
+ ieee80211_draintask(ic, &vap->iv_nstate_task);
+ ieee80211_draintask(ic, &vap->iv_swbmiss_task);
+ IEEE80211_LOCK(ic);
+ KASSERT(vap->iv_state == IEEE80211_S_INIT , ("vap still running"));
TAILQ_REMOVE(&ic->ic_vaps, vap, iv_next);
ieee80211_syncflag_locked(ic, IEEE80211_F_WME);
#ifdef IEEE80211_SUPPORT_SUPERG
@@ -627,9 +644,9 @@ ieee80211_syncifflag_locked(struct ieee80211com *ic, int flag)
/* XXX should we return 1/0 and let caller do this? */
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
if (flag == IFF_PROMISC)
- ic->ic_update_promisc(ifp);
+ ieee80211_runtask(ic, &ic->ic_promisc_task);
else if (flag == IFF_ALLMULTI)
- ic->ic_update_mcast(ifp);
+ ieee80211_runtask(ic, &ic->ic_mcast_task);
}
}
}
diff --git a/sys/net80211/ieee80211_freebsd.h b/sys/net80211/ieee80211_freebsd.h
index 2e0075e..3ed9ece 100644
--- a/sys/net80211/ieee80211_freebsd.h
+++ b/sys/net80211/ieee80211_freebsd.h
@@ -32,6 +32,7 @@
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/rwlock.h>
+#include <sys/taskqueue.h>
/*
* Common state locking definitions.
diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c
index b28dffa..d40680a 100644
--- a/sys/net80211/ieee80211_ioctl.c
+++ b/sys/net80211/ieee80211_ioctl.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/systm.h>
-#include <sys/taskqueue.h>
#include <net/if.h>
#include <net/if_dl.h>
@@ -3196,8 +3195,7 @@ ieee80211_ioctl_updatemulti(struct ieee80211com *ic)
(void) if_addmulti(parent, ifma->ifma_addr, NULL);
}
parent->if_ioctl = ioctl;
-
- ic->ic_update_mcast(ic->ic_ifp);
+ ieee80211_runtask(ic, &ic->ic_mcast_task);
IEEE80211_UNLOCK(ic);
}
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index 2f39eb8..483af2d 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -629,16 +629,18 @@ ieee80211_sync_curchan(struct ieee80211com *ic)
ic->ic_curchan = c;
ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);
ic->ic_rt = ieee80211_get_ratetable(ic->ic_curchan);
+ IEEE80211_UNLOCK(ic);
ic->ic_set_channel(ic);
+ IEEE80211_LOCK(ic);
}
}
/*
- * Change the current channel. The request channel may be
+ * Setup the current channel. The request channel may be
* promoted if other vap's are operating with HT20/HT40.
*/
void
-ieee80211_setcurchan(struct ieee80211com *ic, struct ieee80211_channel *c)
+ieee80211_setupcurchan(struct ieee80211com *ic, struct ieee80211_channel *c)
{
if (ic->ic_htcaps & IEEE80211_HTC_HT) {
int flags = gethtadjustflags(ic);
@@ -654,7 +656,17 @@ ieee80211_setcurchan(struct ieee80211com *ic, struct ieee80211_channel *c)
ic->ic_bsschan = ic->ic_curchan = c;
ic->ic_curmode = ieee80211_chan2mode(ic->ic_curchan);
ic->ic_rt = ieee80211_get_ratetable(ic->ic_curchan);
- ic->ic_set_channel(ic);
+}
+
+/*
+ * Change the current channel. The channel change is guaranteed to have
+ * happened before the next state change.
+ */
+void
+ieee80211_setcurchan(struct ieee80211com *ic, struct ieee80211_channel *c)
+{
+ ieee80211_setupcurchan(ic, c);
+ ieee80211_runtask(ic, &ic->ic_chan_task);
}
/*
diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h
index 9e9d254..47f705f 100644
--- a/sys/net80211/ieee80211_node.h
+++ b/sys/net80211/ieee80211_node.h
@@ -286,6 +286,8 @@ void ieee80211_node_set_chan(struct ieee80211_node *,
void ieee80211_create_ibss(struct ieee80211vap*, struct ieee80211_channel *);
void ieee80211_reset_bss(struct ieee80211vap *);
void ieee80211_sync_curchan(struct ieee80211com *);
+void ieee80211_setupcurchan(struct ieee80211com *,
+ struct ieee80211_channel *);
void ieee80211_setcurchan(struct ieee80211com *, struct ieee80211_channel *);
int ieee80211_ibss_merge(struct ieee80211_node *);
struct ieee80211_scan_entry;
diff --git a/sys/net80211/ieee80211_proto.c b/sys/net80211/ieee80211_proto.c
index 572580f..98888d8 100644
--- a/sys/net80211/ieee80211_proto.c
+++ b/sys/net80211/ieee80211_proto.c
@@ -37,7 +37,6 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
-#include <sys/taskqueue.h>
#include <sys/socket.h>
#include <sys/sockio.h>
@@ -96,7 +95,13 @@ const char *ieee80211_wme_acnames[] = {
"WME_UPSD",
};
+static void beacon_miss(void *, int);
+static void beacon_swmiss(void *, int);
static void parent_updown(void *, int);
+static void update_mcast(void *, int);
+static void update_promisc(void *, int);
+static void update_channel(void *, int);
+static void ieee80211_newstate_cb(void *, int);
static int ieee80211_new_state_locked(struct ieee80211vap *,
enum ieee80211_state, int);
@@ -131,6 +136,10 @@ ieee80211_proto_attach(struct ieee80211com *ic)
ic->ic_protmode = IEEE80211_PROT_CTSONLY;
TASK_INIT(&ic->ic_parent_task, 0, parent_updown, ifp);
+ TASK_INIT(&ic->ic_mcast_task, 0, update_mcast, ic);
+ TASK_INIT(&ic->ic_promisc_task, 0, update_promisc, ic);
+ TASK_INIT(&ic->ic_chan_task, 0, update_channel, ic);
+ TASK_INIT(&ic->ic_bmiss_task, 0, beacon_miss, ic);
ic->ic_wme.wme_hipri_switch_hysteresis =
AGGRESSIVE_MODE_SWITCH_HYSTERESIS;
@@ -176,6 +185,8 @@ ieee80211_proto_vattach(struct ieee80211vap *vap)
vap->iv_bmiss_max = IEEE80211_BMISS_MAX;
callout_init(&vap->iv_swbmiss, CALLOUT_MPSAFE);
callout_init(&vap->iv_mgtsend, CALLOUT_MPSAFE);
+ TASK_INIT(&vap->iv_nstate_task, 0, ieee80211_newstate_cb, vap);
+ TASK_INIT(&vap->iv_swbmiss_task, 0, beacon_swmiss, vap);
/*
* Install default tx rate handling: no fixed rate, lowest
* supported rate for mgmt and multicast frames. Default
@@ -1072,6 +1083,32 @@ parent_updown(void *arg, int npending)
parent->if_ioctl(parent, SIOCSIFFLAGS, NULL);
}
+static void
+update_mcast(void *arg, int npending)
+{
+ struct ieee80211com *ic = arg;
+ struct ifnet *parent = ic->ic_ifp;
+
+ ic->ic_update_mcast(parent);
+}
+
+static void
+update_promisc(void *arg, int npending)
+{
+ struct ieee80211com *ic = arg;
+ struct ifnet *parent = ic->ic_ifp;
+
+ ic->ic_update_promisc(parent);
+}
+
+static void
+update_channel(void *arg, int npending)
+{
+ struct ieee80211com *ic = arg;
+
+ ic->ic_set_channel(ic);
+}
+
/*
* Block until the parent is in a known state. This is
* used after any operations that dispatch a task (e.g.
@@ -1080,7 +1117,13 @@ parent_updown(void *arg, int npending)
void
ieee80211_waitfor_parent(struct ieee80211com *ic)
{
- taskqueue_drain(taskqueue_thread, &ic->ic_parent_task);
+ taskqueue_block(ic->ic_tq);
+ ieee80211_draintask(ic, &ic->ic_parent_task);
+ ieee80211_draintask(ic, &ic->ic_mcast_task);
+ ieee80211_draintask(ic, &ic->ic_promisc_task);
+ ieee80211_draintask(ic, &ic->ic_chan_task);
+ ieee80211_draintask(ic, &ic->ic_bmiss_task);
+ taskqueue_unblock(ic->ic_tq);
}
/*
@@ -1121,7 +1164,7 @@ ieee80211_start_locked(struct ieee80211vap *vap)
IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
"%s: up parent %s\n", __func__, parent->if_xname);
parent->if_flags |= IFF_UP;
- taskqueue_enqueue(taskqueue_thread, &ic->ic_parent_task);
+ ieee80211_runtask(ic, &ic->ic_parent_task);
return;
}
}
@@ -1156,8 +1199,7 @@ ieee80211_start_locked(struct ieee80211vap *vap)
* preempted if the station is locked to a particular
* channel.
*/
- /* XXX needed? */
- ieee80211_new_state_locked(vap, IEEE80211_S_INIT, 0);
+ vap->iv_flags_ext |= IEEE80211_FEXT_REINIT;
if (vap->iv_opmode == IEEE80211_M_MONITOR ||
vap->iv_opmode == IEEE80211_M_WDS)
ieee80211_new_state_locked(vap,
@@ -1240,7 +1282,7 @@ ieee80211_stop_locked(struct ieee80211vap *vap)
IEEE80211_MSG_STATE | IEEE80211_MSG_DEBUG,
"down parent %s\n", parent->if_xname);
parent->if_flags &= ~IFF_UP;
- taskqueue_enqueue(taskqueue_thread, &ic->ic_parent_task);
+ ieee80211_runtask(ic, &ic->ic_parent_task);
}
}
}
@@ -1319,10 +1361,20 @@ ieee80211_resume_all(struct ieee80211com *ic)
void
ieee80211_beacon_miss(struct ieee80211com *ic)
{
+ IEEE80211_LOCK(ic);
+ if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
+ /* Process in a taskq, the handler may reenter the driver */
+ ieee80211_runtask(ic, &ic->ic_bmiss_task);
+ }
+ IEEE80211_UNLOCK(ic);
+}
+
+static void
+beacon_miss(void *arg, int npending)
+{
+ struct ieee80211com *ic = arg;
struct ieee80211vap *vap;
- if (ic->ic_flags & IEEE80211_F_SCAN)
- return;
/* XXX locking */
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
/*
@@ -1337,6 +1389,18 @@ ieee80211_beacon_miss(struct ieee80211com *ic)
}
}
+static void
+beacon_swmiss(void *arg, int npending)
+{
+ struct ieee80211vap *vap = arg;
+
+ if (vap->iv_state != IEEE80211_S_RUN)
+ return;
+
+ /* XXX Call multiple times if npending > zero? */
+ vap->iv_bmiss(vap);
+}
+
/*
* Software beacon miss handling. Check if any beacons
* were received in the last period. If not post a
@@ -1366,7 +1430,7 @@ ieee80211_swbmiss(void *arg)
vap->iv_swbmiss_count = 0;
} else if (vap->iv_swbmiss_count == 0) {
if (vap->iv_bmiss != NULL)
- vap->iv_bmiss(vap);
+ ieee80211_runtask(ic, &vap->iv_swbmiss_task);
if (vap->iv_bmiss_count == 0) /* don't re-arm timer */
return;
} else
@@ -1463,7 +1527,6 @@ ieee80211_cac_completeswitch(struct ieee80211vap *vap0)
* and mark them as waiting for a scan to complete. These vaps
* will be brought up when the scan completes and the scanning vap
* reaches RUN state by wakeupwaiting.
- * XXX if we do this in threads we can use sleep/wakeup.
*/
static void
markwaiting(struct ieee80211vap *vap0)
@@ -1473,10 +1536,16 @@ markwaiting(struct ieee80211vap *vap0)
IEEE80211_LOCK_ASSERT(ic);
+ /*
+ * A vap list entry can not disappear since we are running on the
+ * taskqueue and a vap destroy will queue and drain another state
+ * change task.
+ */
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
if (vap == vap0)
continue;
if (vap->iv_state != IEEE80211_S_INIT) {
+ /* NB: iv_newstate may drop the lock */
vap->iv_newstate(vap, IEEE80211_S_INIT, 0);
vap->iv_flags_ext |= IEEE80211_FEXT_SCANWAIT;
}
@@ -1487,6 +1556,7 @@ markwaiting(struct ieee80211vap *vap0)
* Wakeup all vap's waiting for a scan to complete. This is the
* companion to markwaiting (above) and is used to coordinate
* multiple vaps scanning.
+ * This is called from the state taskqueue.
*/
static void
wakeupwaiting(struct ieee80211vap *vap0)
@@ -1496,12 +1566,18 @@ wakeupwaiting(struct ieee80211vap *vap0)
IEEE80211_LOCK_ASSERT(ic);
+ /*
+ * A vap list entry can not disappear since we are running on the
+ * taskqueue and a vap destroy will queue and drain another state
+ * change task.
+ */
TAILQ_FOREACH(vap, &ic->ic_vaps, iv_next) {
if (vap == vap0)
continue;
if (vap->iv_flags_ext & IEEE80211_FEXT_SCANWAIT) {
vap->iv_flags_ext &= ~IEEE80211_FEXT_SCANWAIT;
/* NB: sta's cannot go INIT->RUN */
+ /* NB: iv_newstate may drop the lock */
vap->iv_newstate(vap,
vap->iv_opmode == IEEE80211_M_STA ?
IEEE80211_S_SCAN : IEEE80211_S_RUN, 0);
@@ -1513,15 +1589,63 @@ wakeupwaiting(struct ieee80211vap *vap0)
* Handle post state change work common to all operating modes.
*/
static void
-ieee80211_newstate_cb(struct ieee80211vap *vap,
- enum ieee80211_state nstate, int arg)
+ieee80211_newstate_cb(void *xvap, int npending)
{
+ struct ieee80211vap *vap = xvap;
struct ieee80211com *ic = vap->iv_ic;
+ enum ieee80211_state nstate, ostate;
+ int arg, rc;
- IEEE80211_LOCK_ASSERT(ic);
+ IEEE80211_LOCK(ic);
+ nstate = vap->iv_nstate;
+ arg = vap->iv_nstate_arg;
+ if (vap->iv_flags_ext & IEEE80211_FEXT_REINIT) {
+ /*
+ * We have been requested to drop back to the INIT before
+ * proceeding to the new state.
+ */
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,
+ "%s: %s -> %s arg %d\n", __func__,
+ ieee80211_state_name[vap->iv_state],
+ ieee80211_state_name[IEEE80211_S_INIT], arg);
+ vap->iv_newstate(vap, IEEE80211_S_INIT, arg);
+ vap->iv_flags_ext &= ~IEEE80211_FEXT_REINIT;
+ }
+
+ ostate = vap->iv_state;
+ if (nstate == IEEE80211_S_SCAN && ostate != IEEE80211_S_INIT) {
+ /*
+ * SCAN was forced; e.g. on beacon miss. Force other running
+ * vap's to INIT state and mark them as waiting for the scan to
+ * complete. This insures they don't interfere with our
+ * scanning. Since we are single threaded the vaps can not
+ * transition again while we are executing.
+ *
+ * XXX not always right, assumes ap follows sta
+ */
+ markwaiting(vap);
+ }
IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,
- "%s: %s arg %d\n", __func__, ieee80211_state_name[nstate], arg);
+ "%s: %s -> %s arg %d\n", __func__,
+ ieee80211_state_name[ostate], ieee80211_state_name[nstate], arg);
+
+ rc = vap->iv_newstate(vap, nstate, arg);
+ vap->iv_flags_ext &= ~IEEE80211_FEXT_STATEWAIT;
+ if (rc != 0) {
+ /* State transition failed */
+ KASSERT(rc != EINPROGRESS, ("iv_newstate was deferred"));
+ KASSERT(nstate != IEEE80211_S_INIT,
+ ("INIT state change failed"));
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,
+ "%s: %s returned error %d\n", __func__,
+ ieee80211_state_name[nstate], rc);
+ goto done;
+ }
+
+ /* No actual transition, skip post processing */
+ if (ostate == nstate)
+ goto done;
if (nstate == IEEE80211_S_RUN) {
/*
@@ -1549,7 +1673,8 @@ ieee80211_newstate_cb(struct ieee80211vap *vap,
/* XXX NB: cast for altq */
ieee80211_flush_ifq((struct ifqueue *)&ic->ic_ifp->if_snd, vap);
}
- vap->iv_newstate_cb = NULL;
+done:
+ IEEE80211_UNLOCK(ic);
}
/*
@@ -1586,10 +1711,32 @@ ieee80211_new_state_locked(struct ieee80211vap *vap,
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211vap *vp;
enum ieee80211_state ostate;
- int nrunning, nscanning, rc;
+ int nrunning, nscanning;
IEEE80211_LOCK_ASSERT(ic);
+ if (vap->iv_flags_ext & IEEE80211_FEXT_STATEWAIT) {
+ if (vap->iv_nstate == IEEE80211_S_INIT) {
+ /*
+ * XXX The vap is being stopped, do no allow any other
+ * state changes until this is completed.
+ */
+ return -1;
+ }
+#if 0
+ /* Warn if the previous state hasn't completed. */
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_STATE,
+ "%s: pending %s -> %s transition lost\n", __func__,
+ ieee80211_state_name[vap->iv_state],
+ ieee80211_state_name[vap->iv_nstate]);
+#else
+ /* XXX temporarily enable to identify issues */
+ if_printf(vap->iv_ifp, "%s: pending %s -> %s transition lost\n",
+ __func__, ieee80211_state_name[vap->iv_state],
+ ieee80211_state_name[vap->iv_nstate]);
+#endif
+ }
+
nrunning = nscanning = 0;
/* XXX can track this state instead of calculating */
TAILQ_FOREACH(vp, &ic->ic_vaps, iv_next) {
@@ -1625,8 +1772,7 @@ ieee80211_new_state_locked(struct ieee80211vap *vap,
__func__, ieee80211_state_name[ostate],
ieee80211_state_name[nstate]);
vap->iv_flags_ext |= IEEE80211_FEXT_SCANWAIT;
- rc = 0;
- goto done;
+ return 0;
}
if (nrunning) {
/*
@@ -1650,16 +1796,6 @@ ieee80211_new_state_locked(struct ieee80211vap *vap,
}
#endif
}
- } else {
- /*
- * SCAN was forced; e.g. on beacon miss. Force
- * other running vap's to INIT state and mark
- * them as waiting for the scan to complete. This
- * insures they don't interfere with our scanning.
- *
- * XXX not always right, assumes ap follows sta
- */
- markwaiting(vap);
}
break;
case IEEE80211_S_RUN:
@@ -1676,8 +1812,7 @@ ieee80211_new_state_locked(struct ieee80211vap *vap,
ieee80211_state_name[ostate],
ieee80211_state_name[nstate]);
vap->iv_flags_ext |= IEEE80211_FEXT_SCANWAIT;
- rc = 0;
- goto done;
+ return 0;
}
if (vap->iv_opmode == IEEE80211_M_HOSTAP &&
IEEE80211_IS_CHAN_DFS(ic->ic_bsschan) &&
@@ -1706,20 +1841,12 @@ ieee80211_new_state_locked(struct ieee80211vap *vap,
default:
break;
}
- /* XXX on transition RUN->CAC do we need to set nstate = iv_state? */
- if (ostate != nstate) {
- /*
- * Arrange for work to happen after state change completes.
- * If this happens asynchronously the caller must arrange
- * for the com lock to be held.
- */
- vap->iv_newstate_cb = ieee80211_newstate_cb;
- }
- rc = vap->iv_newstate(vap, nstate, arg);
- if (rc == 0 && vap->iv_newstate_cb != NULL)
- vap->iv_newstate_cb(vap, nstate, arg);
-done:
- return rc;
+ /* defer the state change to a thread */
+ vap->iv_nstate = nstate;
+ vap->iv_nstate_arg = arg;
+ vap->iv_flags_ext |= IEEE80211_FEXT_STATEWAIT;
+ ieee80211_runtask(ic, &vap->iv_nstate_task);
+ return EINPROGRESS;
}
int
diff --git a/sys/net80211/ieee80211_scan.c b/sys/net80211/ieee80211_scan.c
index 7ce2d31..c1f4a13 100644
--- a/sys/net80211/ieee80211_scan.c
+++ b/sys/net80211/ieee80211_scan.c
@@ -33,7 +33,9 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/proc.h>
#include <sys/kernel.h>
+#include <sys/condvar.h>
#include <sys/socket.h>
@@ -52,10 +54,12 @@ struct scan_state {
#define ISCAN_MINDWELL 0x0001 /* min dwell time reached */
#define ISCAN_DISCARD 0x0002 /* discard rx'd frames */
#define ISCAN_CANCEL 0x0004 /* cancel current scan */
-#define ISCAN_START 0x0008 /* 1st time through next_scan */
+#define ISCAN_ABORT 0x0008 /* end the scan immediately */
unsigned long ss_chanmindwell; /* min dwell on curchan */
unsigned long ss_scanend; /* time scan must stop */
u_int ss_duration; /* duration for next scan */
+ struct task ss_scan_task; /* scan execution */
+ struct cv ss_scan_cv; /* scan signal */
struct callout ss_scan_timer; /* scan timer */
};
#define SCAN_PRIVATE(ss) ((struct scan_state *) ss)
@@ -88,10 +92,10 @@ struct scan_state {
#define ROAM_RATE_QUARTER_DEFAULT 2*3 /* quarter-width 11a/g bss */
#define ROAM_MCS_11N_DEFAULT (1 | IEEE80211_RATE_MCS) /* 11n bss */
-static void scan_restart_pwrsav(void *);
static void scan_curchan(struct ieee80211_scan_state *, unsigned long);
static void scan_mindwell(struct ieee80211_scan_state *);
-static void scan_next(void *);
+static void scan_signal(void *);
+static void scan_task(void *, int);
MALLOC_DEFINE(M_80211_SCAN, "80211scan", "802.11 scan state");
@@ -107,7 +111,10 @@ ieee80211_scan_attach(struct ieee80211com *ic)
return;
}
callout_init_mtx(&ss->ss_scan_timer, IEEE80211_LOCK_OBJ(ic), 0);
+ cv_init(&ss->ss_scan_cv, "scan");
+ TASK_INIT(&ss->ss_scan_task, 0, scan_task, ss);
ic->ic_scan = &ss->base;
+ ss->base.ss_ic = ic;
ic->ic_scan_curchan = scan_curchan;
ic->ic_scan_mindwell = scan_mindwell;
@@ -119,12 +126,17 @@ ieee80211_scan_detach(struct ieee80211com *ic)
struct ieee80211_scan_state *ss = ic->ic_scan;
if (ss != NULL) {
- callout_drain(&SCAN_PRIVATE(ss)->ss_scan_timer);
+ IEEE80211_LOCK(ic);
+ SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_ABORT;
+ scan_signal(ss);
+ IEEE80211_UNLOCK(ic);
+ ieee80211_draintask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
+ KASSERT((ic->ic_flags & IEEE80211_F_SCAN) == 0,
+ ("scan still running"));
if (ss->ss_ops != NULL) {
ss->ss_ops->scan_detach(ss);
ss->ss_ops = NULL;
}
- ic->ic_flags &= ~IEEE80211_F_SCAN;
ic->ic_scan = NULL;
free(SCAN_PRIVATE(ss), M_80211_SCAN);
}
@@ -174,9 +186,8 @@ ieee80211_scan_vdetach(struct ieee80211vap *vap)
ss = ic->ic_scan;
if (ss != NULL && ss->ss_vap == vap) {
if (ic->ic_flags & IEEE80211_F_SCAN) {
- /* XXX callout_drain */
- callout_stop(&SCAN_PRIVATE(ss)->ss_scan_timer);
- ic->ic_flags &= ~IEEE80211_F_SCAN;
+ SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_ABORT;
+ scan_signal(ss);
}
if (ss->ss_ops != NULL) {
ss->ss_ops->scan_detach(ss);
@@ -293,15 +304,6 @@ scan_update_locked(struct ieee80211vap *vap,
}
}
-static void
-change_channel(struct ieee80211com *ic,
- struct ieee80211_channel *chan)
-{
- ic->ic_curchan = chan;
- ic->ic_rt = ieee80211_get_ratetable(chan);
- ic->ic_set_channel(ic);
-}
-
static char
channel_type(const struct ieee80211_channel *c)
{
@@ -325,7 +327,7 @@ channel_type(const struct ieee80211_channel *c)
void
ieee80211_scan_dump_channels(const struct ieee80211_scan_state *ss)
{
- struct ieee80211com *ic = ss->ss_vap->iv_ic;
+ struct ieee80211com *ic = ss->ss_ic;
const char *sep;
int i;
@@ -352,76 +354,6 @@ scan_dump(struct ieee80211_scan_state *ss)
}
#endif /* IEEE80211_DEBUG */
-/*
- * Enable station power save mode and start/restart the scanning thread.
- */
-static void
-scan_restart_pwrsav(void *arg)
-{
- struct scan_state *ss = (struct scan_state *) arg;
- struct ieee80211vap *vap = ss->base.ss_vap;
- struct ieee80211com *ic = vap->iv_ic;
- int ticksdelay;
-
- ieee80211_sta_pwrsave(vap, 1);
- /*
- * Use an initial 1ms delay so the null
- * data frame has a chance to go out.
- * XXX 1ms is a lot, better to trigger scan
- * on tx complete.
- */
- ticksdelay = msecs_to_ticks(1);
- if (ticksdelay < 1)
- ticksdelay = 1;
- ic->ic_scan_start(ic); /* notify driver */
- ss->ss_scanend = ticks + ticksdelay + ss->ss_duration;
- ss->ss_iflags |= ISCAN_START;
- callout_reset(&ss->ss_scan_timer, ticksdelay, scan_next, ss);
-}
-
-/*
- * Start/restart scanning. If we're operating in station mode
- * and associated notify the ap we're going into power save mode
- * and schedule a callback to initiate the work (where there's a
- * better context for doing the work). Otherwise, start the scan
- * directly.
- */
-static int
-scan_restart(struct scan_state *ss, u_int duration)
-{
- struct ieee80211vap *vap = ss->base.ss_vap;
- struct ieee80211com *ic = vap->iv_ic;
- int defer = 0;
-
- if (ss->base.ss_next == ss->base.ss_last) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
- "%s: no channels to scan\n", __func__);
- return 0;
- }
- if (vap->iv_opmode == IEEE80211_M_STA &&
- vap->iv_state == IEEE80211_S_RUN) {
- if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) {
- /*
- * Initiate power save before going off-channel.
- * Note that we cannot do this directly because
- * of locking issues; instead we defer it to a
- * tasklet.
- */
- ss->ss_duration = duration;
- defer = 1;
- }
- }
-
- if (!defer) {
- ic->ic_scan_start(ic); /* notify driver */
- ss->ss_scanend = ticks + duration;
- ss->ss_iflags |= ISCAN_START;
- callout_reset(&ss->ss_scan_timer, 0, scan_next, ss);
- } else
- scan_restart_pwrsav(ss);
- return 1;
-}
-
static void
copy_ssid(struct ieee80211vap *vap, struct ieee80211_scan_state *ss,
int nssid, const struct ieee80211_scan_ssid ssids[])
@@ -485,16 +417,18 @@ start_scan_locked(const struct ieee80211_scanner *scan,
/* NB: flush frames rx'd before 1st channel change */
SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD;
+ SCAN_PRIVATE(ss)->ss_duration = duration;
ss->ss_next = 0;
ss->ss_mindwell = mindwell;
ss->ss_maxdwell = maxdwell;
+ /* NB: scan_start must be before the scan runtask */
ss->ss_ops->scan_start(ss, vap);
#ifdef IEEE80211_DEBUG
if (ieee80211_msg_scan(vap))
scan_dump(ss);
#endif /* IEEE80211_DEBUG */
- if (scan_restart(SCAN_PRIVATE(ss), duration))
- ic->ic_flags |= IEEE80211_F_SCAN;
+ ic->ic_flags |= IEEE80211_F_SCAN;
+ ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
}
} else {
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
@@ -716,11 +650,11 @@ ieee80211_bg_scan(struct ieee80211vap *vap, int flags)
}
/* NB: flush frames rx'd before 1st channel change */
SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD;
+ SCAN_PRIVATE(ss)->ss_duration = duration;
ss->ss_maxdwell = duration;
- if (scan_restart(SCAN_PRIVATE(ss), duration)) {
- ic->ic_flags |= IEEE80211_F_SCAN;
- ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN;
- }
+ ic->ic_flags |= IEEE80211_F_SCAN;
+ ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN;
+ ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
} else {
/* XXX msg+stat */
}
@@ -756,9 +690,8 @@ ieee80211_cancel_scan(struct ieee80211vap *vap)
/* clear bg scan NOPICK and mark cancel request */
ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL;
- /* force it to fire asap */
- callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer,
- 0, scan_next, ss);
+ /* wake up the scan task */
+ scan_signal(ss);
}
IEEE80211_UNLOCK(ic);
}
@@ -783,9 +716,8 @@ ieee80211_cancel_anyscan(struct ieee80211vap *vap)
/* clear bg scan NOPICK and mark cancel request */
ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL;
- /* force it to fire asap */
- callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer,
- 0, scan_next, ss);
+ /* wake up the scan task */
+ scan_signal(ss);
}
IEEE80211_UNLOCK(ic);
}
@@ -800,7 +732,10 @@ ieee80211_scan_next(struct ieee80211vap *vap)
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_scan_state *ss = ic->ic_scan;
- callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer, 0, scan_next, ss);
+ /* wake up the scan task */
+ IEEE80211_LOCK(ic);
+ scan_signal(ss);
+ IEEE80211_UNLOCK(ic);
}
/*
@@ -816,7 +751,7 @@ ieee80211_scan_done(struct ieee80211vap *vap)
IEEE80211_LOCK(ic);
ss = ic->ic_scan;
ss->ss_next = ss->ss_last; /* all channels are complete */
- scan_next(ss);
+ scan_signal(ss);
IEEE80211_UNLOCK(ic);
}
@@ -866,12 +801,22 @@ scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
{
struct ieee80211vap *vap = ss->ss_vap;
- IEEE80211_LOCK_ASSERT(vap->iv_ic);
-
+ IEEE80211_LOCK(vap->iv_ic);
if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
ieee80211_probe_curchan(vap, 0);
callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer,
- maxdwell, scan_next, ss);
+ maxdwell, scan_signal, ss);
+ IEEE80211_UNLOCK(vap->iv_ic);
+}
+
+static void
+scan_signal(void *arg)
+{
+ struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg;
+
+ IEEE80211_LOCK_ASSERT(ss->ss_ic);
+
+ cv_signal(&SCAN_PRIVATE(ss)->ss_scan_cv);
}
/*
@@ -881,35 +826,67 @@ scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
static void
scan_mindwell(struct ieee80211_scan_state *ss)
{
- callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer, 0, scan_next, ss);
+ struct ieee80211com *ic = ss->ss_ic;
+
+ IEEE80211_LOCK(ic);
+ scan_signal(ss);
+ IEEE80211_UNLOCK(ic);
}
-/*
- * Switch to the next channel marked for scanning.
- */
static void
-scan_next(void *arg)
+scan_task(void *arg, int pending)
{
-#define ISCAN_REP (ISCAN_MINDWELL | ISCAN_START | ISCAN_DISCARD)
+#define ISCAN_REP (ISCAN_MINDWELL | ISCAN_DISCARD)
struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg;
struct ieee80211vap *vap = ss->ss_vap;
- struct ieee80211com *ic = vap->iv_ic;
+ struct ieee80211com *ic = ss->ss_ic;
struct ieee80211_channel *chan;
unsigned long maxdwell, scanend;
- int scandone;
+ int scandone = 0;
- IEEE80211_LOCK_ASSERT(ic);
+ IEEE80211_LOCK(ic);
+ if (vap == NULL || (ic->ic_flags & IEEE80211_F_SCAN) == 0 ||
+ (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)) {
+ /* Cancelled before we started */
+ goto done;
+ }
+
+ if (ss->ss_next == ss->ss_last) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: no channels to scan\n", __func__);
+ goto done;
+ }
+
+ if (vap->iv_opmode == IEEE80211_M_STA &&
+ vap->iv_state == IEEE80211_S_RUN) {
+ if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) {
+ /* Enable station power save mode */
+ ieee80211_sta_pwrsave(vap, 1);
+ /*
+ * Use an 1ms delay so the null data frame has a chance
+ * to go out.
+ * XXX Should use M_TXCB mechanism to eliminate this.
+ */
+ cv_timedwait(&SCAN_PRIVATE(ss)->ss_scan_cv,
+ IEEE80211_LOCK_OBJ(ic), hz / 1000);
+ if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)
+ goto done;
+ }
+ }
+
+ scanend = ticks + SCAN_PRIVATE(ss)->ss_duration;
+ IEEE80211_UNLOCK(ic);
+ ic->ic_scan_start(ic); /* notify driver */
+ IEEE80211_LOCK(ic);
+
+ for (;;) {
+ scandone = (ss->ss_next >= ss->ss_last) ||
+ (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0;
+ if (scandone || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) ||
+ (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT) ||
+ time_after(ticks + ss->ss_mindwell, scanend))
+ break;
- if ((ic->ic_flags & IEEE80211_F_SCAN) == 0)
- return;
-again:
- scandone = (ss->ss_next >= ss->ss_last) ||
- (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0;
- scanend = SCAN_PRIVATE(ss)->ss_scanend;
- if (!scandone &&
- (ss->ss_flags & IEEE80211_SCAN_GOTPICK) == 0 &&
- ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_START) ||
- time_before(ticks + ss->ss_mindwell, scanend))) {
chan = ss->ss_chans[ss->ss_next++];
/*
@@ -934,7 +911,15 @@ again:
/*
* Potentially change channel and phy mode.
*/
- change_channel(ic, chan);
+ ic->ic_curchan = chan;
+ ic->ic_rt = ieee80211_get_ratetable(chan);
+ IEEE80211_UNLOCK(ic);
+ /*
+ * Perform the channel change and scan unlocked so the driver
+ * may sleep. Once set_channel returns the hardware has
+ * completed the channel change.
+ */
+ ic->ic_set_channel(ic);
/*
* Scan curchan. Drivers for "intelligent hardware"
@@ -942,93 +927,115 @@ again:
* the work. Otherwise we manage the work outselves;
* sending a probe request (as needed), and arming the
* timeout to switch channels after maxdwell ticks.
+ *
+ * scan_curchan should only pause for the time required to
+ * prepare/initiate the hardware for the scan (if at all), the
+ * below condvar is used to sleep for the channels dwell time
+ * and allows it to be signalled for abort.
*/
ic->ic_scan_curchan(ss, maxdwell);
+ IEEE80211_LOCK(ic);
SCAN_PRIVATE(ss)->ss_chanmindwell = ticks + ss->ss_mindwell;
/* clear mindwell lock and initial channel change flush */
SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP;
- } else {
- ic->ic_scan_end(ic); /* notify driver */
- /*
- * Record scan complete time. Note that we also do
- * this when canceled so any background scan will
- * not be restarted for a while.
- */
- if (scandone)
- ic->ic_lastscan = ticks;
- /* return to the bss channel */
- if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
- ic->ic_curchan != ic->ic_bsschan)
- ieee80211_setcurchan(ic, ic->ic_bsschan);
- /* clear internal flags and any indication of a pick */
- SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP;
- ss->ss_flags &= ~IEEE80211_SCAN_GOTPICK;
- /*
- * If not canceled and scan completed, do post-processing.
- * If the callback function returns 0, then it wants to
- * continue/restart scanning. Unfortunately we needed to
- * notify the driver to end the scan above to avoid having
- * rx frames alter the scan candidate list.
- */
- if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0 &&
- !ss->ss_ops->scan_end(ss, vap) &&
- (ss->ss_flags & IEEE80211_SCAN_ONCE) == 0 &&
- time_before(ticks + ss->ss_mindwell, scanend)) {
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
- "%s: done, restart "
- "[ticks %u, dwell min %lu scanend %lu]\n",
- __func__,
- ticks, ss->ss_mindwell, scanend);
- ss->ss_next = 0; /* reset to begining */
- if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
- vap->iv_stats.is_scan_active++;
- else
- vap->iv_stats.is_scan_passive++;
+ if ((SCAN_PRIVATE(ss)->ss_iflags & (ISCAN_CANCEL|ISCAN_ABORT)))
+ continue;
- ss->ss_ops->scan_restart(ss, vap); /* XXX? */
- ic->ic_scan_start(ic); /* notify driver */
- goto again;
- } else {
- /* past here, scandone is ``true'' if not in bg mode */
- if ((ss->ss_flags & IEEE80211_SCAN_BGSCAN) == 0)
- scandone = 1;
+ /* Wait to be signalled to scan the next channel */
+ cv_wait(&SCAN_PRIVATE(ss)->ss_scan_cv, IEEE80211_LOCK_OBJ(ic));
+ }
+ if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)
+ goto done;
- IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
- "%s: %s, "
- "[ticks %u, dwell min %lu scanend %lu]\n",
- __func__, scandone ? "done" : "stopped",
- ticks, ss->ss_mindwell, scanend);
+ IEEE80211_UNLOCK(ic);
+ ic->ic_scan_end(ic); /* notify driver */
+ IEEE80211_LOCK(ic);
- /*
- * Clear the SCAN bit first in case frames are
- * pending on the station power save queue. If
- * we defer this then the dispatch of the frames
- * may generate a request to cancel scanning.
- */
- ic->ic_flags &= ~IEEE80211_F_SCAN;
- /*
- * Drop out of power save mode when a scan has
- * completed. If this scan was prematurely terminated
- * because it is a background scan then don't notify
- * the ap; we'll either return to scanning after we
- * receive the beacon frame or we'll drop out of power
- * save mode because the beacon indicates we have frames
- * waiting for us.
- */
- if (scandone) {
- ieee80211_sta_pwrsave(vap, 0);
- if (ss->ss_next >= ss->ss_last) {
- ieee80211_notify_scan_done(vap);
- ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN;
- }
- }
- SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_CANCEL;
- ss->ss_flags &=
- ~(IEEE80211_SCAN_ONCE | IEEE80211_SCAN_PICK1ST);
+ /*
+ * Record scan complete time. Note that we also do
+ * this when canceled so any background scan will
+ * not be restarted for a while.
+ */
+ if (scandone)
+ ic->ic_lastscan = ticks;
+ /* return to the bss channel */
+ if (ic->ic_bsschan != IEEE80211_CHAN_ANYC &&
+ ic->ic_curchan != ic->ic_bsschan) {
+ ieee80211_setupcurchan(ic, ic->ic_bsschan);
+ IEEE80211_UNLOCK(ic);
+ ic->ic_set_channel(ic);
+ IEEE80211_LOCK(ic);
+ }
+ /* clear internal flags and any indication of a pick */
+ SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP;
+ ss->ss_flags &= ~IEEE80211_SCAN_GOTPICK;
+
+ /*
+ * If not canceled and scan completed, do post-processing.
+ * If the callback function returns 0, then it wants to
+ * continue/restart scanning. Unfortunately we needed to
+ * notify the driver to end the scan above to avoid having
+ * rx frames alter the scan candidate list.
+ */
+ if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0 &&
+ !ss->ss_ops->scan_end(ss, vap) &&
+ (ss->ss_flags & IEEE80211_SCAN_ONCE) == 0 &&
+ time_before(ticks + ss->ss_mindwell, scanend)) {
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: done, restart "
+ "[ticks %u, dwell min %lu scanend %lu]\n",
+ __func__,
+ ticks, ss->ss_mindwell, scanend);
+ ss->ss_next = 0; /* reset to begining */
+ if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
+ vap->iv_stats.is_scan_active++;
+ else
+ vap->iv_stats.is_scan_passive++;
+
+ ss->ss_ops->scan_restart(ss, vap); /* XXX? */
+ ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
+ IEEE80211_UNLOCK(ic);
+ return;
+ }
+
+ /* past here, scandone is ``true'' if not in bg mode */
+ if ((ss->ss_flags & IEEE80211_SCAN_BGSCAN) == 0)
+ scandone = 1;
+
+ IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
+ "%s: %s, [ticks %u, dwell min %lu scanend %lu]\n",
+ __func__, scandone ? "done" : "stopped",
+ ticks, ss->ss_mindwell, scanend);
+
+ /*
+ * Clear the SCAN bit first in case frames are
+ * pending on the station power save queue. If
+ * we defer this then the dispatch of the frames
+ * may generate a request to cancel scanning.
+ */
+done:
+ ic->ic_flags &= ~IEEE80211_F_SCAN;
+ /*
+ * Drop out of power save mode when a scan has
+ * completed. If this scan was prematurely terminated
+ * because it is a background scan then don't notify
+ * the ap; we'll either return to scanning after we
+ * receive the beacon frame or we'll drop out of power
+ * save mode because the beacon indicates we have frames
+ * waiting for us.
+ */
+ if (scandone) {
+ ieee80211_sta_pwrsave(vap, 0);
+ if (ss->ss_next >= ss->ss_last) {
+ ieee80211_notify_scan_done(vap);
+ ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN;
}
}
+ SCAN_PRIVATE(ss)->ss_iflags &= ~(ISCAN_CANCEL|ISCAN_ABORT);
+ ss->ss_flags &= ~(IEEE80211_SCAN_ONCE | IEEE80211_SCAN_PICK1ST);
+ IEEE80211_UNLOCK(ic);
#undef ISCAN_REP
}
diff --git a/sys/net80211/ieee80211_scan.h b/sys/net80211/ieee80211_scan.h
index 78e5fe4..edba660 100644
--- a/sys/net80211/ieee80211_scan.h
+++ b/sys/net80211/ieee80211_scan.h
@@ -90,6 +90,7 @@ struct ieee80211_scan_ssid {
*/
struct ieee80211_scan_state {
struct ieee80211vap *ss_vap;
+ struct ieee80211com *ss_ic;
const struct ieee80211_scanner *ss_ops; /* policy hookup, see below */
void *ss_priv; /* scanner private state */
uint16_t ss_flags;
diff --git a/sys/net80211/ieee80211_scan_sta.c b/sys/net80211/ieee80211_scan_sta.c
index 607c36d..cef3db4 100644
--- a/sys/net80211/ieee80211_scan_sta.c
+++ b/sys/net80211/ieee80211_scan_sta.c
@@ -32,10 +32,10 @@ __FBSDID("$FreeBSD$");
#include "opt_wlan.h"
#include <sys/param.h>
-#include <sys/systm.h>
+#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
-
+
#include <sys/socket.h>
#include <net/if.h>
@@ -1640,7 +1640,7 @@ ap_force_promisc(struct ieee80211com *ic)
IEEE80211_LOCK(ic);
/* set interface into promiscuous mode */
ifp->if_flags |= IFF_PROMISC;
- ic->ic_update_promisc(ifp);
+ ieee80211_runtask(ic, &ic->ic_promisc_task);
IEEE80211_UNLOCK(ic);
}
diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h
index 55204f8..6c4ee74 100644
--- a/sys/net80211/ieee80211_var.h
+++ b/sys/net80211/ieee80211_var.h
@@ -126,7 +126,12 @@ struct ieee80211com {
enum ieee80211_opmode ic_opmode; /* operation mode */
struct ifmedia ic_media; /* interface media config */
struct callout ic_inact; /* inactivity processing */
+ struct taskqueue *ic_tq; /* deferred state thread */
struct task ic_parent_task; /* deferred parent processing */
+ struct task ic_promisc_task;/* deferred promisc update */
+ struct task ic_mcast_task; /* deferred mcast update */
+ struct task ic_chan_task; /* deferred channel change */
+ struct task ic_bmiss_task; /* deferred beacon miss hndlr */
uint32_t ic_flags; /* state flags */
uint32_t ic_flags_ext; /* extended state flags */
@@ -325,8 +330,10 @@ struct ieee80211vap {
uint32_t iv_htcaps; /* HT capabilities */
enum ieee80211_opmode iv_opmode; /* operation mode */
enum ieee80211_state iv_state; /* state machine state */
- void (*iv_newstate_cb)(struct ieee80211vap *,
- enum ieee80211_state, int);
+ enum ieee80211_state iv_nstate; /* pending state */
+ int iv_nstate_arg; /* pending state arg */
+ struct task iv_nstate_task; /* deferred state processing */
+ struct task iv_swbmiss_task;/* deferred iv_bmiss call */
struct callout iv_mgtsend; /* mgmt frame response timer */
/* inactivity timer settings */
int iv_inact_init; /* setting for new station */
@@ -519,6 +526,8 @@ MALLOC_DECLARE(M_80211_VAP);
#define IEEE80211_FEXT_SWBMISS 0x00000400 /* CONF: do bmiss in s/w */
#define IEEE80211_FEXT_DFS 0x00000800 /* CONF: DFS enabled */
#define IEEE80211_FEXT_DOTD 0x00001000 /* CONF: 11d enabled */
+#define IEEE80211_FEXT_STATEWAIT 0x00002000 /* STATUS: awaiting state chg */
+#define IEEE80211_FEXT_REINIT 0x00004000 /* STATUS: INIT state first */
/* NB: immutable: should be set only when creating a vap */
#define IEEE80211_FEXT_WDSLEGACY 0x00010000 /* CONF: legacy WDS operation */
#define IEEE80211_FEXT_PROBECHAN 0x00020000 /* CONF: probe passive channel*/
@@ -536,9 +545,10 @@ MALLOC_DECLARE(M_80211_VAP);
#define IEEE80211_FEXT_BITS \
"\20\1NONHT_PR\2INACT\3SCANWAIT\4BGSCAN\5WPS\6TSN\7SCANREQ\10RESUME" \
- "\0114ADDR\12NONEPR_PR\13SWBMISS\14DFS\15DOTD\22WDSLEGACY\23PROBECHAN" \
- "\24HT\25AMDPU_TX\26AMPDU_TX\27AMSDU_TX\30AMSDU_RX\31USEHT40\32PUREN" \
- "\33SHORTGI20\34SHORTGI40\35HTCOMPAT\36RIFS"
+ "\0114ADDR\12NONEPR_PR\13SWBMISS\14DFS\15DOTD\16STATEWAIT\17REINIT" \
+ "\22WDSLEGACY\23PROBECHAN\24HT\25AMDPU_TX\26AMPDU_TX\27AMSDU_TX" \
+ "\30AMSDU_RX\31USEHT40\32PUREN\33SHORTGI20\34SHORTGI40\35HTCOMPAT" \
+ "\36RIFS"
#define IEEE80211_FVEN_BITS "\20"
@@ -633,6 +643,24 @@ struct ieee80211_channel *ieee80211_find_channel_byieee(struct ieee80211com *,
int ieee80211_setmode(struct ieee80211com *, enum ieee80211_phymode);
enum ieee80211_phymode ieee80211_chan2mode(const struct ieee80211_channel *);
+/*
+ * Enqueue a task on the state thread.
+ */
+static __inline void
+ieee80211_runtask(struct ieee80211com *ic, struct task *task)
+{
+ taskqueue_enqueue(ic->ic_tq, task);
+}
+
+/*
+ * Wait for a queued task to complete.
+ */
+static __inline void
+ieee80211_draintask(struct ieee80211com *ic, struct task *task)
+{
+ taskqueue_drain(ic->ic_tq, task);
+}
+
/*
* Key update synchronization methods. XXX should not be visible.
*/
OpenPOWER on IntegriCloud