svn commit: r276730 - in head/sys: conf modules/wlan net80211

Adrian Chadd adrian at FreeBSD.org
Tue Jan 6 02:08:47 UTC 2015


Author: adrian
Date: Tue Jan  6 02:08:45 2015
New Revision: 276730
URL: https://svnweb.freebsd.org/changeset/base/276730

Log:
  Refactor and split out the net80211 software scan engine from the rest
  of the scan API.
  
  The eventual aim is to have 'ieee80211_scan.c' have the net80211 and
  driver facing scan API to start, finish and continue doing scanning
  while 'ieee80211_swscan.c' implements the software scanner that
  runs the scan task, handles probe request/reply bits, configures
  the VAP off-channel, changes channel and does the scanning bits.
  
  For NICs that do no scanning at all, the existing code is needed.
  ath(4) and most of the other NICs (dumb USB ones in particular)
  do little to no scan offload - it's all done in software.
  
  Some NICs may do single channel at a time scanning; I haven't really
  checked them out in detail.
  
  iwn(4), the upcoming 7260 driver stuff, the new Qualcomm Atheros
  11ac chipsets and the Atheros mobile/USB full-offload chips all
  have complete scan engines in firmware.  We don't have to drive
  any of it at all - the firmware just needs to be told what to scan,
  when to scan, how long to scan.  It'll take care of going off
  channel, pausing TX/RX appropriately, sending sleep notification
  to the AP, sending probe requests and handling probe responses.
  It'll do passive/active scan itself.  It's almost completely
  transparent to the network stack - all we see are scan notifications
  when it finishes scanning each channel and beacons/probe responses
  when it does its thing.  Once it's done we get a final notification
  that the scan is complete, with some scan results in the message.
  The iwn(4) NICs handle doing active scanning too as an option
  and will handle waiting appropriately on 5GHz passive channels
  before active scanning.
  
  There's some more refactoring, tidying up and lock assertions to
  sprinkle around to tidy this whole thing up before I turn swscan.c
  into another set of ic methods to override by the driver or
  alternate scan module.  So in theory this is all one big no-op
  commit.  In theory.
  
  Tested:
  
  * iwn(4) 5200, STA mode
  * ath(4) 6205, STA mode
  * ath(4) - various NICs, AP mode

Added:
  head/sys/net80211/ieee80211_scan_sw.c
     - copied, changed from r276517, head/sys/net80211/ieee80211_scan.c
  head/sys/net80211/ieee80211_scan_sw.h   (contents, props changed)
Modified:
  head/sys/conf/files
  head/sys/modules/wlan/Makefile
  head/sys/net80211/ieee80211_scan.c
  head/sys/net80211/ieee80211_scan.h

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Tue Jan  6 01:30:32 2015	(r276729)
+++ head/sys/conf/files	Tue Jan  6 02:08:45 2015	(r276730)
@@ -3316,6 +3316,7 @@ net80211/ieee80211_scan_sta.c	optional w
 net80211/ieee80211_sta.c	optional wlan \
 	compile-with "${NORMAL_C} -Wno-unused-function"
 net80211/ieee80211_superg.c	optional wlan ieee80211_support_superg
+net80211/ieee80211_swscan.c	optional wlan
 net80211/ieee80211_tdma.c	optional wlan ieee80211_support_tdma
 net80211/ieee80211_wds.c	optional wlan
 net80211/ieee80211_xauth.c	optional wlan wlan_xauth

Modified: head/sys/modules/wlan/Makefile
==============================================================================
--- head/sys/modules/wlan/Makefile	Tue Jan  6 01:30:32 2015	(r276729)
+++ head/sys/modules/wlan/Makefile	Tue Jan  6 02:08:45 2015	(r276730)
@@ -7,7 +7,7 @@ SRCS=	ieee80211.c ieee80211_action.c iee
 	ieee80211_crypto.c ieee80211_crypto_none.c ieee80211_dfs.c \
 	ieee80211_freebsd.c ieee80211_input.c ieee80211_ioctl.c \
 	ieee80211_mesh.c ieee80211_node.c ieee80211_output.c ieee80211_phy.c \
-	ieee80211_power.c ieee80211_proto.c ieee80211_scan.c \
+	ieee80211_power.c ieee80211_proto.c ieee80211_scan.c ieee80211_scan_sw.c \
 	ieee80211_scan_sta.c ieee80211_radiotap.c ieee80211_ratectl.c \
 	ieee80211_ratectl_none.c ieee80211_regdomain.c \
 	ieee80211_ht.c ieee80211_hwmp.c ieee80211_adhoc.c ieee80211_hostap.c \

