Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 2 Dec 2005 22:36:03 GMT
From:      Sam Leffler <sam@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 87660 for review
Message-ID:  <200512022236.jB2Ma3sw090019@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=87660

Change 87660 by sam@sam_ebb on 2005/12/02 22:35:47

	cleanups for setting channel:
	o when checking for an 11g channel upgrade search the entire
	  table instead of assuming b channels are sorted before g
	o set ic_curchan for monitor+wds modes since the INIT -> RUN
	  transition starts operation on that channel and not the
	  desired channel (which may not be set)
	o break out channel set code; it's large enough now

Affected files ...

.. //depot/projects/wifi/sys/net80211/ieee80211_ioctl.c#55 edit

Differences ...

==== //depot/projects/wifi/sys/net80211/ieee80211_ioctl.c#55 (text+ko) ====

@@ -1350,10 +1350,19 @@
 }
 
 static int
-find11gchannel(struct ieee80211com *ic, int i, int freq)
+find11gchannel(struct ieee80211com *ic, int start, int freq)
 {
-	for (; i < ic->ic_nchans; i++) {
-		const struct ieee80211_channel *c = &ic->ic_channels[i];
+	const struct ieee80211_channel *c;
+	int i;
+
+	for (i = start+1; i < ic->ic_nchans; i++) {
+		c = &ic->ic_channels[i];
+		if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
+			return 1;
+	}
+	/* NB: should not be needed but in case things are mis-sorted */
+	for (i = 0; i < start; i++) {
+		c = &ic->ic_channels[i];
 		if (c->ic_freq == freq && IEEE80211_IS_CHAN_ANYG(c))
 			return 1;
 	}
@@ -1391,7 +1400,7 @@
 			 *     are present.
 			 */
 			if (!IEEE80211_IS_CHAN_B(c) ||
-			    !find11gchannel(ic, i+1, c->ic_freq))
+			    !find11gchannel(ic, i, c->ic_freq))
 				return c;
 		} else {
 			if ((c->ic_flags & modeflags) == modeflags)
@@ -1413,16 +1422,94 @@
 		return (IEEE80211_IS_CHAN_ANYG(c));
 	case IEEE80211_MODE_11A:
 		return (IEEE80211_IS_CHAN_A(c));
-#ifdef	IEEE80211_MODE_TURBO_STATIC_A
-	case IEEE80211_MODE_TURBO_STATIC_A:
-		return (IEEE80211_IS_CHAN_A(c) && IEEE80211_IS_CHAN_STURBO(c));
-#endif
+	case IEEE80211_MODE_STURBO_A:
+		return (IEEE80211_IS_CHAN_STURBO(c));
 	}
 	return 1;
 
 }
 
 static int
