8000 net80211: split scan_task() (#3) (into scan_start() and · freebsd/freebsd-src@2755a03 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2755a03

Browse files
author
avos
committed
net80211: split scan_task() (#3) (into scan_start() and
scan_curchan_task() functions) (This part should fix the problem, described in https://lists.freebsd.org/pipermail/freebsd-wireless/2016-January/006420.html) - Rename ss_scan_task into ss_scan_start (better describes it's current purpose) - Utilize taskqueue_*_timeout() functions instead of current mechanism: * reschedule scan_curchan_task() via taskqueue_enqueue_timeout() for every 'maxdwell' msecs (will replace infinite loop + sleeping for 'maxdwell' period via cv_wait()); * rerun the task immediately when an external event occurs (instead of waking it up via cv_signal()) Also, use mtx_sleep() to wait for null frame transmission (allows to drop conditional variable). Tested with: * Intel 3945BG, STA mode; * RTL8188EU, STA mode. Approved by: adrian (mentor) Differential Revision: https://reviews.freebsd.org/D5145 git-svn-id: svn+ssh://svn.freebsd.org/base/head@296232 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f
1 parent bcaeb73 commit 2755a03

File tree

1 file changed

+111
-92
lines changed

1 file changed

+111
-92
lines changed

sys/net80211/ieee80211_scan_sw.c

Lines changed: 111 additions & 92 deletions
F438
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,12 @@ struct scan_state {
5959
#define ISCAN_DISCARD 0x0002 /* discard rx'd frames */
6060
#define ISCAN_CANCEL 0x0004 /* cancel current scan */
6161
#define ISCAN_ABORT 0x0008 /* end the scan immediately */
62+
#define ISCAN_RUNNING 0x0010 /* scan was started */
6263
unsigned long ss_chanmindwell; /* min dwell on curchan */
6364
unsigned long ss_scanend; /* time scan must stop */
6465
u_int ss_duration; /* duration for next scan */
65-
struct task ss_scan_task; /* scan execution */
66-
struct cv ss_scan_cv; /* scan signal */
67-
struct callout ss_scan_timer; /* scan timer */
66+
struct task ss_scan_start; /* scan start */
67+
struct timeout_task ss_scan_curchan; /* scan execution */
6868
};
6969
#define SCAN_PRIVATE(ss) ((struct scan_state *) ss)
7070

@@ -99,7 +99,8 @@ struct scan_state {
9999
static void scan_curchan(struct ieee80211_scan_state *, unsigned long);
100100
static void scan_mindwell(struct ieee80211_scan_state *);
101101
static void scan_signal(void *);
102-
static void scan_task(void *, int);
102+
static void scan_start(void *, int);
103+
static void scan_curchan_task(void *, int);
103104
static void scan_end(struct ieee80211_scan_state *, int);
104105
static void scan_done(struct ieee80211_scan_state *, int);
105106

@@ -115,8 +116,9 @@ ieee80211_swscan_detach(struct ieee80211com *ic)
115116
SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_ABORT;
116117
scan_signal(ss);
117118
IEEE80211_UNLOCK(ic);
118-
ieee80211_draintask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
119-
callout_drain(&SCAN_PRIVATE(ss)->ss_scan_timer);
119+
ieee80211_draintask(ic, &SCAN_PRIVATE(ss)->ss_scan_start);
120+
taskqueue_drain_timeout(ic->ic_tq,
121+
&SCAN_PRIVATE(ss)->ss_scan_curchan);
120122
KASSERT((ic->ic_flags & IEEE80211_F_SCAN) == 0,
121123
("scan still running"));
122124

@@ -238,7 +240,7 @@ ieee80211_swscan_start_scan_locked(const struct ieee80211_scanner *scan,
238240
ic->ic_flags |= IEEE80211_F_SCAN;
239241

240242
/* Start scan task */
241-
ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
243+
ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_start);
242244
}
243245
return 1;
244246
} else {
@@ -413,7 +415,8 @@ ieee80211_swscan_bg_scan(const struct ieee80211_scanner *scan,
413415
ss->ss_maxdwell = duration;
414416
ic->ic_flags |= IEEE80211_F_SCAN;
415417
ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN;
416-
ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
418+
ieee80211_runtask(ic,
419+
&SCAN_PRIVATE(ss)->ss_scan_start);
417420
} else {
418421
/* XXX msg+stat */
419422
}
@@ -560,18 +563,25 @@ scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
560563
IEEE80211_LOCK(vap->iv_ic);
561564
if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
562565
ieee80211_probe_curchan(vap, 0);
563-
callout_reset(&SCAN_PRIVATE(ss)->ss_scan_timer,
564-
maxdwell, scan_signal, ss);
566+
taskqueue_enqueue_timeout(vap->iv_ic->ic_tq,
567+
&SCAN_PRIVATE(ss)->ss_scan_curchan, maxdwell);
565568
IEEE80211_UNLOCK(vap->iv_ic);
566569
}
567570

568571
static void
569572
scan_signal(void *arg)
570573
{
571574
struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg;
575+
struct scan_state *ss_priv = SCAN_PRIVATE(ss);
576+
struct timeout_task *scan_task = &ss_priv->ss_scan_curchan;
577+
struct ieee80211com *ic = ss->ss_ic;
578+
579+
IEEE80211_LOCK_ASSERT(ic);
572580

573-
IEEE80211_LOCK_ASSERT(ss->ss_ic);
574-
cv_signal(&SCAN_PRIVATE(ss)->ss_scan_cv);
581+
if (ss_priv->ss_iflags & ISCAN_RUNNING) {
582+
if (taskqueue_cancel_timeout(ic->ic_tq, scan_task, NULL) == 0)
583+
taskqueue_enqueue_timeout(ic->ic_tq, scan_task, 0);
584+
}
575585
}
576586

577587
/*
@@ -591,16 +601,13 @@ scan_mindwell(struct ieee80211_scan_state *ss)
591601
}
592602

593603
static void
594-
scan_task(void *arg, int pending)
604+
scan_start(void *arg, int pending)
595605
{
596606
#define ISCAN_REP (ISCAN_MINDWELL | ISCAN_DISCARD)
597607
struct ieee80211_scan_state *ss = (struct ieee80211_scan_state *) arg;
598608
struct scan_state *ss_priv = SCAN_PRIVATE(ss);
599609
struct ieee80211vap *vap = ss->ss_vap;
600610
struct ieee80211com *ic = ss->ss_ic;
601-
struct ieee80211_channel *chan;
602-
unsigned long maxdwell;
603-
int scandone = 0;
604611

605612
IEEE80211_LOCK(ic);
606613
if (vap == NULL || (ic->ic_flags & IEEE80211_F_SCAN) == 0 ||
@@ -627,8 +634,8 @@ scan_task(void *arg, int pending)
627634
* to go out.
628635
* XXX Should use M_TXCB mechanism to eliminate this.
629636
*/
630-
cv_timedwait(&ss_priv->ss_scan_cv,
631-
IEEE80211_LOCK_OBJ(ic), msecs_to_ticks(1));
637+
mtx_sleep(vap, IEEE80211_LOCK_OBJ(ic), PCATCH,
638+
"sta_ps", msecs_to_ticks(1));
632639
if (ss_priv->ss_iflags & ISCAN_ABORT) {
633640
scan_done(ss, 0);
634641
return;
@@ -641,90 +648,102 @@ scan_task(void *arg, int pending)
641648
/* XXX scan state can change! Re-validate scan state! */
642649

643650
IEEE80211_UNLOCK(ic);
651+
644652
ic->ic_scan_start(ic); /* notify driver */
645-
IEEE80211_LOCK(ic);
646653

647-
for (;;) {
654+
scan_curchan_task(ss, 0);
655+
}
648656

649-
scandone = (ss->ss_next >= ss->ss_last) ||
650-
(ss_priv->ss_iflags & ISCAN_CANCEL) != 0;
657+
static void
658+
scan_curchan_task(void *arg, int pending)
659+
{
660+
struct ieee80211_scan_state *ss = arg;
661+
struct scan_state *ss_priv = SCAN_PRIVATE(ss);
662+
struct ieee80211vap *vap = ss->ss_vap;
663+
struct ieee80211com *ic = ss->ss_ic;
664+
struct ieee80211_channel *chan;
665+
unsigned long maxdwell;
666+
int scandone;
651667

652-
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
653-
"%s: loop start; scandone=%d\n",
654-
__func__,
655-
scandone);
668+
IEEE80211_LOCK(ic);
669+
end:
670+
scandone = (ss->ss_next >= ss->ss_last) ||
671+
(ss_priv->ss_iflags & ISCAN_CANCEL) != 0;
656672

657-
if (scandone || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) ||
658-
(ss_priv->ss_iflags & ISCAN_ABORT) ||
659-
time_after(ticks + ss->ss_mindwell, ss_priv->ss_scanend)) {
660-
scan_end(ss, scandone);
661-
return;
662-
}
673+
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
674+
"%s: loop start; scandone=%d\n",
675+
__func__,
676+
scandone);
663677