Modified: head/sys/net80211/ieee80211_scan.c
==============================================================================
--- head/sys/net80211/ieee80211_scan.c	Tue Jan  6 01:30:32 2015	(r276729)
+++ head/sys/net80211/ieee80211_scan.c	Tue Jan  6 02:08:45 2015	(r276730)
@@ -46,35 +46,10 @@ __FBSDID("$FreeBSD$");
 
 #include <net80211/ieee80211_var.h>
 
-#include <net/bpf.h>
-
-struct scan_state {
-	struct ieee80211_scan_state base;	/* public state */
-
-	u_int		ss_iflags;		/* flags used internally */
-#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_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)
+/* XXX until it's implemented as attach ops */
+#include <net80211/ieee80211_scan_sw.h>
 
-/*
- * Amount of time to go off-channel during a background
- * scan.  This value should be large enough to catch most
- * ap's but short enough that we can return on-channel
- * before our listen interval expires.
- *
- * XXX tunable
- * XXX check against configured listen interval
- */
-#define	IEEE80211_SCAN_OFFCHANNEL	msecs_to_ticks(150)
+#include <net/bpf.h>
 
 /*
  * Roaming-related defaults.  RSSI thresholds are as returned by the
@@ -93,55 +68,32 @@ 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_curchan(struct ieee80211_scan_state *, unsigned long);
-static	void scan_mindwell(struct ieee80211_scan_state *);
-static	void scan_signal(void *);
-static	void scan_task(void *, int);
-
-MALLOC_DEFINE(M_80211_SCAN, "80211scan", "802.11 scan state");
-
 void
 ieee80211_scan_attach(struct ieee80211com *ic)
 {
-	struct scan_state *ss;
-
-	ss = (struct scan_state *) malloc(sizeof(struct scan_state),
-		M_80211_SCAN, M_NOWAIT | M_ZERO);
-	if (ss == NULL) {
-		ic->ic_scan = NULL;
-		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;
+	/*
+	 * For now, the swscan module does both the
+	 * allocation (so it can pad it) and sets up the net80211
+	 * bits.
+	 *
+	 * I'll split this stuff later.
+	 */
+	ieee80211_swscan_attach(ic);
 }
 
 void
 ieee80211_scan_detach(struct ieee80211com *ic)
 {
-	struct ieee80211_scan_state *ss = ic->ic_scan;
 
-	if (ss != NULL) {
-		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);
-		callout_drain(&SCAN_PRIVATE(ss)->ss_scan_timer);
-		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_scan = NULL;
-		free(SCAN_PRIVATE(ss), M_80211_SCAN);
-	}
+	/*
+	 * Ideally we'd do the ss_ops detach call here;
+	 * but then ieee80211_swscan_detach would need
+	 * to be split in two.
+	 *
+	 * I'll do that later.
+	 */
+	ieee80211_swscan_detach(ic);
 }
 
 static const struct ieee80211_roamparam defroam[IEEE80211_MODE_MAX] = {
@@ -176,6 +128,8 @@ ieee80211_scan_vattach(struct ieee80211v
 
 	vap->iv_roaming = IEEE80211_ROAMING_AUTO;
 	memcpy(vap->iv_roamparms, defroam, sizeof(defroam));
+
+	ieee80211_swscan_vattach(vap);
 }
 
 void
@@ -186,11 +140,10 @@ ieee80211_scan_vdetach(struct ieee80211v
 
 	IEEE80211_LOCK(ic);
 	ss = ic->ic_scan;
+
+	ieee80211_swscan_vdetach(vap);
+
 	if (ss != NULL && ss->ss_vap == vap) {
-		if (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);
 			ss->ss_ops = NULL;
@@ -261,8 +214,8 @@ ieee80211_scanner_unregister_all(const s
  * ensure later callbacks find ss_ops set to properly
  * reflect current operating mode.
  */
-static void
-scan_update_locked(struct ieee80211vap *vap,
+void
+ieee80211_scan_update_locked(struct ieee80211vap *vap,
 	const struct ieee80211_scanner *scan)
 {
 	struct ieee80211com *ic = vap->iv_ic;
@@ -307,6 +260,9 @@ scan_update_locked(struct ieee80211vap *
 	}
 }
 
+/*
+ * XXX TODO: should be a global method!
+ */
 static char
 channel_type(const struct ieee80211_channel *c)
 {
@@ -345,8 +301,8 @@ ieee80211_scan_dump_channels(const struc
 }
 
 #ifdef IEEE80211_DEBUG
-static void
-scan_dump(struct ieee80211_scan_state *ss)
+void
+ieee80211_scan_dump(struct ieee80211_scan_state *ss)
 {
 	struct ieee80211vap *vap = ss->ss_vap;
 
@@ -357,8 +313,8 @@ scan_dump(struct ieee80211_scan_state *s
 }
 #endif /* IEEE80211_DEBUG */
 
-static void
-copy_ssid(struct ieee80211vap *vap, struct ieee80211_scan_state *ss,
+void
+ieee80211_scan_copy_ssid(struct ieee80211vap *vap, struct ieee80211_scan_state *ss,
 	int nssid, const struct ieee80211_scan_ssid ssids[])
 {
 	if (nssid > IEEE80211_SCAN_MAX_SSID) {
@@ -375,8 +331,8 @@ copy_ssid(struct ieee80211vap *vap, stru
 /*
  * Start a scan unless one is already going.
  */
-static int
-start_scan_locked(const struct ieee80211_scanner *scan,
+int
+ieee80211_start_scan_locked(const struct ieee80211_scanner *scan,
 	struct ieee80211vap *vap, int flags, u_int duration,
 	u_int mindwell, u_int maxdwell,
 	u_int nssid, const struct ieee80211_scan_ssid ssids[])
@@ -404,10 +360,10 @@ start_scan_locked(const struct ieee80211
 		    , flags & IEEE80211_SCAN_ONCE ? ", once" : ""
 		);
 
-		scan_update_locked(vap, scan);
+		ieee80211_scan_update_locked(vap, scan);
 		if (ss->ss_ops != NULL) {
 			if ((flags & IEEE80211_SCAN_NOSSID) == 0)
-				copy_ssid(vap, ss, nssid, ssids);
+				ieee80211_scan_copy_ssid(vap, ss, nssid, ssids);
 
 			/* NB: top 4 bits for internal use */
 			ss->ss_flags = flags & 0xfff;
@@ -420,9 +376,9 @@ start_scan_locked(const struct ieee80211
 			if (flags & IEEE80211_SCAN_BGSCAN)
 				ic->ic_flags_ext |= IEEE80211_FEXT_BGSCAN;
 
-			/* NB: flush frames rx'd before 1st channel change */
-			SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD;
-			SCAN_PRIVATE(ss)->ss_duration = duration;
+			/* Set duration for this particular scan */
+			ieee80211_swscan_set_scan_duration(vap, duration);
+
 			ss->ss_next = 0;
 			ss->ss_mindwell = mindwell;
 			ss->ss_maxdwell = maxdwell;
@@ -430,10 +386,12 @@ start_scan_locked(const struct ieee80211
 			ss->ss_ops->scan_start(ss, vap);
 #ifdef IEEE80211_DEBUG
 			if (ieee80211_msg_scan(vap))
-				scan_dump(ss);
+				ieee80211_scan_dump(ss);
 #endif /* IEEE80211_DEBUG */
 			ic->ic_flags |= IEEE80211_F_SCAN;
-			ieee80211_runtask(ic, &SCAN_PRIVATE(ss)->ss_scan_task);
+
+			/* Start scan task */
+			ieee80211_swscan_run_scan_task(vap);
 		}
 		return 1;
 	} else {
@@ -452,9 +410,7 @@ ieee80211_start_scan(struct ieee80211vap
 	u_int duration, u_int mindwell, u_int maxdwell,
 	u_int nssid, const struct ieee80211_scan_ssid ssids[])
 {
-	struct ieee80211com *ic = vap->iv_ic;
 	const struct ieee80211_scanner *scan;
-	int result;
 
 	scan = ieee80211_scanner_get(vap->iv_opmode);
 	if (scan == NULL) {
@@ -465,12 +421,9 @@ ieee80211_start_scan(struct ieee80211vap
 		return 0;
 	}
 
-	IEEE80211_LOCK(ic);
-	result = start_scan_locked(scan, vap, flags, duration,
+	/* XXX ops */
+	return ieee80211_swscan_start_scan(scan, vap, flags, duration,
 	    mindwell, maxdwell, nssid, ssids);
-	IEEE80211_UNLOCK(ic);
-
-	return result;
 }
 
 /*
@@ -517,49 +470,19 @@ ieee80211_check_scan(struct ieee80211vap
 		/* XXX re-use cache contents? e.g. adhoc<->sta */
 		flags |= IEEE80211_SCAN_FLUSH;
 	}
-	scan_update_locked(vap, scan);
-	if (ss->ss_ops != NULL) {
-		/* XXX verify ss_ops matches vap->iv_opmode */
-		if ((flags & IEEE80211_SCAN_NOSSID) == 0) {
-			/*
-			 * Update the ssid list and mark flags so if
-			 * we call start_scan it doesn't duplicate work.
-			 */
-			copy_ssid(vap, ss, nssid, ssids);
-			flags |= IEEE80211_SCAN_NOSSID;
-		}
-		if ((ic->ic_flags & IEEE80211_F_SCAN) == 0 &&
-		    (flags & IEEE80211_SCAN_FLUSH) == 0 &&
-		    time_before(ticks, ic->ic_lastscan + vap->iv_scanvalid)) {
-			/*
-			 * We're not currently scanning and the cache is
-			 * deemed hot enough to consult.  Lock out others
-			 * by marking IEEE80211_F_SCAN while we decide if
-			 * something is already in the scan cache we can
-			 * use.  Also discard any frames that might come
-			 * in while temporarily marked as scanning.
-			 */
-			SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_DISCARD;
-			ic->ic_flags |= IEEE80211_F_SCAN;
 
-			/* NB: need to use supplied flags in check */
-			ss->ss_flags = flags & 0xff;
-			result = ss->ss_ops->scan_end(ss, vap);
-
-			ic->ic_flags &= ~IEEE80211_F_SCAN;
-			SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_DISCARD;
-			if (result) {
-				ieee80211_notify_scan_done(vap);
-				IEEE80211_UNLOCK(ic);
-				return 1;
-			}
-		}
-	}
-	result = start_scan_locked(scan, vap, flags, duration,
+	/*
+	 * XXX TODO: separate things out a bit better.
+	 * XXX TODO: ops
+	 */
+	ieee80211_scan_update_locked(vap, scan);
+
+	result = ieee80211_swscan_check_scan(scan, vap, flags, duration,
 	    mindwell, maxdwell, nssid, ssids);
+
 	IEEE80211_UNLOCK(ic);
 
-	return result;
+	return (result);
 }
 
 /*
@@ -582,10 +505,10 @@ ieee80211_check_scan_current(struct ieee
 int
 ieee80211_bg_scan(struct ieee80211vap *vap, int flags)
 {
-	struct ieee80211com *ic = vap->iv_ic;
-	struct ieee80211_scan_state *ss = ic->ic_scan;
 	const struct ieee80211_scanner *scan;
 
+	// IEEE80211_UNLOCK_ASSERT(sc);
+
 	scan = ieee80211_scanner_get(vap->iv_opmode);
 	if (scan == NULL) {
 		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
@@ -595,84 +518,14 @@ ieee80211_bg_scan(struct ieee80211vap *v
 		return 0;
 	}
 
-	IEEE80211_LOCK(ic);
-	if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) {
-		u_int duration;
-		/*
-		 * Go off-channel for a fixed interval that is large
-		 * enough to catch most ap's but short enough that
-		 * we can return on-channel before our listen interval
-		 * expires.
-		 */
-		duration = IEEE80211_SCAN_OFFCHANNEL;
-
-		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
-		    "%s: %s scan, ticks %u duration %lu\n", __func__,
-		    ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive",
-		    ticks, duration);
-
-		scan_update_locked(vap, scan);
-		if (ss->ss_ops != NULL) {
-			ss->ss_vap = vap;
-			/*
-			 * A background scan does not select a new sta; it
-			 * just refreshes the scan cache.  Also, indicate
-			 * the scan logic should follow the beacon schedule:
-			 * we go off-channel and scan for a while, then
-			 * return to the bss channel to receive a beacon,
-			 * then go off-channel again.  All during this time
-			 * we notify the ap we're in power save mode.  When
-			 * the scan is complete we leave power save mode.
-			 * If any beacon indicates there are frames pending
-			 * for us then we drop out of power save mode
-			 * (and background scan) automatically by way of the
-			 * usual sta power save logic.
-			 */
-			ss->ss_flags |= IEEE80211_SCAN_NOPICK
-				     |  IEEE80211_SCAN_BGSCAN
-				     |  flags
-				     ;
-			/* if previous scan completed, restart */
-			if (ss->ss_next >= ss->ss_last) {
-				if (ss->ss_flags & IEEE80211_SCAN_ACTIVE)
-					vap->iv_stats.is_scan_active++;
-				else
-					vap->iv_stats.is_scan_passive++;
-				/*
-				 * NB: beware of the scan cache being flushed;
-				 *     if the channel list is empty use the
-				 *     scan_start method to populate it.
-				 */
-				ss->ss_next = 0;
-				if (ss->ss_last != 0)
-					ss->ss_ops->scan_restart(ss, vap);
-				else {
-					ss->ss_ops->scan_start(ss, vap);
-#ifdef IEEE80211_DEBUG
-					if (ieee80211_msg_scan(vap))
-						scan_dump(ss);
-#endif /* IEEE80211_DEBUG */
-				}
-			}
-			/* 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;
-			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 */
-		}
-	} else {
-		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
-		    "%s: %s scan already in progress\n", __func__,
-		    ss->ss_flags & IEEE80211_SCAN_ACTIVE ? "active" : "passive");
-	}
-	IEEE80211_UNLOCK(ic);
-
-	/* NB: racey, does it matter? */
-	return (ic->ic_flags & IEEE80211_F_SCAN);
+	/*
+	 * XXX TODO: pull apart the bgscan logic into whatever
+	 * belongs here and whatever belongs in the software
+	 * scanner.
+	 *
+	 * XXX TODO: ops
+	 */
+	return (ieee80211_swscan_bg_scan(scan, vap, flags));
 }
 
 /*
@@ -681,32 +534,9 @@ ieee80211_bg_scan(struct ieee80211vap *v
 void
 ieee80211_cancel_scan(struct ieee80211vap *vap)
 {
-	struct ieee80211com *ic = vap->iv_ic;
-	struct ieee80211_scan_state *ss = ic->ic_scan;
 
-	IEEE80211_LOCK(ic);
-	if ((ic->ic_flags & IEEE80211_F_SCAN) &&
-	    ss->ss_vap == vap &&
-	    (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0) {
-		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
-		    "%s: cancel %s scan\n", __func__,
-		    ss->ss_flags & IEEE80211_SCAN_ACTIVE ?
-			"active" : "passive");
-
-		/* clear bg scan NOPICK and mark cancel request */
-		ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
-		SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL;
-		/* wake up the scan task */
-		scan_signal(ss);
-	} else {
-		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
-		    "%s: called; F_SCAN=%d, vap=%s, CANCEL=%d\n",
-		        __func__,
-			!! (ic->ic_flags & IEEE80211_F_SCAN),
-			(ss->ss_vap == vap ? "match" : "nomatch"),
-			!! (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL));
-	}
-	IEEE80211_UNLOCK(ic);
+	/* XXX TODO: ops */
+	ieee80211_swscan_cancel_scan(vap);
 }
 
 /*
@@ -715,31 +545,9 @@ ieee80211_cancel_scan(struct ieee80211va
 void
 ieee80211_cancel_anyscan(struct ieee80211vap *vap)
 {
-	struct ieee80211com *ic = vap->iv_ic;
-	struct ieee80211_scan_state *ss = ic->ic_scan;
 
-	IEEE80211_LOCK(ic);
-	if ((ic->ic_flags & IEEE80211_F_SCAN) &&
-	    (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) == 0) {
-		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
-		    "%s: cancel %s scan\n", __func__,
-		    ss->ss_flags & IEEE80211_SCAN_ACTIVE ?
-			"active" : "passive");
-
-		/* clear bg scan NOPICK and mark cancel request */
-		ss->ss_flags &= ~IEEE80211_SCAN_NOPICK;
-		SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_CANCEL;
-		/* wake up the scan task */
-		scan_signal(ss);
-	} else {
-		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
-		    "%s: called; F_SCAN=%d, vap=%s, CANCEL=%d\n",
-		        __func__,
-			!! (ic->ic_flags & IEEE80211_F_SCAN),
-			(ss->ss_vap == vap ? "match" : "nomatch"),
-			!! (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL));
-	}
-	IEEE80211_UNLOCK(ic);
+	/* XXX TODO: ops */
+	ieee80211_swscan_cancel_anyscan(vap);
 }
 
 /*
@@ -749,15 +557,9 @@ ieee80211_cancel_anyscan(struct ieee8021
 void
 ieee80211_scan_next(struct ieee80211vap *vap)
 {
-	struct ieee80211com *ic = vap->iv_ic;
-	struct ieee80211_scan_state *ss = ic->ic_scan;
-
-	IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: called\n", __func__);
 
-	/* wake up the scan task */
-	IEEE80211_LOCK(ic);
-	scan_signal(ss);
-	IEEE80211_UNLOCK(ic);
+	/* XXX TODO: ops */
+	ieee80211_swscan_scan_next(vap);
 }
 
 /*
@@ -775,7 +577,10 @@ ieee80211_scan_done(struct ieee80211vap 
 	IEEE80211_LOCK(ic);
 	ss = ic->ic_scan;
 	ss->ss_next = ss->ss_last; /* all channels are complete */
-	scan_signal(ss);
+
+	/* XXX TODO: ops */
+	ieee80211_swscan_scan_done(vap);
+
 	IEEE80211_UNLOCK(ic);
 }
 
@@ -790,328 +595,14 @@ void
 ieee80211_probe_curchan(struct ieee80211vap *vap, int force)
 {
 	struct ieee80211com *ic = vap->iv_ic;
-	struct ieee80211_scan_state *ss = ic->ic_scan;
-	struct ifnet *ifp = vap->iv_ifp;
-	int i;
 
 	if ((ic->ic_curchan->ic_flags & IEEE80211_CHAN_PASSIVE) && !force) {
 		ic->ic_flags_ext |= IEEE80211_FEXT_PROBECHAN;
 		return;
 	}
-	/*
-	 * Send directed probe requests followed by any
-	 * broadcast probe request.
-	 * XXX remove dependence on ic/vap->iv_bss
-	 */
-	for (i = 0; i < ss->ss_nssid; i++)
-		ieee80211_send_probereq(vap->iv_bss,
-			vap->iv_myaddr, ifp->if_broadcastaddr,
-			ifp->if_broadcastaddr,
-			ss->ss_ssid[i].ssid, ss->ss_ssid[i].len);
-	if ((ss->ss_flags & IEEE80211_SCAN_NOBCAST) == 0)
-		ieee80211_send_probereq(vap->iv_bss,
-			vap->iv_myaddr, ifp->if_broadcastaddr,
-			ifp->if_broadcastaddr,
-			"", 0);
-}
-
-/*
- * Scan curchan.  If this is an active scan and the channel
- * is not marked passive then send probe request frame(s).
- * Arrange for the channel change after maxdwell ticks.
- */
-static void
-scan_curchan(struct ieee80211_scan_state *ss, unsigned long maxdwell)
-{
-	struct ieee80211vap *vap  = ss->ss_vap;
-
-	IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
-	    "%s: calling; maxdwell=%lu\n",
-	    __func__,
-	    maxdwell);
-	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_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);
-}
-
-/*
- * Handle mindwell requirements completed; initiate a channel
- * change to the next channel asap.
- */
-static void
-scan_mindwell(struct ieee80211_scan_state *ss)
-{
-	struct ieee80211com *ic = ss->ss_ic;
-
-	IEEE80211_DPRINTF(ss->ss_vap, IEEE80211_MSG_SCAN, "%s: called\n", __func__);
-
-	IEEE80211_LOCK(ic);
-	scan_signal(ss);
-	IEEE80211_UNLOCK(ic);
-}
-
-static void
-scan_task(void *arg, int pending)
-{
-#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 = ss->ss_ic;
-	struct ieee80211_channel *chan;
-	unsigned long maxdwell, scanend;
-	int scandone = 0;
-
-	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__);
-		scandone = 1;
-		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 */
-			vap->iv_sta_ps(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;
-
-	/* XXX scan state can change! Re-validate scan state! */
-
-	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;
-
-		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
-		    "%s: loop start; scandone=%d\n",
-		    __func__,
-		    scandone);
-
-		if (scandone || (ss->ss_flags & IEEE80211_SCAN_GOTPICK) ||
-		    (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT) ||
-		     time_after(ticks + ss->ss_mindwell, scanend))
-			break;
-
-		chan = ss->ss_chans[ss->ss_next++];
-
-		/*
-		 * Watch for truncation due to the scan end time.
-		 */
-		if (time_after(ticks + ss->ss_maxdwell, scanend))
-			maxdwell = scanend - ticks;
-		else
-			maxdwell = ss->ss_maxdwell;
-
-		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
-		    "%s: chan %3d%c -> %3d%c [%s, dwell min %lums max %lums]\n",
-		    __func__,
-		    ieee80211_chan2ieee(ic, ic->ic_curchan),
-		        channel_type(ic->ic_curchan),
-		    ieee80211_chan2ieee(ic, chan), channel_type(chan),
-		    (ss->ss_flags & IEEE80211_SCAN_ACTIVE) &&
-			(chan->ic_flags & IEEE80211_CHAN_PASSIVE) == 0 ?
-			"active" : "passive",
-		    ticks_to_msecs(ss->ss_mindwell), ticks_to_msecs(maxdwell));
-
-		/*
-		 * Potentially change channel and phy mode.
-		 */
-		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);
-		ieee80211_radiotap_chan_change(ic);
-
-		/*
-		 * Scan curchan.  Drivers for "intelligent hardware"
-		 * override ic_scan_curchan to tell the device to do
-		 * 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);
-
-		/* XXX scan state can change! Re-validate scan state! */
-
-		SCAN_PRIVATE(ss)->ss_chanmindwell = ticks + ss->ss_mindwell;
-		/* clear mindwell lock and initial channel change flush */
-		SCAN_PRIVATE(ss)->ss_iflags &= ~ISCAN_REP;
-
-		if ((SCAN_PRIVATE(ss)->ss_iflags & (ISCAN_CANCEL|ISCAN_ABORT)))
-			continue;
-
-		IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: waiting\n", __func__);
-		/* Wait to be signalled to scan the next channel */
-		cv_wait(&SCAN_PRIVATE(ss)->ss_scan_cv, IEEE80211_LOCK_OBJ(ic));
-	}
-
-	IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN, "%s: out\n", __func__);
-
-	if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_ABORT)
-		goto done;
-
-	IEEE80211_UNLOCK(ic);
-	ic->ic_scan_end(ic);		/* notify driver */
-	IEEE80211_LOCK(ic);
-	/* XXX scan state can change! Re-validate scan state! */
-
-	/*
-	 * Since a cancellation may have occured during one of the
-	 * driver calls (whilst unlocked), update scandone.
-	 */
-	if (scandone == 0 &&
-	    ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0)) {
-		/* XXX printf? */
-		if_printf(vap->iv_ifp,
-		    "%s: OOPS! scan cancelled during driver call (1)!\n",
-		    __func__);
-		scandone = 1;
-	}
-
-	/*
-	 * 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_radiotap_chan_change(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);
-
-	/*
-	 * Since a cancellation may have occured during one of the
-	 * driver calls (whilst unlocked), update scandone.
-	 */
-	if (scandone == 0 &&
-	    ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_CANCEL) != 0)) {
-		/* XXX printf? */
-		if_printf(vap->iv_ifp,
-		    "%s: OOPS! scan cancelled during driver call (2)!\n",
-		    __func__);
-		scandone = 1;
-	}
-
-	/*
-	 * 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) {
-		vap->iv_sta_ps(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
+	/* XXX TODO: ops */
+	ieee80211_swscan_probe_curchan(vap, force);
 }
 
 #ifdef IEEE80211_DEBUG
