Commit d51b70ff5122d31e27733ba03c3afd62bb86bd63
Committed by
Johannes Berg
1 parent
86c228a762
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
mac80211: move ibss presp generation in own function
Channel Switch will later require to generate beacons without setting them immediately. Therefore split the presp generation in an own function. Splitting the original very long function might be a good idea anyway. Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de> Signed-off-by: Mathias Kretschmer <mathias.kretschmer@fokus.fraunhofer.de> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Showing 1 changed file with 109 additions and 76 deletions Side-by-side Diff
net/mac80211/ibss.c
... | ... | @@ -34,13 +34,12 @@ |
34 | 34 | |
35 | 35 | #define IEEE80211_IBSS_MAX_STA_ENTRIES 128 |
36 | 36 | |
37 | - | |
38 | -static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |
39 | - const u8 *bssid, const int beacon_int, | |
40 | - struct ieee80211_channel *chan, | |
41 | - const u32 basic_rates, | |
42 | - const u16 capability, u64 tsf, | |
43 | - bool creator) | |
37 | +static struct beacon_data * | |
38 | +ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata, | |
39 | + const int beacon_int, const u32 basic_rates, | |
40 | + const u16 capability, u64 tsf, | |
41 | + struct cfg80211_chan_def *chandef, | |
42 | + bool *have_higher_than_11mbit) | |
44 | 43 | { |
45 | 44 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
46 | 45 | struct ieee80211_local *local = sdata->local; |
47 | 46 | |
... | ... | @@ -48,70 +47,11 @@ |
48 | 47 | struct ieee80211_mgmt *mgmt; |
49 | 48 | u8 *pos; |
50 | 49 | struct ieee80211_supported_band *sband; |
51 | - struct cfg80211_bss *bss; | |
52 | - u32 bss_change, rate_flags, rates = 0, rates_added = 0; | |
53 | - struct cfg80211_chan_def chandef; | |
54 | - enum nl80211_bss_scan_width scan_width; | |
55 | - bool have_higher_than_11mbit = false; | |
50 | + u32 rate_flags, rates = 0, rates_added = 0; | |
56 | 51 | struct beacon_data *presp; |
57 | 52 | int frame_len; |
58 | 53 | int shift; |
59 | 54 | |
60 | - sdata_assert_lock(sdata); | |
61 | - | |
62 | - /* Reset own TSF to allow time synchronization work. */ | |
63 | - drv_reset_tsf(local, sdata); | |
64 | - | |
65 | - if (!ether_addr_equal(ifibss->bssid, bssid)) | |
66 | - sta_info_flush(sdata); | |
67 | - | |
68 | - /* if merging, indicate to driver that we leave the old IBSS */ | |
69 | - if (sdata->vif.bss_conf.ibss_joined) { | |
70 | - sdata->vif.bss_conf.ibss_joined = false; | |
71 | - sdata->vif.bss_conf.ibss_creator = false; | |
72 | - sdata->vif.bss_conf.enable_beacon = false; | |
73 | - netif_carrier_off(sdata->dev); | |
74 | - ieee80211_bss_info_change_notify(sdata, | |
75 | - BSS_CHANGED_IBSS | | |
76 | - BSS_CHANGED_BEACON_ENABLED); | |
77 | - } | |
78 | - | |
79 | - presp = rcu_dereference_protected(ifibss->presp, | |
80 | - lockdep_is_held(&sdata->wdev.mtx)); | |
81 | - rcu_assign_pointer(ifibss->presp, NULL); | |
82 | - if (presp) | |
83 | - kfree_rcu(presp, rcu_head); | |
84 | - | |
85 | - sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; | |
86 | - | |
87 | - chandef = ifibss->chandef; | |
88 | - if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) { | |
89 | - if (chandef.width == NL80211_CHAN_WIDTH_5 || | |
90 | - chandef.width == NL80211_CHAN_WIDTH_10 || | |
91 | - chandef.width == NL80211_CHAN_WIDTH_20_NOHT || | |
92 | - chandef.width == NL80211_CHAN_WIDTH_20) { | |
93 | - sdata_info(sdata, | |
94 | - "Failed to join IBSS, beacons forbidden\n"); | |
95 | - return; | |
96 | - } | |
97 | - chandef.width = NL80211_CHAN_WIDTH_20; | |
98 | - chandef.center_freq1 = chan->center_freq; | |
99 | - } | |
100 | - | |
101 | - ieee80211_vif_release_channel(sdata); | |
102 | - if (ieee80211_vif_use_channel(sdata, &chandef, | |
103 | - ifibss->fixed_channel ? | |
104 | - IEEE80211_CHANCTX_SHARED : | |
105 | - IEEE80211_CHANCTX_EXCLUSIVE)) { | |
106 | - sdata_info(sdata, "Failed to join IBSS, no channel context\n"); | |
107 | - return; | |
108 | - } | |
109 | - | |
110 | - memcpy(ifibss->bssid, bssid, ETH_ALEN); | |
111 | - | |
112 | - sband = local->hw.wiphy->bands[chan->band]; | |
113 | - shift = ieee80211_vif_get_shift(&sdata->vif); | |
114 | - | |
115 | 55 | /* Build IBSS probe response */ |
116 | 56 | frame_len = sizeof(struct ieee80211_hdr_3addr) + |
117 | 57 | 12 /* struct ieee80211_mgmt.u.beacon */ + |
... | ... | @@ -125,7 +65,7 @@ |
125 | 65 | ifibss->ie_len; |
126 | 66 | presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL); |
127 | 67 | if (!presp) |
128 | - return; | |
68 | + return NULL; | |
129 | 69 | |
130 | 70 | presp->head = (void *)(presp + 1); |
131 | 71 | |
132 | 72 | |
... | ... | @@ -146,12 +86,19 @@ |
146 | 86 | memcpy(pos, ifibss->ssid, ifibss->ssid_len); |
147 | 87 | pos += ifibss->ssid_len; |
148 | 88 | |
149 | - rate_flags = ieee80211_chandef_rate_flags(&chandef); | |
89 | + sband = local->hw.wiphy->bands[chandef->chan->band]; | |
90 | + rate_flags = ieee80211_chandef_rate_flags(chandef); | |
91 | + shift = ieee80211_chandef_get_shift(chandef); | |
92 | + rates_n = 0; | |
93 | + if (have_higher_than_11mbit) | |
94 | + *have_higher_than_11mbit = false; | |
95 | + | |
150 | 96 | for (i = 0; i < sband->n_bitrates; i++) { |
151 | 97 | if ((rate_flags & sband->bitrates[i].flags) != rate_flags) |
152 | 98 | continue; |
153 | - if (sband->bitrates[i].bitrate > 110) | |
154 | - have_higher_than_11mbit = true; | |
99 | + if (sband->bitrates[i].bitrate > 110 && | |
100 | + have_higher_than_11mbit) | |
101 | + *have_higher_than_11mbit = true; | |
155 | 102 | |
156 | 103 | rates |= BIT(i); |
157 | 104 | rates_n++; |
... | ... | @@ -178,7 +125,8 @@ |
178 | 125 | if (sband->band == IEEE80211_BAND_2GHZ) { |
179 | 126 | *pos++ = WLAN_EID_DS_PARAMS; |
180 | 127 | *pos++ = 1; |
181 | - *pos++ = ieee80211_frequency_to_channel(chan->center_freq); | |
128 | + *pos++ = ieee80211_frequency_to_channel( | |
129 | + chandef->chan->center_freq); | |
182 | 130 | } |
183 | 131 | |
184 | 132 | *pos++ = WLAN_EID_IBSS_PARAMS; |
... | ... | @@ -210,9 +158,9 @@ |
210 | 158 | } |
211 | 159 | |
212 | 160 | /* add HT capability and information IEs */ |
213 | - if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT && | |
214 | - chandef.width != NL80211_CHAN_WIDTH_5 && | |
215 | - chandef.width != NL80211_CHAN_WIDTH_10 && | |
161 | + if (chandef->width != NL80211_CHAN_WIDTH_20_NOHT && | |
162 | + chandef->width != NL80211_CHAN_WIDTH_5 && | |
163 | + chandef->width != NL80211_CHAN_WIDTH_10 && | |
216 | 164 | sband->ht_cap.ht_supported) { |
217 | 165 | struct ieee80211_sta_ht_cap ht_cap; |
218 | 166 | |
... | ... | @@ -226,7 +174,7 @@ |
226 | 174 | * keep them at 0 |
227 | 175 | */ |
228 | 176 | pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap, |
229 | - &chandef, 0); | |
177 | + chandef, 0); | |
230 | 178 | } |
231 | 179 | |
232 | 180 | if (local->hw.queues >= IEEE80211_NUM_ACS) { |
233 | 181 | |
234 | 182 | |
235 | 183 | |
... | ... | @@ -243,9 +191,94 @@ |
243 | 191 | |
244 | 192 | presp->head_len = pos - presp->head; |
245 | 193 | if (WARN_ON(presp->head_len > frame_len)) |
194 | + goto error; | |
195 | + | |
196 | + return presp; | |
197 | +error: | |
198 | + kfree(presp); | |
199 | + return NULL; | |
200 | +} | |
201 | + | |
202 | +static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |
203 | + const u8 *bssid, const int beacon_int, | |
204 | + struct ieee80211_channel *chan, | |
205 | + const u32 basic_rates, | |
206 | + const u16 capability, u64 tsf, | |
207 | + bool creator) | |
208 | +{ | |
209 | + struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | |
210 | + struct ieee80211_local *local = sdata->local; | |
211 | + struct ieee80211_supported_band *sband; | |
212 | + struct ieee80211_mgmt *mgmt; | |
213 | + struct cfg80211_bss *bss; | |
214 | + u32 bss_change; | |
215 | + struct cfg80211_chan_def chandef; | |
216 | + struct beacon_data *presp; | |
217 | + enum nl80211_bss_scan_width scan_width; | |
218 | + bool have_higher_than_11mbit; | |
219 | + | |
220 | + sdata_assert_lock(sdata); | |
221 | + | |
222 | + /* Reset own TSF to allow time synchronization work. */ | |
223 | + drv_reset_tsf(local, sdata); | |
224 | + | |
225 | + if (!ether_addr_equal(ifibss->bssid, bssid)) | |
226 | + sta_info_flush(sdata); | |
227 | + | |
228 | + /* if merging, indicate to driver that we leave the old IBSS */ | |
229 | + if (sdata->vif.bss_conf.ibss_joined) { | |
230 | + sdata->vif.bss_conf.ibss_joined = false; | |
231 | + sdata->vif.bss_conf.ibss_creator = false; | |
232 | + sdata->vif.bss_conf.enable_beacon = false; | |
233 | + netif_carrier_off(sdata->dev); | |
234 | + ieee80211_bss_info_change_notify(sdata, | |
235 | + BSS_CHANGED_IBSS | | |
236 | + BSS_CHANGED_BEACON_ENABLED); | |
237 | + } | |
238 | + | |
239 | + presp = rcu_dereference_protected(ifibss->presp, | |
240 | + lockdep_is_held(&sdata->wdev.mtx)); | |
241 | + rcu_assign_pointer(ifibss->presp, NULL); | |
242 | + if (presp) | |
243 | + kfree_rcu(presp, rcu_head); | |
244 | + | |
245 | + sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; | |
246 | + | |
247 | + chandef = ifibss->chandef; | |
248 | + if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) { | |
249 | + if (chandef.width == NL80211_CHAN_WIDTH_5 || | |
250 | + chandef.width == NL80211_CHAN_WIDTH_10 || | |
251 | + chandef.width == NL80211_CHAN_WIDTH_20_NOHT || | |
252 | + chandef.width == NL80211_CHAN_WIDTH_20) { | |
253 | + sdata_info(sdata, | |
254 | + "Failed to join IBSS, beacons forbidden\n"); | |
255 | + return; | |
256 | + } | |
257 | + chandef.width = NL80211_CHAN_WIDTH_20; | |
258 | + chandef.center_freq1 = chan->center_freq; | |
259 | + } | |
260 | + | |
261 | + ieee80211_vif_release_channel(sdata); | |
262 | + if (ieee80211_vif_use_channel(sdata, &chandef, | |
263 | + ifibss->fixed_channel ? | |
264 | + IEEE80211_CHANCTX_SHARED : | |
265 | + IEEE80211_CHANCTX_EXCLUSIVE)) { | |
266 | + sdata_info(sdata, "Failed to join IBSS, no channel context\n"); | |
246 | 267 | return; |
268 | + } | |
247 | 269 | |
270 | + memcpy(ifibss->bssid, bssid, ETH_ALEN); | |
271 | + | |
272 | + sband = local->hw.wiphy->bands[chan->band]; | |
273 | + | |
274 | + presp = ieee80211_ibss_build_presp(sdata, beacon_int, basic_rates, | |
275 | + capability, tsf, &chandef, | |
276 | + &have_higher_than_11mbit); | |
277 | + if (!presp) | |
278 | + return; | |
279 | + | |
248 | 280 | rcu_assign_pointer(ifibss->presp, presp); |
281 | + mgmt = (void *)presp->head; | |
249 | 282 | |
250 | 283 | sdata->vif.bss_conf.enable_beacon = true; |
251 | 284 | sdata->vif.bss_conf.beacon_int = beacon_int; |