Changeset View
Changeset View
Standalone View
Standalone View
sys/net80211/ieee80211_scan_sw.c
Show First 20 Lines • Show All 588 Lines • ▼ Show 20 Lines | scan_mindwell(struct ieee80211_scan_state *ss) | ||||
IEEE80211_UNLOCK(ic); | IEEE80211_UNLOCK(ic); | ||||
} | } | ||||
static void | static void | ||||
scan_task(void *arg, int pending) | scan_task(void *arg, int pending) | ||||
{ | { | ||||
#define ISCAN_REP (ISCAN_MINDWELL | ISCAN_DISCARD) | #define ISCAN_REP (ISCAN_MINDWELL | ISCAN_DISCARD) | ||||
struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg; | struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg; | ||||
struct scan_state *ss_priv = SCAN_PRIVATE(ss); | |||||
struct ieee80211vap *vap = ss->ss_vap; | struct ieee80211vap *vap = ss->ss_vap; | ||||
struct ieee80211com *ic = ss->ss_ic; | struct ieee80211com *ic = ss->ss_ic; | ||||
struct ieee80211_channel *chan; | struct ieee80211_channel *chan; | ||||
unsigned long maxdwell, scanend; | unsigned long maxdwell, scanend; | ||||
int scandone = 0; | int scandone = 0; | ||||
IEEE80211_LOCK(ic); | IEEE80211_LOCK(ic); | ||||
if (vap == NULL || (ic->ic_flags & IEEE80211_F_SCAN) == 0 || | if (vap == NULL || (ic->ic_flags & IEEE80211_F_SCAN) == 0 || | ||||
(SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)) { | (ss_priv->ss_iflags & ISCAN_ABORT)) { | ||||
/* Cancelled before we started */ | /* Cancelled before we started */ | ||||
goto done; | goto done; | ||||
} | } | ||||
if (ss->ss_next == ss->ss_last) { | if (ss->ss_next == ss->ss_last) { | ||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, | IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, | ||||
"%s: no channels to scan\n", __func__); | "%s: no channels to scan\n", __func__); | ||||
scandone = 1; | scandone = 1; | ||||
goto done; | goto done; | ||||
} | } | ||||
if (vap->iv_opmode == IEEE80211_M_STA && | if (vap->iv_opmode == IEEE80211_M_STA && | ||||
vap->iv_state == IEEE80211_S_RUN) { | vap->iv_state == IEEE80211_S_RUN) { | ||||
if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) { | if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) { | ||||
/* Enable station power save mode */ | /* Enable station power save mode */ | ||||
vap->iv_sta_ps(vap, 1); | vap->iv_sta_ps(vap, 1); | ||||
/* | /* | ||||
* Use an 1ms delay so the null data frame has a chance | * Use an 1ms delay so the null data frame has a chance | ||||
* to go out. | * to go out. | ||||
* XXX Should use M_TXCB mechanism to eliminate this. | * XXX Should use M_TXCB mechanism to eliminate this. | ||||
*/ | */ | ||||
cv_timedwait(&SCAN_PRIVATE(ss)->ss_scan_cv, | cv_timedwait(&ss_priv->ss_scan_cv, | ||||
IEEE80211_LOCK_OBJ(ic), msecs_to_ticks(1)); | IEEE80211_LOCK_OBJ(ic), msecs_to_ticks(1)); | ||||
if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT) | if (ss_priv->ss_iflags & ISCAN_ABORT) | ||||
goto done; | goto done; | ||||
} | } | ||||
} | } | ||||
scanend = ticks + SCAN_PRIVATE(ss)->ss_duration; | scanend = ticks + ss_priv->ss_duration; | ||||
/* XXX scan state can change! Re-validate scan state! */ | /* XXX scan state can change! Re-validate scan state! */ | ||||
IEEE80211_UNLOCK(ic); | IEEE80211_UNLOCK(ic); | ||||
ic->ic_scan_start(ic); /* notify driver */ | ic->ic_scan_start(ic); /* notify driver */ | ||||
IEEE80211_LOCK(ic); | IEEE80211_LOCK(ic); | ||||
for (;;) { | for (;;) { | ||||
scandone = (ss->ss_next >= ss->ss_last) || | scandone = (ss->ss_next >= ss->ss_last) || | ||||
(SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0; | (ss_priv->ss_iflags & ISCAN_CANCEL) != 0; | ||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, | IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, | ||||
"%s: loop start; scandone=%d\n", | "%s: loop start; scandone=%d\n", | ||||
__func__, | __func__, | ||||
scandone); | scandone); | ||||
if (scandone || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) || | if (scandone || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) || | ||||
(SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT) || | (ss_priv->ss_iflags & ISCAN_ABORT) || | ||||
time_after(ticks + ss->ss_mindwell, scanend)) | time_after(ticks + ss->ss_mindwell, scanend)) | ||||
break; | break; | ||||
chan = ss->ss_chans[ss->ss_next++]; | chan = ss->ss_chans[ss->ss_next++]; | ||||
/* | /* | ||||
* Watch for truncation due to the scan end time. | * Watch for truncation due to the scan end time. | ||||
*/ | */ | ||||
Show All 40 Lines | for (;;) { | ||||
* below condvar is used to sleep for the channels dwell time | * below condvar is used to sleep for the channels dwell time | ||||
* and allows it to be signalled for abort. | * and allows it to be signalled for abort. | ||||
*/ | */ | ||||
ic->ic_scan_curchan(ss, maxdwell); | ic->ic_scan_curchan(ss, maxdwell); | ||||
IEEE80211_LOCK(ic); | IEEE80211_LOCK(ic); | ||||
/* XXX scan state can change! Re-validate scan state! */ | /* XXX scan state can change! Re-validate scan state! */ | ||||
SCAN_PRIVATE(ss)->ss_chanmindwell = ticks + ss->ss_mindwell; | ss_priv->ss_chanmindwell = ticks + ss->ss_mindwell; | ||||
/* clear mindwell lock and initial channel change flush */ | /* clear mindwell lock and initial channel change flush */ | ||||
SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP; | ss_priv->ss_iflags &= ~ISCAN_REP; | ||||
if ((SCAN_PRIVATE(ss)->ss_iflags & (ISCAN_CANCEL|ISCAN_ABORT))) | if (ss_priv->ss_iflags & (ISCAN_CANCEL|ISCAN_ABORT)) | ||||
continue; | continue; | ||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: waiting\n", __func__); | IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: waiting\n", __func__); | ||||
/* Wait to be signalled to scan the next channel */ | /* Wait to be signalled to scan the next channel */ | ||||
cv_wait(&SCAN_PRIVATE(ss)->ss_scan_cv, IEEE80211_LOCK_OBJ(ic)); | cv_wait(&ss_priv->ss_scan_cv, IEEE80211_LOCK_OBJ(ic)); | ||||
} | } | ||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: out\n", __func__); | IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: out\n", __func__); | ||||
if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT) | if (ss_priv->ss_iflags & ISCAN_ABORT) | ||||
goto done; | goto done; | ||||
IEEE80211_UNLOCK(ic); | IEEE80211_UNLOCK(ic); | ||||
ic->ic_scan_end(ic); /* notify driver */ | ic->ic_scan_end(ic); /* notify driver */ | ||||
IEEE80211_LOCK(ic); | IEEE80211_LOCK(ic); | ||||
/* XXX scan state can change! Re-validate scan state! */ | /* XXX scan state can change! Re-validate scan state! */ | ||||
/* | /* | ||||
* Since a cancellation may have occured during one of the | * Since a cancellation may have occured during one of the | ||||
* driver calls (whilst unlocked), update scandone. | * driver calls (whilst unlocked), update scandone. | ||||
*/ | */ | ||||
if (scandone == 0 && | if (scandone == 0 && (ss_priv->ss_iflags & ISCAN_CANCEL) != 0) { | ||||
((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0)) { | |||||
/* XXX printf? */ | /* XXX printf? */ | ||||
if_printf(vap->iv_ifp, | if_printf(vap->iv_ifp, | ||||
"%s: OOPS! scan cancelled during driver call (1)!\n", | "%s: OOPS! scan cancelled during driver call (1)!\n", | ||||
__func__); | __func__); | ||||
scandone = 1; | scandone = 1; | ||||
} | } | ||||
/* | /* | ||||
* Record scan complete time. Note that we also do | * Record scan complete time. Note that we also do | ||||
* this when canceled so any background scan will | * this when canceled so any background scan will | ||||
* not be restarted for a while. | * not be restarted for a while. | ||||
*/ | */ | ||||
if (scandone) | if (scandone) | ||||
ic->ic_lastscan = ticks; | ic->ic_lastscan = ticks; | ||||
/* return to the bss channel */ | /* return to the bss channel */ | ||||
if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && | if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && | ||||
ic->ic_curchan != ic->ic_bsschan) { | ic->ic_curchan != ic->ic_bsschan) { | ||||
ieee80211_setupcurchan(ic, ic->ic_bsschan); | ieee80211_setupcurchan(ic, ic->ic_bsschan); | ||||
IEEE80211_UNLOCK(ic); | IEEE80211_UNLOCK(ic); | ||||
ic->ic_set_channel(ic); | ic->ic_set_channel(ic); | ||||
ieee80211_radiotap_chan_change(ic); | ieee80211_radiotap_chan_change(ic); | ||||
IEEE80211_LOCK(ic); | IEEE80211_LOCK(ic); | ||||
} | } | ||||
/* clear internal flags and any indication of a pick */ | /* clear internal flags and any indication of a pick */ | ||||
SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP; | ss_priv->ss_iflags &= ~ISCAN_REP; | ||||
ss->ss_flags &= ~IEEE80211_SCAN_GOTPICK; | ss->ss_flags &= ~IEEE80211_SCAN_GOTPICK; | ||||
/* | /* | ||||
* If not canceled and scan completed, do post-processing. | * If not canceled and scan completed, do post-processing. | ||||
* If the callback function returns 0, then it wants to | * If the callback function returns 0, then it wants to | ||||
* continue/restart scanning. Unfortunately we needed to | * continue/restart scanning. Unfortunately we needed to | ||||
* notify the driver to end the scan above to avoid having | * notify the driver to end the scan above to avoid having | ||||
* rx frames alter the scan candidate list. | * rx frames alter the scan candidate list. | ||||
*/ | */ | ||||
if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0 && | if ((ss_priv->ss_iflags & ISCAN_CANCEL) == 0 && | ||||
!ss->ss_ops->scan_end(ss, vap) && | !ss->ss_ops->scan_end(ss, vap) && | ||||
(ss->ss_flags & IEEE80211_SCAN_ONCE) == 0 && | (ss->ss_flags & IEEE80211_SCAN_ONCE) == 0 && | ||||
time_before(ticks + ss->ss_mindwell, scanend)) { | time_before(ticks + ss->ss_mindwell, scanend)) { | ||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, | IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, | ||||
"%s: done, restart " | "%s: done, restart " | ||||
"[ticks %u, dwell min %lu scanend %lu]\n", | "[ticks %u, dwell min %lu scanend %lu]\n", | ||||
__func__, | __func__, | ||||
ticks, ss->ss_mindwell, scanend); | ticks, ss->ss_mindwell, scanend); | ||||
ss->ss_next = 0; /* reset to begining */ | ss->ss_next = 0; /* reset to begining */ | ||||
if (ss->ss_flags & IEEE80211_SCAN_ACTIVE) | if (ss->ss_flags & IEEE80211_SCAN_ACTIVE) | ||||
vap->iv_stats.is_scan_active++; | vap->iv_stats.is_scan_active++; | ||||
else | else | ||||
vap->iv_stats.is_scan_passive++; | vap->iv_stats.is_scan_passive++; | ||||
ss->ss_ops->scan_restart(ss, vap); /* XXX? */ | ss->ss_ops->scan_restart(ss, vap); /* XXX? */ | ||||
ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task); | ieee80211_runtask(ic, &ss_priv->ss_scan_task); | ||||
IEEE80211_UNLOCK(ic); | IEEE80211_UNLOCK(ic); | ||||
return; | return; | ||||
} | } | ||||
/* past here, scandone is ``true'' if not in bg mode */ | /* past here, scandone is ``true'' if not in bg mode */ | ||||
if ((ss->ss_flags & IEEE80211_SCAN_BGSCAN) == 0) | if ((ss->ss_flags & IEEE80211_SCAN_BGSCAN) == 0) | ||||
scandone = 1; | scandone = 1; | ||||
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, | IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, | ||||
"%s: %s, [ticks %u, dwell min %lu scanend %lu]\n", | "%s: %s, [ticks %u, dwell min %lu scanend %lu]\n", | ||||
__func__, scandone ? "done" : "stopped", | __func__, scandone ? "done" : "stopped", | ||||
ticks, ss->ss_mindwell, scanend); | ticks, ss->ss_mindwell, scanend); | ||||
/* | /* | ||||
* Since a cancellation may have occured during one of the | * Since a cancellation may have occured during one of the | ||||
* driver calls (whilst unlocked), update scandone. | * driver calls (whilst unlocked), update scandone. | ||||
*/ | */ | ||||
if (scandone == 0 && | if (scandone == 0 && (ss_priv->ss_iflags & ISCAN_CANCEL) != 0) { | ||||
((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0)) { | |||||
/* XXX printf? */ | /* XXX printf? */ | ||||
if_printf(vap->iv_ifp, | if_printf(vap->iv_ifp, | ||||
"%s: OOPS! scan cancelled during driver call (2)!\n", | "%s: OOPS! scan cancelled during driver call (2)!\n", | ||||
__func__); | __func__); | ||||
scandone = 1; | scandone = 1; | ||||
} | } | ||||
/* | /* | ||||
Show All 15 Lines | done: | ||||
*/ | */ | ||||
if (scandone) { | if (scandone) { | ||||
vap->iv_sta_ps(vap, 0); | vap->iv_sta_ps(vap, 0); | ||||
if (ss->ss_next >= ss->ss_last) { | if (ss->ss_next >= ss->ss_last) { | ||||
ieee80211_notify_scan_done(vap); | ieee80211_notify_scan_done(vap); | ||||
ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN; | ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN; | ||||
} | } | ||||
} | } | ||||
SCAN_PRIVATE(ss)->ss_iflags &= ~(ISCAN_CANCEL|ISCAN_ABORT); | ss_priv->ss_iflags &= ~(ISCAN_CANCEL|ISCAN_ABORT); | ||||
ss->ss_flags &= ~(IEEE80211_SCAN_ONCE | IEEE80211_SCAN_PICK1ST); | ss->ss_flags &= ~(IEEE80211_SCAN_ONCE | IEEE80211_SCAN_PICK1ST); | ||||
IEEE80211_UNLOCK(ic); | IEEE80211_UNLOCK(ic); | ||||
#undef ISCAN_REP | #undef ISCAN_REP | ||||
} | } | ||||
/* | /* | ||||
* Process a beacon or probe response frame. | * Process a beacon or probe response frame. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 95 Lines • Show Last 20 Lines |