664-
chan = ss->ss_chans[ss->ss_next++];
678+
if (scandone || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) ||
679+
(ss_priv->ss_iflags & ISCAN_ABORT) ||
680+
time_after(ticks + ss->ss_mindwell, ss_priv->ss_scanend)) {
681+
ss_priv->ss_iflags &= ~ISCAN_RUNNING;
682+
scan_end(ss, scandone);
683+
return;
684+
} else
685+
ss_priv->ss_iflags |= ISCAN_RUNNING;
665686

666-
/*
667-
* Watch for truncation due to the scan end time.
668-
*/
669-
if (time_after(ticks + ss->ss_maxdwell, ss_priv->ss_scanend))
670-
maxdwell = ss_priv->ss_scanend - ticks;
671-
else
672-
maxdwell = ss->ss_maxdwell;
687+
chan = ss->ss_chans[ss->ss_next++];
673688

674-
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
675-
"%s: chan %3d%c -> %3d%c [%s, dwell min %lums max %lums]\n",
676-
__func__,
677-
ieee80211_chan2ieee(ic, ic->ic_curchan),
678-
ieee80211_channel_type_char(ic->ic_curchan),
679-
ieee80211_chan2ieee(ic, chan),
680-
ieee80211_channel_type_char(chan),
681-
(ss->ss_flags & IEEE80211_SCAN_ACTIVE) &&
682-
(chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0 ?
683-
"active" : "passive",
684-
ticks_to_msecs(ss->ss_mindwell), ticks_to_msecs(maxdwell));
689+
/*
690+
* Watch for truncation due to the scan end time.
691+
*/
692+
if (time_after(ticks + ss->ss_maxdwell, ss_priv->ss_scanend))
693+
maxdwell = ss_priv->ss_scanend - ticks;
694+
else
695+
maxdwell = ss->ss_maxdwell;
685696