@@ -1140,8 +631,8 @@ dump_country(const uint8_t *ie)
 	printf("]");
 }
 
-static void
-dump_probe_beacon(uint8_t subtype, int isnew,
+void
+ieee80211_scan_dump_probe_beacon(uint8_t subtype, int isnew,
 	const uint8_t mac[IEEE80211_ADDR_LEN],
 	const struct ieee80211_scanparams *sp, int rssi)
 {
@@ -1172,45 +663,8 @@ ieee80211_add_scan(struct ieee80211vap *
 	const struct ieee80211_frame *wh,
 	int subtype, int rssi, int noise)
 {
-	struct ieee80211com *ic = vap->iv_ic;
-	struct ieee80211_scan_state *ss = ic->ic_scan;
 
-	/* XXX locking */
-	/*
-	 * Frames received during startup are discarded to avoid
-	 * using scan state setup on the initial entry to the timer
-	 * callback.  This can occur because the device may enable
-	 * rx prior to our doing the initial channel change in the
-	 * timer routine.
-	 */
-	if (SCAN_PRIVATE(ss)->ss_iflags & ISCAN_DISCARD)
-		return;
-#ifdef IEEE80211_DEBUG
-	if (ieee80211_msg_scan(vap) && (ic->ic_flags & IEEE80211_F_SCAN))
-		dump_probe_beacon(subtype, 1, wh->i_addr2, sp, rssi);
-#endif
-	if (ss->ss_ops != NULL &&
-	    ss->ss_ops->scan_add(ss, sp, wh, subtype, rssi, noise)) {
-		/*
-		 * If we've reached the min dwell time terminate
-		 * the timer so we'll switch to the next channel.
-		 */
-		if ((SCAN_PRIVATE(ss)->ss_iflags & ISCAN_MINDWELL) == 0 &&
-		    time_after_eq(ticks, SCAN_PRIVATE(ss)->ss_chanmindwell)) {
-			IEEE80211_DPRINTF(vap, IEEE80211_MSG_SCAN,
-			    "%s: chan %3d%c min dwell met (%u > %lu)\n",
-			    __func__,
-			    ieee80211_chan2ieee(ic, ic->ic_curchan),
-				channel_type(ic->ic_curchan),
-			    ticks, SCAN_PRIVATE(ss)->ss_chanmindwell);
-			SCAN_PRIVATE(ss)->ss_iflags |= ISCAN_MINDWELL;
-			/*
-			 * NB: trigger at next clock tick or wait for the
-			 * hardware.
-			 */
-			ic->ic_scan_mindwell(ss);
-		}
-	}
+	return (ieee80211_swscan_add_scan(vap, sp, wh, subtype, rssi, noise));
 }
 
 /*

Modified: head/sys/net80211/ieee80211_scan.h
==============================================================================
--- head/sys/net80211/ieee80211_scan.h	Tue Jan  6 01:30:32 2015	(r276729)
+++ head/sys/net80211/ieee80211_scan.h	Tue Jan  6 02:08:45 2015	(r276730)
@@ -299,4 +299,18 @@ void	ieee80211_scanner_unregister(enum i
 		const struct ieee80211_scanner *);
 void	ieee80211_scanner_unregister_all(const struct ieee80211_scanner *);
 const struct ieee80211_scanner *ieee80211_scanner_get(enum ieee80211_opmode);
+void	ieee80211_scan_update_locked(struct ieee80211vap *vap,
+		const struct ieee80211_scanner *scan);
+void	ieee80211_scan_copy_ssid(struct ieee80211vap *vap,
+		struct ieee80211_scan_state *ss,
+		int nssid, const struct ieee80211_scan_ssid ssids[]);
+void	ieee80211_scan_dump_probe_beacon(uint8_t subtype, int isnew,
+		const uint8_t mac[IEEE80211_ADDR_LEN],
+		const struct ieee80211_scanparams *sp, int rssi);
+int	ieee80211_start_scan_locked(const struct ieee80211_scanner *scan,
+	struct ieee80211vap *vap, int flags, u_int duration,
+	u_int mindwell, u_int maxdwell,
+	u_int nssid, const struct ieee80211_scan_ssid ssids[]);
+void	ieee80211_scan_dump(struct ieee80211_scan_state *ss);
+
 #endif /* _NET80211_IEEE80211_SCAN_H_ */

Copied and modified: head/sys/net80211/ieee80211_scan_sw.c (from r276517, head/sys/net80211/ieee80211_scan.c)
==============================================================================
--- head/sys/net80211/ieee80211_scan.c	Thu Jan  1 22:49:17 2015	(r276517, copy source)
+++ head/sys/net80211/ieee80211_scan_sw.c	Tue Jan  6 02:08:45 2015	(r276730)
@@ -46,6 +46,8 @@ __FBSDID("$FreeBSD$");
 
 #include <net80211/ieee80211_var.h>
 
+#include <net80211/ieee80211_scan_sw.h>
+
 #include <net/bpf.h>
 
 struct scan_state {
@@ -101,7 +103,7 @@ static	void scan_task(void *, int);
 MALLOC_DEFINE(M_80211_SCAN, "80211scan", "802.11 scan state");
 
 void
-ieee80211_scan_attach(struct ieee80211com *ic)
+ieee80211_swscan_attach(struct ieee80211com *ic)
 {
 	struct scan_state *ss;
 
@@ -114,15 +116,20 @@ ieee80211_scan_attach(struct ieee80211co
 	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;
+
+	/*
+	 * TODO: all of the non-vap scan calls should be methods!
+	 */
 }
 
 void
-ieee80211_scan_detach(struct ieee80211com *ic)
+ieee80211_swscan_detach(struct ieee80211com *ic)
 {
 	struct ieee80211_scan_state *ss = ic->ic_scan;
 
@@ -135,6 +142,14 @@ ieee80211_scan_detach(struct ieee80211co
 		callout_drain(&SCAN_PRIVATE(ss)->ss_scan_timer);
 		KASSERT((ic->ic_flags & IEEE80211_F_SCAN) == 0,
 		    ("scan still running"));
+
+		/*

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list