+ieee80211_ioctl_setchannel(struct ieee80211com *ic,
+	const struct ieee80211req *ireq)
+{
+	int error;
+
+	/* XXX 0xffff overflows 16-bit signed */
+	if (ireq->i_val == 0 ||
+	    ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) {
+		ic->ic_des_chan = IEEE80211_CHAN_ANYC;
+	} else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX) {
+		return EINVAL;
+	} else {
+		struct ieee80211_channel *c, *c2;
+
+		c = findchannel(ic, ireq->i_val, ic->ic_des_mode);
+		if (c == NULL) {
+			c = findchannel(ic, ireq->i_val,
+				IEEE80211_MODE_AUTO);
+			if (c == NULL)
+				return EINVAL;
+		}
+		/*
+		 * Fine tune channel selection based on desired mode:
+		 *   if 11b is requested, find the 11b version of any
+		 *      11g channel returned,
+		 *   if static turbo, find the turbo version of any
+		 *	11a channel return,
+		 *   otherwise we should be ok with what we've got.
+		 */
+		switch (ic->ic_des_mode) {
+		case IEEE80211_MODE_11B:
+			if (IEEE80211_IS_CHAN_ANYG(c)) {
+				c2 = findchannel(ic, ireq->i_val,
+					IEEE80211_MODE_11B);
+				/* NB: should not happen, =>'s 11g w/o 11b */
+				if (c2 != NULL)
+					c = c2;
+			}
+			break;
+		case IEEE80211_MODE_TURBO_A:
+			if (IEEE80211_IS_CHAN_A(c)) {
+				c2 = findchannel(ic, ireq->i_val,
+					IEEE80211_MODE_TURBO_A);
+				if (c2 != NULL)
+					c = c2;
+			}
+			break;
+		default:		/* NB: no static turboG */
+			break;
+		}
+		if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
+		    !check_mode_consistency(c, ic->ic_des_mode))
+			return EINVAL;
+		if (ic->ic_state == IEEE80211_S_RUN && c == ic->ic_bsschan)
+			return 0;	/* NB: nothing to do */
+		ic->ic_des_chan = c;
+	}
+	error = 0;
+	if ((ic->ic_opmode == IEEE80211_M_MONITOR ||
+	    ic->ic_opmode == IEEE80211_M_WDS) &&
+	    ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
+		/*
+		 * Monitor and wds modes can switch directly.
+		 */
+		ic->ic_curchan = ic->ic_des_chan;
+		if (ic->ic_state == IEEE80211_S_RUN)
+			ic->ic_set_channel(ic);
+	} else {
+		/*
+		 * Need to go through the state machine in case we
+		 * need to reassociate or the like.  The state machine
+		 * will pickup the desired channel and avoid scanning.
+		 */
+		if (IS_UP_AUTO(ic))
+			error = ieee80211_init(ic, RESCAN);
+	}
+	return error;
+}
+
+static int
 ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211req *ireq)
 {
 	static const u_int8_t zerobssid[IEEE80211_ADDR_LEN];
@@ -1547,78 +1634,7 @@
 			error = ieee80211_init(ic, RESCAN);
 		break;
 	case IEEE80211_IOC_CHANNEL:
-		/* XXX 0xffff overflows 16-bit signed */
-		if (ireq->i_val == 0 ||
-		    ireq->i_val == (int16_t) IEEE80211_CHAN_ANY) {
-			ic->ic_des_chan = IEEE80211_CHAN_ANYC;
-		} else if ((u_int) ireq->i_val > IEEE80211_CHAN_MAX) {
-			return EINVAL;
-		} else {
-			struct ieee80211_channel *c, *c2;
-
-			c = findchannel(ic, ireq->i_val, ic->ic_des_mode);
-			if (c == NULL) {
-				c = findchannel(ic, ireq->i_val,
-					IEEE80211_MODE_AUTO);
-				if (c == NULL)
-					return EINVAL;
-			}
-			/*
-			 * Fine tune channel selection based on desired mode:
-			 *   if 11b is requested, find the 11b version of any
-			 *      11g channel returned,
-			 *   if static turbo, find the turbo version of any
-			 *	11a channel return,
-			 *   otherwise we should be ok with what we've got.
-			 */
-			switch (ic->ic_des_mode) {
-			case IEEE80211_MODE_11B:
-				if (IEEE80211_IS_CHAN_ANYG(c)) {
-					c2 = findchannel(ic, ireq->i_val,
-						IEEE80211_MODE_11B);
-					/* NB: should not happen, =>'s 11g w/o 11b */
-					if (c2 != NULL)
-						c = c2;
-				}
-				break;
-			case IEEE80211_MODE_TURBO_A:
-				if (IEEE80211_IS_CHAN_A(c)) {
-					c2 = findchannel(ic, ireq->i_val,
-						IEEE80211_MODE_TURBO_A);
-					if (c2 != NULL)
-						c = c2;
-				}
-				break;
-			default:		/* NB: no static turboG */
-				break;
-			}
-			if (ic->ic_opmode == IEEE80211_M_HOSTAP &&
-			    !check_mode_consistency(c, ic->ic_des_mode))
-				return EINVAL;
-			if (ic->ic_state == IEEE80211_S_RUN &&
-			    c == ic->ic_bsschan)
-				break;
-			ic->ic_des_chan = c;
-		}
-		if ((ic->ic_opmode == IEEE80211_M_MONITOR ||
-		    ic->ic_opmode == IEEE80211_M_WDS) &&
-		    ic->ic_des_chan != IEEE80211_CHAN_ANYC) {
-			/*
-			 * Monitor and wds modes can switch directly.
-			 */
-			if (ic->ic_state == IEEE80211_S_RUN) {
-				ic->ic_curchan = ic->ic_des_chan;
-				ic->ic_set_channel(ic);
-			}
-		} else {
-			/*
-			 * Need to go through the state machine in case we
-			 * need to reassociate or the like.  The state machine
-			 * will pickup the desired channel and avoid scanning.
-			 */
-			if (IS_UP_AUTO(ic))
-				error = ieee80211_init(ic, RESCAN);
-		}
+		error = ieee80211_ioctl_setchannel(ic, ireq);
 		break;
 	case IEEE80211_IOC_POWERSAVE:
 		switch (ireq->i_val) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200512022236.jB2Ma3sw090019>