1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
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)
@@ -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;
|