diff options
| -rw-r--r-- | package/madwifi/patches/415-chan_switch.patch | 187 | 
1 files changed, 187 insertions, 0 deletions
diff --git a/package/madwifi/patches/415-chan_switch.patch b/package/madwifi/patches/415-chan_switch.patch new file mode 100644 index 000000000..85050647c --- /dev/null +++ b/package/madwifi/patches/415-chan_switch.patch @@ -0,0 +1,187 @@ +--- 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) +@@ -4625,7 +4597,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;  | 