686-
/*
687-
* Potentially change channel and phy mode.
688-
*/
689-
ic->ic_curchan = chan;
690-
ic->ic_rt = ieee80211_get_ratetable(chan);
691-
IEEE80211_UNLOCK(ic);
692-
/*
693-
* Perform the channel change and scan unlocked so the driver
694-
* may sleep. Once set_channel returns the hardware has
695-
* completed the channel change.
696-
*/
697-
ic->ic_set_channel(ic);
698-
ieee80211_radiotap_chan_change(ic);
697+
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
698+
"%s: chan %3d%c -> %3d%c [%s, dwell min %lums max %lums]\n",
699+
__func__,
700+
ieee80211_chan2ieee(ic, ic->ic_curchan),
701+
ieee80211_channel_type_char(ic->ic_curchan),
702+
ieee80211_chan2ieee(ic, chan),
703+
ieee80211_channel_type_char(chan),
704+
(ss->ss_flags & IEEE80211_SCAN_ACTIVE) &&
705+
(chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0 ?
706+
"active" : "passive",
707+
ticks_to_msecs(ss->ss_mindwell), ticks_to_msecs(maxdwell));
699708

700-
/*
701-
* Scan curchan. Drivers for "intelligent hardware"
702-
* override ic_scan_curchan to tell the device to do
703-
* the work. Otherwise we manage the work outselves;
704-
* sending a probe request (as needed), and arming the
705-
* timeout to switch channels after maxdwell ticks.
706-
*
707-
* scan_curchan should only pause for the time required to
708-
* prepare/initiate the hardware for the scan (if at all), the
709-
* below condvar is used to sleep for the channels dwell time
710-
* and allows it to be signalled for abort.
711-
*/
712-
ic->ic_scan_curchan(ss, maxdwell);
713-
IEEE80211_LOCK(ic);
709+
/*
710+
* Potentially change channel and phy mode.
711+
*/
712+
ic->ic_curchan = chan;
713+
ic->ic_rt = ieee80211_get_ratetable(chan);
714+
IEEE80211_UNLOCK(ic);
715+
/*
716+
* Perform the channel change and scan unlocked so the driver
717+
* may sleep. Once set_channel returns the hardware has
718+
* completed the channel change.
719+
*/
720+
ic->ic_set_channel(ic);
721+
ieee80211_radiotap_chan_change(ic);
722+
723+
/*
724+
* Scan curchan. Drivers for "intelligent hardware"
725+
* override ic_scan_curchan to tell the device to do
726+
* the work. Otherwise we manage the work ourselves;
727+
* sending a probe request (as needed), and arming the
728+
* timeout to switch channels after maxdwell ticks.
729+
*
730+
* scan_curchan should only pause for the time required to
731+
* prepare/initiate the hardware for the scan (if at all).
732+
*/
< F438 /code>733+
ic->ic_scan_curchan(ss, maxdwell);
734+
IEEE80211_LOCK(ic);
714735

