188 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			188 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
--- a/net80211/ieee80211_beacon.c
 | 
						|
+++ b/net80211/ieee80211_beacon.c
 | 
						|
@@ -224,18 +224,18 @@ ieee80211_beacon_alloc(struct ieee80211_
 | 
						|
 	pktlen = 8					/* time stamp */
 | 
						|
 		 + sizeof(u_int16_t)			/* beacon interval */
 | 
						|
 		 + sizeof(u_int16_t)			/* capability information */
 | 
						|
-		 + 2 + ni->ni_esslen			/* ssid */
 | 
						|
+		 + 2 + IEEE80211_NWID_LEN			/* ssid */
 | 
						|
 		 + 2 + IEEE80211_RATE_SIZE		/* supported rates */
 | 
						|
 		 + 7 					/* FH/DS parameters max(7,3) */
 | 
						|
-		 + 2 + 4 + vap->iv_tim_len		/* IBSS/TIM parameter set*/
 | 
						|
+		 + sizeof(struct ieee80211_tim_ie) + 128 /* IBSS/TIM parameter set*/
 | 
						|
 		 + ic->ic_country_ie.country_len + 2	/* country code */
 | 
						|
 		 + 3					/* power constraint */
 | 
						|
 		 + 5					/* channel switch announcement */
 | 
						|
 		 + 3					/* ERP */
 | 
						|
 		 + 2 + (IEEE80211_RATE_MAXSIZE - IEEE80211_RATE_SIZE) /* Ext. Supp. Rates */
 | 
						|
-		 + (vap->iv_caps & IEEE80211_C_WME ?	/* WME */
 | 
						|
+		 + (ic->ic_caps & IEEE80211_C_WME ?	/* WME */
 | 
						|
 			sizeof(struct ieee80211_wme_param) : 0)
 | 
						|
-		 + (vap->iv_caps & IEEE80211_C_WPA ?	/* WPA 1+2 */
 | 
						|
+		 + (ic->ic_caps & IEEE80211_C_WPA ?	/* WPA 1+2 */
 | 
						|
 			2 * sizeof(struct ieee80211_ie_wpa) : 0)
 | 
						|
 		 + sizeof(struct ieee80211_ie_athAdvCap)
 | 
						|
 #ifdef ATH_SUPERG_XR
 | 
						|
@@ -290,17 +290,26 @@ ieee80211_beacon_update(struct ieee80211
 | 
						|
 	IEEE80211_LOCK_IRQ(ic);
 | 
						|
 
 | 
						|
 	/* Check if we need to change channel right now */
 | 
						|
-	if ((ic->ic_flags & IEEE80211_F_DOTH) &&
 | 
						|
-	    (vap->iv_flags & IEEE80211_F_CHANSWITCH)) {
 | 
						|
-		struct ieee80211_channel *c = 
 | 
						|
+	if (ic->ic_flags & IEEE80211_F_CHANSWITCH) {
 | 
						|
+		struct ieee80211_channel *c =
 | 
						|
 			ieee80211_doth_findchan(vap, ic->ic_chanchange_chan);
 | 
						|
-		
 | 
						|
-		if (!vap->iv_chanchange_count && !c) {
 | 
						|
-			vap->iv_flags &= ~IEEE80211_F_CHANSWITCH;
 | 
						|
-			ic->ic_flags &= ~IEEE80211_F_CHANSWITCH;
 | 
						|
-		} else if (vap->iv_chanchange_count &&
 | 
						|
-			   ((!ic->ic_chanchange_tbtt) ||
 | 
						|
-			    (vap->iv_chanchange_count == ic->ic_chanchange_tbtt))) {
 | 
						|
+		struct ieee80211vap *avp;
 | 
						|
+		int do_switch = 1;
 | 
						|
+
 | 
						|
+		TAILQ_FOREACH(avp, &ic->ic_vaps, iv_next) {
 | 
						|
+			if (!(avp->iv_flags & IEEE80211_F_CHANSWITCH))
 | 
						|
+				continue;
 | 
						|
+
 | 
						|
+			do_switch = 0;
 | 
						|
+			break;
 | 
						|
+		}
 | 
						|
+		if (vap->iv_flags & IEEE80211_F_CHANSWITCH) {
 | 
						|
+			if (vap->iv_chanchange_count-- <= 1) {
 | 
						|
+				vap->iv_flags &= ~IEEE80211_F_CHANSWITCH;
 | 
						|
+				vap->iv_chanchange_count = 0;
 | 
						|
+			}
 | 
						|
+		}
 | 
						|
+		if (do_switch) {
 | 
						|
 			u_int8_t *frm;
 | 
						|
 
 | 
						|
 			IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
 | 
						|
@@ -316,16 +325,7 @@ ieee80211_beacon_update(struct ieee80211
 | 
						|
 			} else
 | 
						|
 				ic->ic_bsschan = c;
 | 
						|
 
 | 
						|
-			skb_pull(skb, sizeof(struct ieee80211_frame));
 | 
						|
-			skb_trim(skb, 0);
 | 
						|
-			frm = skb->data;
 | 
						|
-			skb_put(skb, ieee80211_beacon_init(ni, bo, frm) - frm);
 | 
						|
-			skb_push(skb, sizeof(struct ieee80211_frame));
 | 
						|
-
 | 
						|
-			vap->iv_chanchange_count = 0;
 | 
						|
-			vap->iv_flags &= ~IEEE80211_F_CHANSWITCH;
 | 
						|
 			ic->ic_flags &= ~IEEE80211_F_CHANSWITCH;
 | 
						|
-
 | 
						|
 			/* NB: Only for the first VAP to get here, and when we
 | 
						|
 			 * have a valid channel to which to change. */
 | 
						|
 			if (c && (ic->ic_curchan != c)) {
 | 
						|
@@ -488,22 +488,20 @@ ieee80211_beacon_update(struct ieee80211
 | 
						|
 
 | 
						|
 	if (IEEE80211_IS_MODE_BEACON(vap->iv_opmode)) {
 | 
						|
 
 | 
						|
-		if ((ic->ic_flags & IEEE80211_F_DOTH) &&
 | 
						|
-		    (ic->ic_flags & IEEE80211_F_CHANSWITCH)) {
 | 
						|
+		if (ic->ic_flags & IEEE80211_F_CHANSWITCH) {
 | 
						|
 			struct ieee80211_ie_csa *csa_ie =
 | 
						|
 				(struct ieee80211_ie_csa *)bo->bo_chanswitch;
 | 
						|
 
 | 
						|
-			IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH, 
 | 
						|
+			if (csa_ie->csa_len == 0) {
 | 
						|
+				IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
 | 
						|
 					"%s: Sending 802.11h chanswitch IE: "
 | 
						|
 					"%d/%d\n", __func__, 
 | 
						|
 					ic->ic_chanchange_chan, 
 | 
						|
 					ic->ic_chanchange_tbtt);
 | 
						|
-			if (!vap->iv_chanchange_count) {
 | 
						|
-				vap->iv_flags |= IEEE80211_F_CHANSWITCH;
 | 
						|
 
 | 
						|
 				/* copy out trailer to open up a slot */
 | 
						|
 				memmove(bo->bo_chanswitch + sizeof(*csa_ie),
 | 
						|
-					bo->bo_chanswitch, 
 | 
						|
+					bo->bo_chanswitch,
 | 
						|
 					bo->bo_chanswitch_trailerlen);
 | 
						|
 
 | 
						|
 				/* add ie in opened slot */
 | 
						|
@@ -523,17 +521,15 @@ ieee80211_beacon_update(struct ieee80211
 | 
						|
 				bo->bo_ath_caps += sizeof(*csa_ie);
 | 
						|
 				bo->bo_xr += sizeof(*csa_ie);
 | 
						|
 
 | 
						|
-				/* indicate new beacon length so other layers 
 | 
						|
+				/* indicate new beacon length so other layers
 | 
						|
 				 * may manage memory */
 | 
						|
 				skb_put(skb, sizeof(*csa_ie));
 | 
						|
 				len_changed = 1;
 | 
						|
-			} else if(csa_ie->csa_count)
 | 
						|
-				csa_ie->csa_count--;
 | 
						|
-			
 | 
						|
-			vap->iv_chanchange_count++;
 | 
						|
-			IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
 | 
						|
-				"%s: CHANSWITCH IE, change in %d TBTT\n",
 | 
						|
-				__func__, csa_ie->csa_count);
 | 
						|
+
 | 
						|
+				IEEE80211_DPRINTF(vap, IEEE80211_MSG_DOTH,
 | 
						|
+					"%s: CHANSWITCH IE, change in %d TBTT\n",
 | 
						|
+					__func__, csa_ie->csa_count);
 | 
						|
+			}
 | 
						|
 		}
 | 
						|
 #ifdef ATH_SUPERG_XR
 | 
						|
 		if (vap->iv_flags & IEEE80211_F_XRUPDATE) {
 | 
						|
--- a/net80211/ieee80211_wireless.c
 | 
						|
+++ b/net80211/ieee80211_wireless.c
 | 
						|
@@ -699,39 +699,11 @@ ieee80211_ioctl_siwfreq(struct net_devic
 | 
						|
 			if (c == NULL)			/* no channel */
 | 
						|
 				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 (vap->iv_des_mode) {
 | 
						|
-		case IEEE80211_MODE_11B:
 | 
						|
-			if (IEEE80211_IS_CHAN_ANYG(c)) {
 | 
						|
-				c2 = findchannel(ic, i, 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, i, IEEE80211_MODE_TURBO_A);
 | 
						|
-				if (c2 != NULL)
 | 
						|
-					c = c2;
 | 
						|
-			}
 | 
						|
-			break;
 | 
						|
-		default:		/* NB: no static turboG */
 | 
						|
-			break;
 | 
						|
-		}
 | 
						|
+
 | 
						|
 		if (ieee80211_check_mode_consistency(ic, vap->iv_des_mode, c)) {
 | 
						|
 			if (vap->iv_opmode == IEEE80211_M_HOSTAP)
 | 
						|
 				return -EINVAL;
 | 
						|
 		}
 | 
						|
-		if ((vap->iv_state == IEEE80211_S_RUN) && (c == vap->iv_des_chan))
 | 
						|
-			return 0;			/* no change, return */
 | 
						|
 
 | 
						|
 		/* Don't allow to change to channel with radar found */
 | 
						|
 		if (c->ic_flags & IEEE80211_CHAN_RADAR)
 | 
						|
@@ -4634,7 +4606,13 @@ static void
 | 
						|
 pre_announced_chanswitch(struct net_device *dev, u_int32_t channel, u_int32_t tbtt) {
 | 
						|
 	struct ieee80211vap *vap = dev->priv;
 | 
						|
 	struct ieee80211com *ic = vap->iv_ic;
 | 
						|
+	struct ieee80211vap *avp;
 | 
						|
+
 | 
						|
 	/* now flag the beacon update to include the channel switch IE */
 | 
						|
+	TAILQ_FOREACH(avp, &ic->ic_vaps, iv_next) {
 | 
						|
+		avp->iv_flags |= IEEE80211_F_CHANSWITCH;
 | 
						|
+		avp->iv_chanchange_count = tbtt;
 | 
						|
+	}
 | 
						|
 	ic->ic_flags |= IEEE80211_F_CHANSWITCH;
 | 
						|
 	ic->ic_chanchange_chan = channel;
 | 
						|
 	ic->ic_chanchange_tbtt = tbtt;
 |