715-
/* XXX scan state can change! Re-validate scan state! */
736+
/* XXX scan state can change! Re-validate scan state! */
716737

717-
ss_priv->ss_chanmindwell = ticks + ss->ss_mindwell;
718-
/* clear mindwell lock and initial channel change flush */
719-
ss_priv->ss_iflags &= ~ISCAN_REP;
738+
ss_priv->ss_chanmindwell = ticks + ss->ss_mindwell;
739+
/* clear mindwell lock and initial channel change flush */
740+
ss_priv->ss_iflags &= ~ISCAN_REP;
720741

721-
if (ss_priv->ss_iflags & (ISCAN_CANCEL|ISCAN_ABORT))
722-
continue;
742+
if (ss_priv->ss_iflags & (ISCAN_CANCEL|ISCAN_ABORT))
743+
goto end;
723744

724-
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: waiting\n", __func__);
725-
/* Wait to be signalled to scan the next channel */
726-
cv_wait(&ss_priv->ss_scan_cv, IEEE80211_LOCK_OBJ(ic));
727-
}
745+
IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: waiting\n", __func__);
746+
IEEE80211_UNLOCK(ic);
728747
}
729748

730749
static void
@@ -803,7 +822,7 @@ scan_end(struct ieee80211_scan_state *ss, int scandone)
803822
vap->iv_stats.is_scan_passive++;
804823

805824
ss->ss_ops->scan_restart(ss, vap); /* XXX? */
806-
ieee80211_runtask(ic, &ss_priv->ss_scan_task);
825+
ieee80211_runtask(ic, &ss_priv->ss_scan_start);
807826
IEEE80211_UNLOCK(ic);
808827
return;
809828
}
@@ -960,9 +979,9 @@ ieee80211_swscan_attach(struct ieee80211com *ic)
960979
ic->ic_scan = NULL;
961980
return;
962981
}
963-
callout_init_mtx(&ss->ss_scan_timer, IEEE80211_LOCK_OBJ(ic), 0);
964-
cv_init(&ss->ss_scan_cv, "scan");
965-
TASK_INIT(&ss->ss_scan_task, 0, scan_task, ss);
982+
TASK_INIT(&ss->ss_scan_start, 0, scan_start, ss);
983+
TIMEOUT_TASK_INIT(ic->ic_tq, &ss->ss_scan_curchan, 0,
984+
scan_curchan_task, ss);
966985

967986
ic->ic_scan = &ss->base;
968987
ss->base.ss_ic = ic;

0 commit comments

Comments
 (0)
0