1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /****************************************************************************** |
3 | * |
4 | * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. |
5 | * |
6 | ******************************************************************************/ |
7 | |
8 | #include <drv_types.h> |
9 | #include <rtw_debug.h> |
10 | #include <asm/unaligned.h> |
11 | |
12 | void init_mlme_ap_info(struct adapter *padapter) |
13 | { |
14 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; |
15 | struct sta_priv *pstapriv = &padapter->stapriv; |
16 | struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; |
17 | |
18 | spin_lock_init(&pmlmepriv->bcn_update_lock); |
19 | |
20 | /* for ACL */ |
21 | INIT_LIST_HEAD(list: &pacl_list->acl_node_q.queue); |
22 | spin_lock_init(&pacl_list->acl_node_q.lock); |
23 | |
24 | /* pmlmeext->bstart_bss = false; */ |
25 | |
26 | start_ap_mode(padapter); |
27 | } |
28 | |
29 | void free_mlme_ap_info(struct adapter *padapter) |
30 | { |
31 | struct sta_info *psta = NULL; |
32 | struct mlme_priv *pmlmepriv = &padapter->mlmepriv; |
33 | struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; |
34 | struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; |
35 | |
36 | /* stop_ap_mode(padapter); */ |
37 | |
38 | pmlmepriv->update_bcn = false; |
39 | pmlmeext->bstart_bss = false; |
40 | |
41 | rtw_sta_flush(padapter); |
42 | |
43 | pmlmeinfo->state = _HW_STATE_NOLINK_; |
44 | |
45 | /* free_assoc_sta_resources */ |
46 | rtw_free_all_stainfo(padapter); |
47 | |
48 | /* free bc/mc sta_info */ |
49 | psta = rtw_get_bcmc_stainfo(padapter); |
50 | rtw_free_stainfo(padapter, psta); |
51 | } |
52 | |
53 | static void update_BCNTIM(struct adapter *padapter) |
54 | { |
55 | struct sta_priv *pstapriv = &padapter->stapriv; |
56 | struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; |
57 | struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; |
58 | struct wlan_bssid_ex *pnetwork_mlmeext = &pmlmeinfo->network; |
59 | unsigned char *pie = pnetwork_mlmeext->ies; |
60 | |
61 | /* update TIM IE */ |
62 | u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL; |
63 | __le16 tim_bitmap_le; |
64 | uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen; |
65 | |
66 | tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap); |
67 | |
68 | p = rtw_get_ie(pbuf: pie + _FIXED_IE_LENGTH_, |
69 | index: WLAN_EID_TIM, |
70 | len: &tim_ielen, |
71 | limit: pnetwork_mlmeext->ie_length - _FIXED_IE_LENGTH_ |
72 | ); |
73 | if (p && tim_ielen > 0) { |
74 | tim_ielen += 2; |
75 | |
76 | premainder_ie = p + tim_ielen; |
77 | |
78 | tim_ie_offset = (signed int)(p - pie); |
79 | |
80 | remainder_ielen = pnetwork_mlmeext->ie_length - tim_ie_offset - tim_ielen; |
81 | |
82 | /* append TIM IE from dst_ie offset */ |
83 | dst_ie = p; |
84 | } else { |
85 | tim_ielen = 0; |
86 | |
87 | /* calculate head_len */ |
88 | offset = _FIXED_IE_LENGTH_; |
89 | |
90 | /* get ssid_ie len */ |
91 | p = rtw_get_ie(pbuf: pie + _BEACON_IE_OFFSET_, |
92 | index: WLAN_EID_SSID, |
93 | len: &tmp_len, |
94 | limit: (pnetwork_mlmeext->ie_length - _BEACON_IE_OFFSET_) |
95 | ); |
96 | if (p) |
97 | offset += tmp_len + 2; |
98 | |
99 | /* get supported rates len */ |
100 | p = rtw_get_ie(pbuf: pie + _BEACON_IE_OFFSET_, |
101 | index: WLAN_EID_SUPP_RATES, len: &tmp_len, |
102 | limit: (pnetwork_mlmeext->ie_length - _BEACON_IE_OFFSET_) |
103 | ); |
104 | if (p) |
105 | offset += tmp_len + 2; |
106 | |
107 | /* DS Parameter Set IE, len =3 */ |
108 | offset += 3; |
109 | |
110 | premainder_ie = pie + offset; |
111 | |
112 | remainder_ielen = pnetwork_mlmeext->ie_length - offset - tim_ielen; |
113 | |
114 | /* append TIM IE from offset */ |
115 | dst_ie = pie + offset; |
116 | } |
117 | |
118 | if (remainder_ielen > 0) { |
119 | pbackup_remainder_ie = rtw_malloc(remainder_ielen); |
120 | if (pbackup_remainder_ie && premainder_ie) |
121 | memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); |
122 | } |
123 | |
124 | *dst_ie++ = WLAN_EID_TIM; |
125 | |
126 | if ((pstapriv->tim_bitmap & 0xff00) && (pstapriv->tim_bitmap & 0x00fe)) |
127 | tim_ielen = 5; |
128 | else |
129 | tim_ielen = 4; |
130 | |
131 | *dst_ie++ = tim_ielen; |
132 | |
133 | *dst_ie++ = 0;/* DTIM count */ |
134 | *dst_ie++ = 1;/* DTIM period */ |
135 | |
136 | if (pstapriv->tim_bitmap & BIT(0))/* for bc/mc frames */ |
137 | *dst_ie++ = BIT(0);/* bitmap ctrl */ |
138 | else |
139 | *dst_ie++ = 0; |
140 | |
141 | if (tim_ielen == 4) { |
142 | __le16 pvb; |
143 | |
144 | if (pstapriv->tim_bitmap & 0xff00) |
145 | pvb = cpu_to_le16(pstapriv->tim_bitmap >> 8); |
146 | else |
147 | pvb = tim_bitmap_le; |
148 | |
149 | *dst_ie++ = le16_to_cpu(pvb); |
150 | |
151 | } else if (tim_ielen == 5) { |
152 | memcpy(dst_ie, &tim_bitmap_le, 2); |
153 | dst_ie += 2; |
154 | } |
155 | |
156 | /* copy remainder IE */ |
157 | if (pbackup_remainder_ie) { |
158 | memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen); |
159 | |
160 | kfree(objp: pbackup_remainder_ie); |
161 | } |
162 | |
163 | offset = (uint)(dst_ie - pie); |
164 | pnetwork_mlmeext->ie_length = offset + remainder_ielen; |
165 | } |
166 | |
167 | static u8 chk_sta_is_alive(struct sta_info *psta) |
168 | { |
169 | sta_update_last_rx_pkts(psta); |
170 | |
171 | return true; |
172 | } |
173 | |
174 | void expire_timeout_chk(struct adapter *padapter) |
175 | { |
176 | struct list_head *phead, *plist, *tmp; |
177 | u8 updated = false; |
178 | struct sta_info *psta = NULL; |
179 | struct sta_priv *pstapriv = &padapter->stapriv; |
180 | u8 chk_alive_num = 0; |
181 | char chk_alive_list[NUM_STA]; |
182 | int i; |
183 | |
184 | spin_lock_bh(lock: &pstapriv->auth_list_lock); |
185 | |
186 | phead = &pstapriv->auth_list; |
187 | /* check auth_queue */ |
188 | list_for_each_safe(plist, tmp, phead) { |
189 | psta = list_entry(plist, struct sta_info, auth_list); |
190 | |
191 | if (psta->expire_to > 0) { |
192 | psta->expire_to--; |
193 | if (psta->expire_to == 0) { |
194 | list_del_init(entry: &psta->auth_list); |
195 | pstapriv->auth_list_cnt--; |
196 | |
197 | spin_unlock_bh(lock: &pstapriv->auth_list_lock); |
198 | |
199 | rtw_free_stainfo(padapter, psta); |
200 | |
201 | spin_lock_bh(lock: &pstapriv->auth_list_lock); |
202 | } |
203 | } |
204 | } |
205 | |
206 | spin_unlock_bh(lock: &pstapriv->auth_list_lock); |
207 | psta = NULL; |
208 | |
209 | spin_lock_bh(lock: &pstapriv->asoc_list_lock); |
210 | |
211 | phead = &pstapriv->asoc_list; |
212 | /* check asoc_queue */ |
213 | list_for_each_safe(plist, tmp, phead) { |
214 | psta = list_entry(plist, struct sta_info, asoc_list); |
215 | if (chk_sta_is_alive(psta) || !psta->expire_to) { |
216 | psta->expire_to = pstapriv->expire_to; |
217 | psta->keep_alive_trycnt = 0; |
218 | psta->under_exist_checking = 0; |
219 | } else { |
220 | if (psta->expire_to > 0) |
221 | psta->expire_to--; |
222 | } |
223 | |
224 | if (psta->expire_to == 0) { |
225 | struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; |
226 | |
227 | if (padapter->registrypriv.wifi_spec == 1) { |
228 | psta->expire_to = pstapriv->expire_to; |
229 | continue; |
230 | } |
231 | |
232 | if (psta->state & WIFI_SLEEP_STATE) { |
233 | if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) { |
234 | /* to check if alive by another methods */ |
235 | /* if station is at ps mode. */ |
236 | psta->expire_to = pstapriv->expire_to; |
237 | psta->state |= WIFI_STA_ALIVE_CHK_STATE; |
238 | |
239 | /* to update bcn with tim_bitmap for this station */ |
240 | pstapriv->tim_bitmap |= BIT(psta->aid); |
241 | update_beacon(padapter, ie_id: WLAN_EID_TIM, NULL, tx: true); |
242 | |
243 | if (!pmlmeext->active_keep_alive_check) |
244 | continue; |
245 | } |
246 | } |
247 | if (pmlmeext->active_keep_alive_check) { |
248 | int stainfo_offset; |
249 | |
250 | stainfo_offset = rtw_stainfo_offset(stapriv: pstapriv, sta: psta); |
251 | if (stainfo_offset_valid(stainfo_offset)) |
252 | chk_alive_list[chk_alive_num++] = stainfo_offset; |
253 | |
254 | continue; |
255 | } |
256 | list_del_init(entry: &psta->asoc_list); |
257 | pstapriv->asoc_list_cnt--; |
258 | updated = ap_free_sta(padapter, psta, active: false, reason: WLAN_REASON_DEAUTH_LEAVING); |
259 | } else { |
260 | /* TODO: Aging mechanism to digest frames in sleep_q to */ |
261 | /* avoid running out of xmitframe */ |
262 | if (psta->sleepq_len > (NR_XMITFRAME / pstapriv->asoc_list_cnt) |
263 | && padapter->xmitpriv.free_xmitframe_cnt < (( |
264 | NR_XMITFRAME / pstapriv->asoc_list_cnt |
265 | ) / 2) |
266 | ) |
267 | wakeup_sta_to_xmit(padapter, psta); |
268 | } |
269 | } |
270 | |
271 | spin_unlock_bh(lock: &pstapriv->asoc_list_lock); |
272 | |
273 | if (chk_alive_num) { |
274 | u8 backup_oper_channel = 0; |
275 | struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; |
276 | |
277 | /* switch to correct channel of current network before issue keep-alive frames */ |
278 | if (rtw_get_oper_ch(adapter: padapter) != pmlmeext->cur_channel) { |
279 | backup_oper_channel = rtw_get_oper_ch(adapter: padapter); |
280 | SelectChannel(padapter, channel: pmlmeext->cur_channel); |
281 | } |
282 | |
283 | /* issue null data to check sta alive*/ |
284 | for (i = 0; i < chk_alive_num; i++) { |
285 | int ret = _FAIL; |
286 | |
287 | psta = rtw_get_stainfo_by_offset(stapriv: pstapriv, offset: chk_alive_list[i]); |
288 | if (!(psta->state & _FW_LINKED)) |
289 | continue; |
290 | |
291 | if (psta->state & WIFI_SLEEP_STATE) |
292 | ret = issue_nulldata(padapter, da: psta->hwaddr, power_mode: 0, try_cnt: 1, wait_ms: 50); |
293 | else |
294 | ret = issue_nulldata(padapter, da: psta->hwaddr, power_mode: 0, try_cnt: 3, wait_ms: 50); |
295 | |
296 | psta->keep_alive_trycnt++; |
297 | if (ret == _SUCCESS) { |
298 | psta->expire_to = pstapriv->expire_to; |
299 | psta->keep_alive_trycnt = 0; |
300 | continue; |
301 | } else if (psta->keep_alive_trycnt <= 3) { |
302 | psta->expire_to = 1; |
303 | continue; |
304 | } |
305 | |
306 | psta->keep_alive_trycnt = 0; |
307 | spin_lock_bh(lock: &pstapriv->asoc_list_lock); |
308 | if (list_empty(head: &psta->asoc_list) == false) { |
309 | list_del_init(entry: &psta->asoc_list); |
310 | pstapriv->asoc_list_cnt--; |
311 | updated = ap_free_sta(padapter, psta, active: false, |
312 | reason: WLAN_REASON_DEAUTH_LEAVING); |
313 | } |
314 | spin_unlock_bh(lock: &pstapriv->asoc_list_lock); |
315 | } |
316 | |
317 | if (backup_oper_channel > 0) /* back to the original operation channel */ |
318 | SelectChannel(padapter, channel: backup_oper_channel); |
319 | } |
320 | |
321 | associated_clients_update(padapter, updated); |
322 | } |
323 | |
324 | void add_RATid(struct adapter *padapter, struct sta_info *psta, u8 ) |
325 | { |
326 | unsigned char sta_band = 0, shortGIrate = false; |
327 | unsigned int tx_ra_bitmap = 0; |
328 | struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); |
329 | struct wlan_bssid_ex |
330 | *pcur_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network; |
331 | |
332 | if (!psta) |
333 | return; |
334 | |
335 | if (!(psta->state & _FW_LINKED)) |
336 | return; |
337 | |
338 | rtw_hal_update_sta_rate_mask(padapter, psta); |
339 | tx_ra_bitmap = psta->ra_mask; |
340 | |
341 | shortGIrate = query_ra_short_GI(psta); |
342 | |
343 | if (pcur_network->configuration.ds_config > 14) { |
344 | sta_band |= WIRELESS_INVALID; |
345 | } else { |
346 | if (tx_ra_bitmap & 0xffff000) |
347 | sta_band |= WIRELESS_11_24N; |
348 | |
349 | if (tx_ra_bitmap & 0xff0) |
350 | sta_band |= WIRELESS_11G; |
351 | |
352 | if (tx_ra_bitmap & 0x0f) |
353 | sta_band |= WIRELESS_11B; |
354 | } |
355 | |
356 | psta->wireless_mode = sta_band; |
357 | psta->raid = networktype_to_raid_ex(adapter: padapter, psta); |
358 | |
359 | if (psta->aid < NUM_STA) { |
360 | u8 arg[4] = {0}; |
361 | |
362 | arg[0] = psta->mac_id; |
363 | arg[1] = psta->raid; |
364 | arg[2] = shortGIrate; |
365 | arg[3] = psta->init_rate; |
366 | |
367 | rtw_hal_add_ra_tid(padapter, bitmap: tx_ra_bitmap, arg, rssi_level); |
368 | } |
369 | } |
370 | |
371 | void update_bmc_sta(struct adapter *padapter) |
372 | { |
373 | unsigned char network_type; |
374 | int supportRateNum = 0; |
375 | unsigned int tx_ra_bitmap = 0; |
376 | struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); |
377 | struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); |
378 | struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); |
379 | struct wlan_bssid_ex |
380 | *pcur_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network; |
381 | struct sta_info *psta = rtw_get_bcmc_stainfo(padapter); |
382 | |
383 | if (psta) { |
384 | psta->aid = 0;/* default set to 0 */ |
385 | /* psta->mac_id = psta->aid+4; */ |
386 | psta->mac_id = psta->aid + 1;/* mac_id = 1 for bc/mc stainfo */ |
387 | |
388 | pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; |
389 | |
390 | psta->qos_option = 0; |
391 | psta->htpriv.ht_option = false; |
392 | |
393 | psta->ieee8021x_blocked = 0; |
394 | |
395 | memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); |
396 | |
397 | /* psta->dot118021XPrivacy = _NO_PRIVACY_;//!!! remove it, because it has been set before this. */ |
398 | |
399 | /* prepare for add_RATid */ |
400 | supportRateNum = rtw_get_rateset_len(rateset: (u8 *)&pcur_network->supported_rates); |
401 | network_type = rtw_check_network_type(rate: (u8 *)&pcur_network->supported_rates, |
402 | ratelen: supportRateNum, |
403 | channel: pcur_network->configuration.ds_config |
404 | ); |
405 | if (is_supported_tx_cck(network_type)) { |
406 | network_type = WIRELESS_11B; |
407 | } else if (network_type == WIRELESS_INVALID) { /* error handling */ |
408 | |
409 | if (pcur_network->configuration.ds_config > 14) |
410 | network_type = WIRELESS_INVALID; |
411 | else |
412 | network_type = WIRELESS_11B; |
413 | } |
414 | update_sta_basic_rate(psta, wireless_mode: network_type); |
415 | psta->wireless_mode = network_type; |
416 | |
417 | rtw_hal_update_sta_rate_mask(padapter, psta); |
418 | tx_ra_bitmap = psta->ra_mask; |
419 | |
420 | psta->raid = networktype_to_raid_ex(adapter: padapter, psta); |
421 | |
422 | /* ap mode */ |
423 | rtw_hal_set_odm_var(padapter, eVariable: HAL_ODM_STA_INFO, pValue1: psta, bSet: true); |
424 | |
425 | /* if (pHalData->fw_ractrl == true) */ |
426 | { |
427 | u8 arg[4] = {0}; |
428 | |
429 | arg[0] = psta->mac_id; |
430 | arg[1] = psta->raid; |
431 | arg[2] = 0; |
432 | arg[3] = psta->init_rate; |
433 | |
434 | rtw_hal_add_ra_tid(padapter, bitmap: tx_ra_bitmap, arg, rssi_level: 0); |
435 | } |
436 | |
437 | rtw_sta_media_status_rpt(adapter: padapter, psta, mstatus: 1); |
438 | |
439 | spin_lock_bh(lock: &psta->lock); |
440 | psta->state = _FW_LINKED; |
441 | spin_unlock_bh(lock: &psta->lock); |
442 | |
443 | } |
444 | } |
445 | |
446 | /* notes: */ |
447 | /* AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode */ |
448 | /* MAC_ID = AID+1 for sta in ap/adhoc mode */ |
449 | /* MAC_ID = 1 for bc/mc for sta/ap/adhoc */ |
450 | /* MAC_ID = 0 for bssid for sta/ap/adhoc */ |
451 | /* CAM_ID = 0~3 for default key, cmd_id =macid + 3, macid =aid+1; */ |
452 | |
453 | void update_sta_info_apmode(struct adapter *padapter, struct sta_info *psta) |
454 | { |
455 | struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); |
456 | struct security_priv *psecuritypriv = &padapter->securitypriv; |
457 | struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); |
458 | struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; |
459 | struct ht_priv *phtpriv_sta = &psta->htpriv; |
460 | u8 cur_ldpc_cap = 0, cur_stbc_cap = 0, cur_beamform_cap = 0; |
461 | /* set intf_tag to if1 */ |
462 | /* psta->intf_tag = 0; */ |
463 | |
464 | /* psta->mac_id = psta->aid+4; */ |
465 | /* psta->mac_id = psta->aid+1;//alloc macid when call rtw_alloc_stainfo(), */ |
466 | /* release macid when call rtw_free_stainfo() */ |
467 | |
468 | /* ap mode */ |
469 | rtw_hal_set_odm_var(padapter, eVariable: HAL_ODM_STA_INFO, pValue1: psta, bSet: true); |
470 | |
471 | if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) |
472 | psta->ieee8021x_blocked = true; |
473 | else |
474 | psta->ieee8021x_blocked = false; |
475 | |
476 | /* update sta's cap */ |
477 | |
478 | /* ERP */ |
479 | VCS_update(padapter, psta); |
480 | |
481 | /* HT related cap */ |
482 | if (phtpriv_sta->ht_option) { |
483 | /* check if sta supports rx ampdu */ |
484 | phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable; |
485 | |
486 | phtpriv_sta->rx_ampdu_min_spacing = ( |
487 | phtpriv_sta->ht_cap.ampdu_params_info & IEEE80211_HT_CAP_AMPDU_DENSITY |
488 | ) >> 2; |
489 | |
490 | /* bwmode */ |
491 | if (( |
492 | phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info |
493 | ) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH)) |
494 | psta->bw_mode = CHANNEL_WIDTH_40; |
495 | else |
496 | psta->bw_mode = CHANNEL_WIDTH_20; |
497 | |
498 | if (pmlmeext->cur_bwmode < psta->bw_mode) |
499 | psta->bw_mode = pmlmeext->cur_bwmode; |
500 | |
501 | phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset; |
502 | |
503 | /* check if sta support s Short GI 20M */ |
504 | if (( |
505 | phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info |
506 | ) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20)) |
507 | phtpriv_sta->sgi_20m = true; |
508 | |
509 | /* check if sta support s Short GI 40M */ |
510 | if (( |
511 | phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info |
512 | ) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) { |
513 | if (psta->bw_mode == CHANNEL_WIDTH_40) /* according to psta->bw_mode */ |
514 | phtpriv_sta->sgi_40m = true; |
515 | else |
516 | phtpriv_sta->sgi_40m = false; |
517 | } |
518 | |
519 | psta->qos_option = true; |
520 | |
521 | /* B0 Config LDPC Coding Capability */ |
522 | if (TEST_FLAG(phtpriv_ap->ldpc_cap, LDPC_HT_ENABLE_TX) && |
523 | GET_HT_CAPABILITY_ELE_LDPC_CAP((u8 *)(&phtpriv_sta->ht_cap))) |
524 | SET_FLAG(cur_ldpc_cap, (LDPC_HT_ENABLE_TX | LDPC_HT_CAP_TX)); |
525 | |
526 | /* B7 B8 B9 Config STBC setting */ |
527 | if (TEST_FLAG(phtpriv_ap->stbc_cap, STBC_HT_ENABLE_TX) && |
528 | GET_HT_CAPABILITY_ELE_RX_STBC((u8 *)(&phtpriv_sta->ht_cap))) |
529 | SET_FLAG(cur_stbc_cap, (STBC_HT_ENABLE_TX | STBC_HT_CAP_TX)); |
530 | } else { |
531 | phtpriv_sta->ampdu_enable = false; |
532 | |
533 | phtpriv_sta->sgi_20m = false; |
534 | phtpriv_sta->sgi_40m = false; |
535 | psta->bw_mode = CHANNEL_WIDTH_20; |
536 | phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; |
537 | } |
538 | |
539 | phtpriv_sta->ldpc_cap = cur_ldpc_cap; |
540 | phtpriv_sta->stbc_cap = cur_stbc_cap; |
541 | phtpriv_sta->beamform_cap = cur_beamform_cap; |
542 | |
543 | /* Rx AMPDU */ |
544 | send_delba(padapter, initiator: 0, addr: psta->hwaddr);/* recipient */ |
545 | |
546 | /* TX AMPDU */ |
547 | send_delba(padapter, initiator: 1, addr: psta->hwaddr);/* originator */ |
548 | phtpriv_sta->agg_enable_bitmap = 0x0;/* reset */ |
549 | phtpriv_sta->candidate_tid_bitmap = 0x0;/* reset */ |
550 | |
551 | update_ldpc_stbc_cap(psta); |
552 | |
553 | /* todo: init other variables */ |
554 | |
555 | memset((void *)&psta->sta_stats, 0, sizeof(struct stainfo_stats)); |
556 | |
557 | /* add ratid */ |
558 | /* add_RATid(padapter, psta);//move to ap_sta_info_defer_update() */ |
559 | |
560 | spin_lock_bh(lock: &psta->lock); |
561 | psta->state |= _FW_LINKED; |
562 | spin_unlock_bh(lock: &psta->lock); |
563 | } |
564 | |
565 | static void update_ap_info(struct adapter *padapter, struct sta_info *psta) |
566 | { |
567 | struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); |
568 | struct wlan_bssid_ex |
569 | *pnetwork = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network; |
570 | struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); |
571 | struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; |
572 | |
573 | psta->wireless_mode = pmlmeext->cur_wireless_mode; |
574 | |
575 | psta->bssratelen = rtw_get_rateset_len(rateset: pnetwork->supported_rates); |
576 | memcpy(psta->bssrateset, pnetwork->supported_rates, psta->bssratelen); |
577 | |
578 | /* HT related cap */ |
579 | if (phtpriv_ap->ht_option) { |
580 | /* check if sta supports rx ampdu */ |
581 | /* phtpriv_ap->ampdu_enable = phtpriv_ap->ampdu_enable; */ |
582 | |
583 | /* check if sta support s Short GI 20M */ |
584 | if ((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20)) |
585 | phtpriv_ap->sgi_20m = true; |
586 | |
587 | /* check if sta support s Short GI 40M */ |
588 | if ((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40)) |
589 | phtpriv_ap->sgi_40m = true; |
590 | |
591 | psta->qos_option = true; |
592 | } else { |
593 | phtpriv_ap->ampdu_enable = false; |
594 | |
595 | phtpriv_ap->sgi_20m = false; |
596 | phtpriv_ap->sgi_40m = false; |
597 | } |
598 | |
599 | psta->bw_mode = pmlmeext->cur_bwmode; |
600 | phtpriv_ap->ch_offset = pmlmeext->cur_ch_offset; |
601 | |
602 | phtpriv_ap->agg_enable_bitmap = 0x0;/* reset */ |
603 | phtpriv_ap->candidate_tid_bitmap = 0x0;/* reset */ |
604 | |
605 | memcpy(&psta->htpriv, &pmlmepriv->htpriv, sizeof(struct ht_priv)); |
606 | } |
607 | |
608 | static void update_hw_ht_param(struct adapter *padapter) |
609 | { |
610 | unsigned char max_AMPDU_len; |
611 | unsigned char min_MPDU_spacing; |
612 | struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; |
613 | struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); |
614 | |
615 | /* handle A-MPDU parameter field |
616 | * |
617 | * AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k |
618 | * AMPDU_para [4:2]:Min MPDU Start Spacing |
619 | */ |
620 | max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03; |
621 | |
622 | min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2; |
623 | |
624 | rtw_hal_set_hwreg(padapter, variable: HW_VAR_AMPDU_MIN_SPACE, val: (u8 *)(&min_MPDU_spacing)); |
625 | |
626 | rtw_hal_set_hwreg(padapter, variable: HW_VAR_AMPDU_FACTOR, val: (u8 *)(&max_AMPDU_len)); |
627 | |
628 | /* */ |
629 | /* Config SM Power Save setting */ |
630 | /* */ |
631 | pmlmeinfo->SM_PS = (le16_to_cpu( |
632 | pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info |
633 | ) & 0x0C) >> 2; |
634 | |
635 | /* */ |
636 | /* Config current HT Protection mode. */ |
637 | /* */ |
638 | /* pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3; */ |
639 | } |
640 | |
641 | void start_bss_network(struct adapter *padapter) |
642 | { |
643 | u8 *p; |
644 | u8 val8, cur_channel, cur_bwmode, cur_ch_offset; |
645 | u16 bcn_interval; |
646 | u32 acparm; |
647 | int ie_len; |
648 | struct registry_priv *pregpriv = &padapter->registrypriv; |
649 | struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); |
650 | struct security_priv *psecuritypriv = &(padapter->securitypriv); |
651 | struct wlan_bssid_ex |
652 | *pnetwork = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network; |
653 | struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); |
654 | struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); |
655 | struct wlan_bssid_ex *pnetwork_mlmeext = &(pmlmeinfo->network); |
656 | struct HT_info_element *pht_info = NULL; |
657 | u8 cbw40_enable = 0; |
658 | |
659 | bcn_interval = (u16)pnetwork->configuration.beacon_period; |
660 | cur_channel = pnetwork->configuration.ds_config; |
661 | cur_bwmode = CHANNEL_WIDTH_20; |
662 | cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; |
663 | |
664 | /* check if there is wps ie, */ |
665 | /* if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd, */ |
666 | /* and at first time the security ie (RSN/WPA IE) will not include in beacon. */ |
667 | if (!rtw_get_wps_ie(in_ie: pnetwork->ies + _FIXED_IE_LENGTH_, |
668 | in_len: pnetwork->ie_length - _FIXED_IE_LENGTH_, NULL, NULL)) |
669 | pmlmeext->bstart_bss = true; |
670 | |
671 | /* todo: update wmm, ht cap */ |
672 | /* pmlmeinfo->WMM_enable; */ |
673 | /* pmlmeinfo->HT_enable; */ |
674 | if (pmlmepriv->qospriv.qos_option) |
675 | pmlmeinfo->WMM_enable = true; |
676 | if (pmlmepriv->htpriv.ht_option) { |
677 | pmlmeinfo->WMM_enable = true; |
678 | pmlmeinfo->HT_enable = true; |
679 | /* pmlmeinfo->HT_info_enable = true; */ |
680 | /* pmlmeinfo->HT_caps_enable = true; */ |
681 | |
682 | update_hw_ht_param(padapter); |
683 | } |
684 | |
685 | if (!pmlmepriv->cur_network.join_res) { /* setting only at first time */ |
686 | |
687 | /* WEP Key will be set before this function, do not clear CAM. */ |
688 | if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && |
689 | (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)) |
690 | flush_all_cam_entry(padapter); /* clear CAM */ |
691 | } |
692 | |
693 | /* set MSR to AP_Mode */ |
694 | Set_MSR(padapter, _HW_STATE_AP_); |
695 | |
696 | /* Set BSSID REG */ |
697 | rtw_hal_set_hwreg(padapter, variable: HW_VAR_BSSID, val: pnetwork->mac_address); |
698 | |
699 | /* Set EDCA param reg */ |
700 | acparm = 0x002F3217; /* VO */ |
701 | rtw_hal_set_hwreg(padapter, variable: HW_VAR_AC_PARAM_VO, val: (u8 *)(&acparm)); |
702 | acparm = 0x005E4317; /* VI */ |
703 | rtw_hal_set_hwreg(padapter, variable: HW_VAR_AC_PARAM_VI, val: (u8 *)(&acparm)); |
704 | /* acparm = 0x00105320; // BE */ |
705 | acparm = 0x005ea42b; |
706 | rtw_hal_set_hwreg(padapter, variable: HW_VAR_AC_PARAM_BE, val: (u8 *)(&acparm)); |
707 | acparm = 0x0000A444; /* BK */ |
708 | rtw_hal_set_hwreg(padapter, variable: HW_VAR_AC_PARAM_BK, val: (u8 *)(&acparm)); |
709 | |
710 | /* Set Security */ |
711 | val8 = ( |
712 | psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X |
713 | ) ? 0xcc : 0xcf; |
714 | rtw_hal_set_hwreg(padapter, variable: HW_VAR_SEC_CFG, val: (u8 *)(&val8)); |
715 | |
716 | /* Beacon Control related register */ |
717 | rtw_hal_set_hwreg(padapter, variable: HW_VAR_BEACON_INTERVAL, val: (u8 *)(&bcn_interval)); |
718 | |
719 | rtw_hal_set_hwreg(padapter, variable: HW_VAR_DO_IQK, NULL); |
720 | |
721 | if (!pmlmepriv->cur_network.join_res) { /* setting only at first time */ |
722 | /* u32 initialgain; */ |
723 | |
724 | /* initialgain = 0x1e; */ |
725 | |
726 | /* disable dynamic functions, such as high power, DIG */ |
727 | /* Save_DM_Func_Flag(padapter); */ |
728 | /* Switch_DM_Func(padapter, DYNAMIC_FUNC_DISABLE, false); */ |
729 | |
730 | /* turn on all dynamic functions */ |
731 | Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, enable: true); |
732 | |
733 | /* rtw_hal_set_hwreg(padapter, HW_VAR_INITIAL_GAIN, (u8 *)(&initialgain)); */ |
734 | } |
735 | |
736 | /* set channel, bwmode */ |
737 | p = rtw_get_ie(pbuf: (pnetwork->ies + sizeof(struct ndis_802_11_fix_ie)), |
738 | index: WLAN_EID_HT_OPERATION, |
739 | len: &ie_len, |
740 | limit: (pnetwork->ie_length - sizeof(struct ndis_802_11_fix_ie)) |
741 | ); |
742 | if (p && ie_len) { |
743 | pht_info = (struct HT_info_element *)(p + 2); |
744 | |
745 | if (cur_channel > 14) { |
746 | if ((pregpriv->bw_mode & 0xf0) > 0) |
747 | cbw40_enable = 1; |
748 | } else { |
749 | if ((pregpriv->bw_mode & 0x0f) > 0) |
750 | cbw40_enable = 1; |
751 | } |
752 | |
753 | if ((cbw40_enable) && (pht_info->infos[0] & BIT(2))) { |
754 | /* switch to the 40M Hz mode */ |
755 | /* pmlmeext->cur_bwmode = CHANNEL_WIDTH_40; */ |
756 | cur_bwmode = CHANNEL_WIDTH_40; |
757 | switch (pht_info->infos[0] & 0x3) { |
758 | case 1: |
759 | /* pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; */ |
760 | cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER; |
761 | break; |
762 | |
763 | case 3: |
764 | /* pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; */ |
765 | cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER; |
766 | break; |
767 | |
768 | default: |
769 | /* pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; */ |
770 | cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE; |
771 | break; |
772 | } |
773 | } |
774 | } |
775 | |
776 | set_channel_bwmode(padapter, channel: cur_channel, channel_offset: cur_ch_offset, bwmode: cur_bwmode); |
777 | pmlmeext->cur_channel = cur_channel; |
778 | pmlmeext->cur_bwmode = cur_bwmode; |
779 | pmlmeext->cur_ch_offset = cur_ch_offset; |
780 | pmlmeext->cur_wireless_mode = pmlmepriv->cur_network.network_type; |
781 | |
782 | /* let pnetwork_mlmeext == pnetwork_mlme. */ |
783 | memcpy(pnetwork_mlmeext, pnetwork, pnetwork->length); |
784 | |
785 | /* update cur_wireless_mode */ |
786 | update_wireless_mode(padapter); |
787 | |
788 | /* update RRSR after set channel and bandwidth */ |
789 | UpdateBrateTbl(padapter, mBratesOS: pnetwork->supported_rates); |
790 | rtw_hal_set_hwreg(padapter, variable: HW_VAR_BASIC_RATE, val: pnetwork->supported_rates); |
791 | |
792 | /* update capability after cur_wireless_mode updated */ |
793 | update_capinfo( |
794 | Adapter: padapter, |
795 | updateCap: rtw_get_capability(bss: (struct wlan_bssid_ex *)pnetwork) |
796 | ); |
797 | |
798 | if (pmlmeext->bstart_bss) { |
799 | update_beacon(padapter, ie_id: WLAN_EID_TIM, NULL, tx: true); |
800 | |
801 | /* issue beacon frame */ |
802 | send_beacon(padapter); |
803 | } |
804 | |
805 | /* update bc/mc sta_info */ |
806 | update_bmc_sta(padapter); |
807 | |
808 | /* pmlmeext->bstart_bss = true; */ |
809 | } |
810 | |
811 | int rtw_check_beacon_data(struct adapter *padapter, u8 *pbuf, int len) |
812 | { |
813 | int ret = _SUCCESS; |
814 | u8 *p; |
815 | u8 *pHT_caps_ie = NULL; |
816 | u8 *pHT_info_ie = NULL; |
817 | struct sta_info *psta = NULL; |
818 | u16 cap, ht_cap = false; |
819 | uint ie_len = 0; |
820 | int group_cipher, pairwise_cipher; |
821 | u8 channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX]; |
822 | int supportRateNum = 0; |
823 | u8 OUI1[] = {0x00, 0x50, 0xf2, 0x01}; |
824 | u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01}; |
825 | struct registry_priv *pregistrypriv = &padapter->registrypriv; |
826 | struct security_priv *psecuritypriv = &padapter->securitypriv; |
827 | struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); |
828 | struct wlan_bssid_ex |
829 | *pbss_network = (struct wlan_bssid_ex *)&pmlmepriv->cur_network.network; |
830 | u8 *ie = pbss_network->ies; |
831 | |
832 | if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) |
833 | return _FAIL; |
834 | |
835 | if (len < 0 || len > MAX_IE_SZ) |
836 | return _FAIL; |
837 | |
838 | pbss_network->ie_length = len; |
839 | |
840 | memset(ie, 0, MAX_IE_SZ); |
841 | |
842 | memcpy(ie, pbuf, pbss_network->ie_length); |
843 | |
844 | if (pbss_network->infrastructure_mode != Ndis802_11APMode) |
845 | return _FAIL; |
846 | |
847 | pbss_network->rssi = 0; |
848 | |
849 | memcpy(pbss_network->mac_address, myid(&(padapter->eeprompriv)), ETH_ALEN); |
850 | |
851 | /* beacon interval */ |
852 | p = rtw_get_beacon_interval_from_ie(ie);/* ie + 8; 8: TimeStamp, 2: Beacon Interval 2:Capability */ |
853 | /* pbss_network->configuration.beacon_period = le16_to_cpu(*(unsigned short*)p); */ |
854 | pbss_network->configuration.beacon_period = get_unaligned_le16(p); |
855 | |
856 | /* capability */ |
857 | /* cap = *(unsigned short *)rtw_get_capability_from_ie(ie); */ |
858 | /* cap = le16_to_cpu(cap); */ |
859 | cap = get_unaligned_le16(p: ie); |
860 | |
861 | /* SSID */ |
862 | p = rtw_get_ie( |
863 | pbuf: ie + _BEACON_IE_OFFSET_, |
864 | index: WLAN_EID_SSID, |
865 | len: &ie_len, |
866 | limit: (pbss_network->ie_length - _BEACON_IE_OFFSET_) |
867 | ); |
868 | if (p && ie_len > 0) { |
869 | memset(&pbss_network->ssid, 0, sizeof(struct ndis_802_11_ssid)); |
870 | memcpy(pbss_network->ssid.ssid, (p + 2), ie_len); |
871 | pbss_network->ssid.ssid_length = ie_len; |
872 | } |
873 | |
874 | /* channel */ |
875 | channel = 0; |
876 | pbss_network->configuration.length = 0; |
877 | p = rtw_get_ie( |
878 | pbuf: ie + _BEACON_IE_OFFSET_, |
879 | index: WLAN_EID_DS_PARAMS, len: &ie_len, |
880 | limit: (pbss_network->ie_length - _BEACON_IE_OFFSET_) |
881 | ); |
882 | if (p && ie_len > 0) |
883 | channel = *(p + 2); |
884 | |
885 | pbss_network->configuration.ds_config = channel; |
886 | |
887 | memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX); |
888 | /* get supported rates */ |
889 | p = rtw_get_ie( |
890 | pbuf: ie + _BEACON_IE_OFFSET_, |
891 | index: WLAN_EID_SUPP_RATES, |
892 | len: &ie_len, |
893 | limit: (pbss_network->ie_length - _BEACON_IE_OFFSET_) |
894 | ); |
895 | if (p) { |
896 | memcpy(supportRate, p + 2, ie_len); |
897 | supportRateNum = ie_len; |
898 | } |
899 | |
900 | /* get ext_supported rates */ |
901 | p = rtw_get_ie( |
902 | pbuf: ie + _BEACON_IE_OFFSET_, |
903 | index: WLAN_EID_EXT_SUPP_RATES, |
904 | len: &ie_len, |
905 | limit: pbss_network->ie_length - _BEACON_IE_OFFSET_ |
906 | ); |
907 | if (p) { |
908 | memcpy(supportRate + supportRateNum, p + 2, ie_len); |
909 | supportRateNum += ie_len; |
910 | } |
911 | |
912 | network_type = rtw_check_network_type(rate: supportRate, ratelen: supportRateNum, channel); |
913 | |
914 | rtw_set_supported_rate(SupportedRates: pbss_network->supported_rates, mode: network_type); |
915 | |
916 | /* parsing ERP_IE */ |
917 | p = rtw_get_ie( |
918 | pbuf: ie + _BEACON_IE_OFFSET_, |
919 | index: WLAN_EID_ERP_INFO, |
920 | len: &ie_len, |
921 | limit: (pbss_network->ie_length - _BEACON_IE_OFFSET_) |
922 | ); |
923 | if (p && ie_len > 0) |
924 | ERP_IE_handler(padapter, pIE: (struct ndis_80211_var_ie *)p); |
925 | |
926 | /* update privacy/security */ |
927 | if (cap & BIT(4)) |
928 | pbss_network->privacy = 1; |
929 | else |
930 | pbss_network->privacy = 0; |
931 | |
932 | psecuritypriv->wpa_psk = 0; |
933 | |
934 | /* wpa2 */ |
935 | group_cipher = 0; pairwise_cipher = 0; |
936 | psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_; |
937 | psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_; |
938 | p = rtw_get_ie( |
939 | pbuf: ie + _BEACON_IE_OFFSET_, |
940 | index: WLAN_EID_RSN, |
941 | len: &ie_len, |
942 | limit: (pbss_network->ie_length - _BEACON_IE_OFFSET_) |
943 | ); |
944 | if (p && ie_len > 0) { |
945 | if (rtw_parse_wpa2_ie( |
946 | wpa_ie: p, |
947 | wpa_ie_len: ie_len + 2, |
948 | group_cipher: &group_cipher, |
949 | pairwise_cipher: &pairwise_cipher, |
950 | NULL |
951 | ) == _SUCCESS) { |
952 | psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; |
953 | |
954 | psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */ |
955 | psecuritypriv->wpa_psk |= BIT(1); |
956 | |
957 | psecuritypriv->wpa2_group_cipher = group_cipher; |
958 | psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher; |
959 | } |
960 | } |
961 | |
962 | /* wpa */ |
963 | ie_len = 0; |
964 | group_cipher = 0; pairwise_cipher = 0; |
965 | psecuritypriv->wpa_group_cipher = _NO_PRIVACY_; |
966 | psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_; |
967 | for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) { |
968 | p = rtw_get_ie( |
969 | pbuf: p, |
970 | index: WLAN_EID_VENDOR_SPECIFIC, |
971 | len: &ie_len, |
972 | limit: (pbss_network->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2)) |
973 | ); |
974 | if ((p) && (!memcmp(p: p + 2, q: OUI1, size: 4))) { |
975 | if (rtw_parse_wpa_ie( |
976 | wpa_ie: p, |
977 | wpa_ie_len: ie_len + 2, |
978 | group_cipher: &group_cipher, |
979 | pairwise_cipher: &pairwise_cipher, |
980 | NULL |
981 | ) == _SUCCESS) { |
982 | psecuritypriv->dot11AuthAlgrthm = dot11AuthAlgrthm_8021X; |
983 | |
984 | psecuritypriv->dot8021xalg = 1;/* psk, todo:802.1x */ |
985 | |
986 | psecuritypriv->wpa_psk |= BIT(0); |
987 | |
988 | psecuritypriv->wpa_group_cipher = group_cipher; |
989 | psecuritypriv->wpa_pairwise_cipher = pairwise_cipher; |
990 | } |
991 | |
992 | break; |
993 | } |
994 | |
995 | if (!p || ie_len == 0) |
996 | break; |
997 | } |
998 | |
999 | /* wmm */ |
1000 | ie_len = 0; |
1001 | pmlmepriv->qospriv.qos_option = 0; |
1002 | if (pregistrypriv->wmm_enable) { |
1003 | for (p = ie + _BEACON_IE_OFFSET_; ; p += (ie_len + 2)) { |
1004 | p = rtw_get_ie( |
1005 | pbuf: p, |
1006 | index: WLAN_EID_VENDOR_SPECIFIC, |
1007 | len: &ie_len, |
1008 | limit: (pbss_network->ie_length - _BEACON_IE_OFFSET_ - (ie_len + 2)) |
1009 | ); |
1010 | if ((p) && !memcmp(p: p + 2, q: WMM_PARA_IE, size: 6)) { |
1011 | pmlmepriv->qospriv.qos_option = 1; |
1012 | |
1013 | *(p + 8) |= BIT(7);/* QoS Info, support U-APSD */ |
1014 | |
1015 | /* disable all ACM bits since the WMM admission */ |
1016 | /* control is not supported */ |
1017 | *(p + 10) &= ~BIT(4); /* BE */ |
1018 | *(p + 14) &= ~BIT(4); /* BK */ |
1019 | *(p + 18) &= ~BIT(4); /* VI */ |
1020 | *(p + 22) &= ~BIT(4); /* VO */ |
1021 | |
1022 | break; |
1023 | } |
1024 | |
1025 | if (!p || ie_len == 0) |
1026 | break; |
1027 | } |
1028 | } |
1029 | |
1030 | /* parsing HT_CAP_IE */ |
1031 | p = rtw_get_ie( |
1032 | pbuf: ie + _BEACON_IE_OFFSET_, |
1033 | index: WLAN_EID_HT_CAPABILITY, |
1034 | len: &ie_len, |
1035 | limit: (pbss_network->ie_length - _BEACON_IE_OFFSET_) |
1036 | ); |
1037 | if (p && ie_len > 0) { |
1038 | u8 max_rx_ampdu_factor = 0; |
1039 | struct ieee80211_ht_cap *pht_cap = (struct ieee80211_ht_cap *)(p + 2); |
1040 | |
1041 | pHT_caps_ie = p; |
1042 | |
1043 | ht_cap = true; |
1044 | network_type |= WIRELESS_11_24N; |
1045 | |
1046 | rtw_ht_use_default_setting(padapter); |
1047 | |
1048 | if (pmlmepriv->htpriv.sgi_20m == false) |
1049 | pht_cap->cap_info &= cpu_to_le16(~(IEEE80211_HT_CAP_SGI_20)); |
1050 | |
1051 | if (pmlmepriv->htpriv.sgi_40m == false) |
1052 | pht_cap->cap_info &= cpu_to_le16(~(IEEE80211_HT_CAP_SGI_40)); |
1053 | |
1054 | if (!TEST_FLAG(pmlmepriv->htpriv.ldpc_cap, LDPC_HT_ENABLE_RX)) |
1055 | pht_cap->cap_info &= cpu_to_le16(~(IEEE80211_HT_CAP_LDPC_CODING)); |
1056 | |
1057 | if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_TX)) |
1058 | pht_cap->cap_info &= cpu_to_le16(~(IEEE80211_HT_CAP_TX_STBC)); |
1059 | |
1060 | if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_RX)) |
1061 | pht_cap->cap_info &= cpu_to_le16(~(IEEE80211_HT_CAP_RX_STBC_3R)); |
1062 | |
1063 | pht_cap->ampdu_params_info &= ~( |
1064 | IEEE80211_HT_CAP_AMPDU_FACTOR | IEEE80211_HT_CAP_AMPDU_DENSITY |
1065 | ); |
1066 | |
1067 | if ((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) || |
1068 | (psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP)) { |
1069 | pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & |
1070 | (0x07 << 2)); |
1071 | } else { |
1072 | pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & |
1073 | 0x00); |
1074 | } |
1075 | |
1076 | rtw_hal_get_def_var( |
1077 | padapter, |
1078 | eVariable: HW_VAR_MAX_RX_AMPDU_FACTOR, |
1079 | pValue: &max_rx_ampdu_factor |
1080 | ); |
1081 | pht_cap->ampdu_params_info |= ( |
1082 | IEEE80211_HT_CAP_AMPDU_FACTOR & max_rx_ampdu_factor |
1083 | ); /* set Max Rx AMPDU size to 64K */ |
1084 | |
1085 | pht_cap->mcs.rx_mask[0] = 0xff; |
1086 | pht_cap->mcs.rx_mask[1] = 0x0; |
1087 | |
1088 | memcpy(&pmlmepriv->htpriv.ht_cap, p + 2, ie_len); |
1089 | } |
1090 | |
1091 | /* parsing HT_INFO_IE */ |
1092 | p = rtw_get_ie( |
1093 | pbuf: ie + _BEACON_IE_OFFSET_, |
1094 | index: WLAN_EID_HT_OPERATION, |
1095 | len: &ie_len, |
1096 | limit: (pbss_network->ie_length - _BEACON_IE_OFFSET_) |
1097 | ); |
1098 | if (p && ie_len > 0) |
1099 | pHT_info_ie = p; |
1100 | |
1101 | switch (network_type) { |
1102 | case WIRELESS_11B: |
1103 | pbss_network->network_type_in_use = Ndis802_11DS; |
1104 | break; |
1105 | case WIRELESS_11G: |
1106 | case WIRELESS_11BG: |
1107 | case WIRELESS_11G_24N: |
1108 | case WIRELESS_11BG_24N: |
1109 | pbss_network->network_type_in_use = Ndis802_11OFDM24; |
1110 | break; |
1111 | default: |
1112 | pbss_network->network_type_in_use = Ndis802_11OFDM24; |
1113 | break; |
1114 | } |
1115 | |
1116 | pmlmepriv->cur_network.network_type = network_type; |
1117 | |
1118 | pmlmepriv->htpriv.ht_option = false; |
1119 | |
1120 | if ((psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) || |
1121 | (psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_TKIP)) { |
1122 | /* todo: */ |
1123 | /* ht_cap = false; */ |
1124 | } |
1125 | |
1126 | /* ht_cap */ |
1127 | if (pregistrypriv->ht_enable && ht_cap) { |
1128 | pmlmepriv->htpriv.ht_option = true; |
1129 | pmlmepriv->qospriv.qos_option = 1; |
1130 | |
1131 | if (pregistrypriv->ampdu_enable == 1) |
1132 | pmlmepriv->htpriv.ampdu_enable = true; |
1133 | |
1134 | HT_caps_handler(padapter, pIE: (struct ndis_80211_var_ie *)pHT_caps_ie); |
1135 | |
1136 | HT_info_handler(padapter, pIE: (struct ndis_80211_var_ie *)pHT_info_ie); |
1137 | } |
1138 | |
1139 | pbss_network->length = get_wlan_bssid_ex_sz( |
1140 | bss: (struct wlan_bssid_ex *)pbss_network |
1141 | ); |
1142 | |
1143 | /* issue beacon to start bss network */ |
1144 | /* start_bss_network(padapter, (u8 *)pbss_network); */ |
1145 | rtw_startbss_cmd(padapter, flags: RTW_CMDF_WAIT_ACK); |
1146 | |
1147 | /* alloc sta_info for ap itself */ |
1148 | psta = rtw_get_stainfo(pstapriv: &padapter->stapriv, hwaddr: pbss_network->mac_address); |
1149 | if (!psta) { |
1150 | psta = rtw_alloc_stainfo(pstapriv: &padapter->stapriv, hwaddr: pbss_network->mac_address); |
1151 | if (!psta) |
1152 | return _FAIL; |
1153 | } |
1154 | |
1155 | /* update AP's sta info */ |
1156 | update_ap_info(padapter, psta); |
1157 | |
1158 | psta->state |= WIFI_AP_STATE; /* Aries, add, fix bug of flush_cam_entry at STOP AP mode , 0724 */ |
1159 | rtw_indicate_connect(adapter: padapter); |
1160 | |
1161 | pmlmepriv->cur_network.join_res = true;/* for check if already set beacon */ |
1162 | |
1163 | /* update bc/mc sta_info */ |
1164 | /* update_bmc_sta(padapter); */ |
1165 | |
1166 | return ret; |
1167 | } |
1168 | |
1169 | void rtw_set_macaddr_acl(struct adapter *padapter, int mode) |
1170 | { |
1171 | struct sta_priv *pstapriv = &padapter->stapriv; |
1172 | struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; |
1173 | |
1174 | pacl_list->mode = mode; |
1175 | } |
1176 | |
1177 | int rtw_acl_add_sta(struct adapter *padapter, u8 *addr) |
1178 | { |
1179 | struct list_head *plist, *phead; |
1180 | u8 added = false; |
1181 | int i, ret = 0; |
1182 | struct rtw_wlan_acl_node *paclnode; |
1183 | struct sta_priv *pstapriv = &padapter->stapriv; |
1184 | struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; |
1185 | struct __queue *pacl_node_q = &pacl_list->acl_node_q; |
1186 | |
1187 | if ((NUM_ACL - 1) < pacl_list->num) |
1188 | return (-1); |
1189 | |
1190 | spin_lock_bh(lock: &(pacl_node_q->lock)); |
1191 | |
1192 | phead = get_list_head(queue: pacl_node_q); |
1193 | list_for_each(plist, phead) { |
1194 | paclnode = list_entry(plist, struct rtw_wlan_acl_node, list); |
1195 | |
1196 | if (!memcmp(p: paclnode->addr, q: addr, ETH_ALEN)) { |
1197 | if (paclnode->valid == true) { |
1198 | added = true; |
1199 | break; |
1200 | } |
1201 | } |
1202 | } |
1203 | |
1204 | spin_unlock_bh(lock: &(pacl_node_q->lock)); |
1205 | |
1206 | if (added) |
1207 | return ret; |
1208 | |
1209 | spin_lock_bh(lock: &(pacl_node_q->lock)); |
1210 | |
1211 | for (i = 0; i < NUM_ACL; i++) { |
1212 | paclnode = &pacl_list->aclnode[i]; |
1213 | |
1214 | if (!paclnode->valid) { |
1215 | INIT_LIST_HEAD(list: &paclnode->list); |
1216 | |
1217 | memcpy(paclnode->addr, addr, ETH_ALEN); |
1218 | |
1219 | paclnode->valid = true; |
1220 | |
1221 | list_add_tail(new: &paclnode->list, head: get_list_head(queue: pacl_node_q)); |
1222 | |
1223 | pacl_list->num++; |
1224 | |
1225 | break; |
1226 | } |
1227 | } |
1228 | |
1229 | spin_unlock_bh(lock: &(pacl_node_q->lock)); |
1230 | |
1231 | return ret; |
1232 | } |
1233 | |
1234 | void rtw_acl_remove_sta(struct adapter *padapter, u8 *addr) |
1235 | { |
1236 | struct list_head *plist, *phead, *tmp; |
1237 | struct rtw_wlan_acl_node *paclnode; |
1238 | struct sta_priv *pstapriv = &padapter->stapriv; |
1239 | struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; |
1240 | struct __queue *pacl_node_q = &pacl_list->acl_node_q; |
1241 | |
1242 | spin_lock_bh(lock: &(pacl_node_q->lock)); |
1243 | |
1244 | phead = get_list_head(queue: pacl_node_q); |
1245 | list_for_each_safe(plist, tmp, phead) { |
1246 | paclnode = list_entry(plist, struct rtw_wlan_acl_node, list); |
1247 | |
1248 | if ( |
1249 | !memcmp(p: paclnode->addr, q: addr, ETH_ALEN) || |
1250 | is_broadcast_ether_addr(addr) |
1251 | ) { |
1252 | if (paclnode->valid) { |
1253 | paclnode->valid = false; |
1254 | |
1255 | list_del_init(entry: &paclnode->list); |
1256 | |
1257 | pacl_list->num--; |
1258 | } |
1259 | } |
1260 | } |
1261 | |
1262 | spin_unlock_bh(lock: &(pacl_node_q->lock)); |
1263 | |
1264 | } |
1265 | |
1266 | u8 rtw_ap_set_pairwise_key(struct adapter *padapter, struct sta_info *psta) |
1267 | { |
1268 | struct cmd_obj *ph2c; |
1269 | struct set_stakey_parm *psetstakey_para; |
1270 | struct cmd_priv *pcmdpriv = &padapter->cmdpriv; |
1271 | u8 res = _SUCCESS; |
1272 | |
1273 | ph2c = rtw_zmalloc(sizeof(struct cmd_obj)); |
1274 | if (!ph2c) { |
1275 | res = _FAIL; |
1276 | goto exit; |
1277 | } |
1278 | |
1279 | psetstakey_para = rtw_zmalloc(sizeof(struct set_stakey_parm)); |
1280 | if (!psetstakey_para) { |
1281 | kfree(objp: ph2c); |
1282 | res = _FAIL; |
1283 | goto exit; |
1284 | } |
1285 | |
1286 | init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); |
1287 | |
1288 | psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy; |
1289 | |
1290 | memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN); |
1291 | |
1292 | memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16); |
1293 | |
1294 | res = rtw_enqueue_cmd(pcmdpriv, obj: ph2c); |
1295 | |
1296 | exit: |
1297 | |
1298 | return res; |
1299 | } |
1300 | |
1301 | static int rtw_ap_set_key( |
1302 | struct adapter *padapter, |
1303 | u8 *key, |
1304 | u8 alg, |
1305 | int keyid, |
1306 | u8 set_tx |
1307 | ) |
1308 | { |
1309 | u8 keylen; |
1310 | struct cmd_obj *pcmd; |
1311 | struct setkey_parm *psetkeyparm; |
1312 | struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); |
1313 | int res = _SUCCESS; |
1314 | |
1315 | pcmd = rtw_zmalloc(sizeof(struct cmd_obj)); |
1316 | if (!pcmd) { |
1317 | res = _FAIL; |
1318 | goto exit; |
1319 | } |
1320 | psetkeyparm = rtw_zmalloc(sizeof(struct setkey_parm)); |
1321 | if (!psetkeyparm) { |
1322 | kfree(objp: pcmd); |
1323 | res = _FAIL; |
1324 | goto exit; |
1325 | } |
1326 | |
1327 | psetkeyparm->keyid = (u8)keyid; |
1328 | if (is_wep_enc(alg)) |
1329 | padapter->securitypriv.key_mask |= BIT(psetkeyparm->keyid); |
1330 | |
1331 | psetkeyparm->algorithm = alg; |
1332 | |
1333 | psetkeyparm->set_tx = set_tx; |
1334 | |
1335 | switch (alg) { |
1336 | case _WEP40_: |
1337 | keylen = 5; |
1338 | break; |
1339 | case _WEP104_: |
1340 | keylen = 13; |
1341 | break; |
1342 | case _TKIP_: |
1343 | case _TKIP_WTMIC_: |
1344 | case _AES_: |
1345 | default: |
1346 | keylen = 16; |
1347 | } |
1348 | |
1349 | memcpy(&(psetkeyparm->key[0]), key, keylen); |
1350 | |
1351 | pcmd->cmdcode = _SetKey_CMD_; |
1352 | pcmd->parmbuf = (u8 *)psetkeyparm; |
1353 | pcmd->cmdsz = (sizeof(struct setkey_parm)); |
1354 | pcmd->rsp = NULL; |
1355 | pcmd->rspsz = 0; |
1356 | |
1357 | INIT_LIST_HEAD(list: &pcmd->list); |
1358 | |
1359 | res = rtw_enqueue_cmd(pcmdpriv, obj: pcmd); |
1360 | |
1361 | exit: |
1362 | |
1363 | return res; |
1364 | } |
1365 | |
1366 | int rtw_ap_set_group_key(struct adapter *padapter, u8 *key, u8 alg, int keyid) |
1367 | { |
1368 | return rtw_ap_set_key(padapter, key, alg, keyid, set_tx: 1); |
1369 | } |
1370 | |
1371 | int rtw_ap_set_wep_key( |
1372 | struct adapter *padapter, |
1373 | u8 *key, |
1374 | u8 keylen, |
1375 | int keyid, |
1376 | u8 set_tx |
1377 | ) |
1378 | { |
1379 | u8 alg; |
1380 | |
1381 | switch (keylen) { |
1382 | case 5: |
1383 | alg = _WEP40_; |
1384 | break; |
1385 | case 13: |
1386 | alg = _WEP104_; |
1387 | break; |
1388 | default: |
1389 | alg = _NO_PRIVACY_; |
1390 | } |
1391 | |
1392 | return rtw_ap_set_key(padapter, key, alg, keyid, set_tx); |
1393 | } |
1394 | |
1395 | static void update_bcn_fixed_ie(struct adapter *padapter) |
1396 | { |
1397 | } |
1398 | |
1399 | static void update_bcn_erpinfo_ie(struct adapter *padapter) |
1400 | { |
1401 | struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); |
1402 | struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); |
1403 | struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); |
1404 | struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); |
1405 | unsigned char *p, *ie = pnetwork->ies; |
1406 | u32 len = 0; |
1407 | |
1408 | if (!pmlmeinfo->ERP_enable) |
1409 | return; |
1410 | |
1411 | /* parsing ERP_IE */ |
1412 | p = rtw_get_ie( |
1413 | pbuf: ie + _BEACON_IE_OFFSET_, |
1414 | index: WLAN_EID_ERP_INFO, |
1415 | len: &len, |
1416 | limit: (pnetwork->ie_length - _BEACON_IE_OFFSET_) |
1417 | ); |
1418 | if (p && len > 0) { |
1419 | struct ndis_80211_var_ie *pIE = (struct ndis_80211_var_ie *)p; |
1420 | |
1421 | if (pmlmepriv->num_sta_non_erp == 1) |
1422 | pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION; |
1423 | else |
1424 | pIE->data[0] &= ~( |
1425 | RTW_ERP_INFO_NON_ERP_PRESENT | RTW_ERP_INFO_USE_PROTECTION |
1426 | ); |
1427 | |
1428 | if (pmlmepriv->num_sta_no_short_preamble > 0) |
1429 | pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE; |
1430 | else |
1431 | pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE); |
1432 | |
1433 | ERP_IE_handler(padapter, pIE); |
1434 | } |
1435 | } |
1436 | |
1437 | static void update_bcn_htcap_ie(struct adapter *padapter) |
1438 | { |
1439 | } |
1440 | |
1441 | static void update_bcn_htinfo_ie(struct adapter *padapter) |
1442 | { |
1443 | } |
1444 | |
1445 | static void update_bcn_rsn_ie(struct adapter *padapter) |
1446 | { |
1447 | } |
1448 | |
1449 | static void update_bcn_wpa_ie(struct adapter *padapter) |
1450 | { |
1451 | } |
1452 | |
1453 | static void update_bcn_wmm_ie(struct adapter *padapter) |
1454 | { |
1455 | } |
1456 | |
1457 | static void update_bcn_wps_ie(struct adapter *padapter) |
1458 | { |
1459 | u8 *pwps_ie = NULL; |
1460 | u8 *pwps_ie_src; |
1461 | u8 *premainder_ie; |
1462 | u8 *pbackup_remainder_ie = NULL; |
1463 | |
1464 | uint wps_ielen = 0, wps_offset, remainder_ielen; |
1465 | struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); |
1466 | struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); |
1467 | struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); |
1468 | struct wlan_bssid_ex *pnetwork = &(pmlmeinfo->network); |
1469 | unsigned char *ie = pnetwork->ies; |
1470 | u32 ielen = pnetwork->ie_length; |
1471 | |
1472 | pwps_ie = rtw_get_wps_ie( |
1473 | in_ie: ie + _FIXED_IE_LENGTH_, |
1474 | in_len: ielen - _FIXED_IE_LENGTH_, |
1475 | NULL, |
1476 | wps_ielen: &wps_ielen |
1477 | ); |
1478 | |
1479 | if (!pwps_ie || wps_ielen == 0) |
1480 | return; |
1481 | |
1482 | pwps_ie_src = pmlmepriv->wps_beacon_ie; |
1483 | if (!pwps_ie_src) |
1484 | return; |
1485 | |
1486 | wps_offset = (uint)(pwps_ie - ie); |
1487 | |
1488 | premainder_ie = pwps_ie + wps_ielen; |
1489 | |
1490 | remainder_ielen = ielen - wps_offset - wps_ielen; |
1491 | |
1492 | if (remainder_ielen > 0) { |
1493 | pbackup_remainder_ie = rtw_malloc(remainder_ielen); |
1494 | if (pbackup_remainder_ie) |
1495 | memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen); |
1496 | } |
1497 | |
1498 | wps_ielen = (uint)pwps_ie_src[1];/* to get ie data len */ |
1499 | if ((wps_offset + wps_ielen + 2 + remainder_ielen) <= MAX_IE_SZ) { |
1500 | memcpy(pwps_ie, pwps_ie_src, wps_ielen + 2); |
1501 | pwps_ie += (wps_ielen+2); |
1502 | |
1503 | if (pbackup_remainder_ie) |
1504 | memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen); |
1505 | |
1506 | /* update ie_length */ |
1507 | pnetwork->ie_length = wps_offset + (wps_ielen + 2) + remainder_ielen; |
1508 | } |
1509 | |
1510 | kfree(objp: pbackup_remainder_ie); |
1511 | } |
1512 | |
1513 | static void update_bcn_p2p_ie(struct adapter *padapter) |
1514 | { |
1515 | } |
1516 | |
1517 | static void update_bcn_vendor_spec_ie(struct adapter *padapter, u8 *oui) |
1518 | { |
1519 | if (!memcmp(p: RTW_WPA_OUI, q: oui, size: 4)) |
1520 | update_bcn_wpa_ie(padapter); |
1521 | |
1522 | else if (!memcmp(p: WMM_OUI, q: oui, size: 4)) |
1523 | update_bcn_wmm_ie(padapter); |
1524 | |
1525 | else if (!memcmp(p: WPS_OUI, q: oui, size: 4)) |
1526 | update_bcn_wps_ie(padapter); |
1527 | |
1528 | else if (!memcmp(p: P2P_OUI, q: oui, size: 4)) |
1529 | update_bcn_p2p_ie(padapter); |
1530 | } |
1531 | |
1532 | void update_beacon(struct adapter *padapter, u8 ie_id, u8 *oui, u8 tx) |
1533 | { |
1534 | struct mlme_priv *pmlmepriv; |
1535 | struct mlme_ext_priv *pmlmeext; |
1536 | /* struct mlme_ext_info *pmlmeinfo; */ |
1537 | |
1538 | if (!padapter) |
1539 | return; |
1540 | |
1541 | pmlmepriv = &(padapter->mlmepriv); |
1542 | pmlmeext = &(padapter->mlmeextpriv); |
1543 | /* pmlmeinfo = &(pmlmeext->mlmext_info); */ |
1544 | |
1545 | if (!pmlmeext->bstart_bss) |
1546 | return; |
1547 | |
1548 | spin_lock_bh(lock: &pmlmepriv->bcn_update_lock); |
1549 | |
1550 | switch (ie_id) { |
1551 | case 0xFF: |
1552 | |
1553 | update_bcn_fixed_ie(padapter);/* 8: TimeStamp, 2: Beacon Interval 2:Capability */ |
1554 | |
1555 | break; |
1556 | |
1557 | case WLAN_EID_TIM: |
1558 | |
1559 | update_BCNTIM(padapter); |
1560 | |
1561 | break; |
1562 | |
1563 | case WLAN_EID_ERP_INFO: |
1564 | |
1565 | update_bcn_erpinfo_ie(padapter); |
1566 | |
1567 | break; |
1568 | |
1569 | case WLAN_EID_HT_CAPABILITY: |
1570 | |
1571 | update_bcn_htcap_ie(padapter); |
1572 | |
1573 | break; |
1574 | |
1575 | case WLAN_EID_RSN: |
1576 | |
1577 | update_bcn_rsn_ie(padapter); |
1578 | |
1579 | break; |
1580 | |
1581 | case WLAN_EID_HT_OPERATION: |
1582 | |
1583 | update_bcn_htinfo_ie(padapter); |
1584 | |
1585 | break; |
1586 | |
1587 | case WLAN_EID_VENDOR_SPECIFIC: |
1588 | |
1589 | update_bcn_vendor_spec_ie(padapter, oui); |
1590 | |
1591 | break; |
1592 | |
1593 | default: |
1594 | break; |
1595 | } |
1596 | |
1597 | pmlmepriv->update_bcn = true; |
1598 | |
1599 | spin_unlock_bh(lock: &pmlmepriv->bcn_update_lock); |
1600 | |
1601 | if (tx) { |
1602 | /* send_beacon(padapter);//send_beacon must execute on TSR level */ |
1603 | set_tx_beacon_cmd(padapter); |
1604 | } |
1605 | } |
1606 | |
1607 | /* |
1608 | * op_mode |
1609 | * Set to 0 (HT pure) under the following conditions |
1610 | * - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or |
1611 | * - all STAs in the BSS are 20 MHz HT in 20 MHz BSS |
1612 | * Set to 1 (HT non-member protection) if there may be non-HT STAs |
1613 | * in both the primary and the secondary channel |
1614 | * Set to 2 if only HT STAs are associated in BSS, |
1615 | * however and at least one 20 MHz HT STA is associated |
1616 | * Set to 3 (HT mixed mode) when one or more non-HT STAs are associated |
1617 | * (currently non-GF HT station is considered as non-HT STA also) |
1618 | */ |
1619 | static int rtw_ht_operation_update(struct adapter *padapter) |
1620 | { |
1621 | u16 cur_op_mode, new_op_mode; |
1622 | int op_mode_changes = 0; |
1623 | struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); |
1624 | struct ht_priv *phtpriv_ap = &pmlmepriv->htpriv; |
1625 | |
1626 | if (pmlmepriv->htpriv.ht_option) |
1627 | return 0; |
1628 | |
1629 | if (!(pmlmepriv->ht_op_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) |
1630 | && pmlmepriv->num_sta_ht_no_gf) { |
1631 | pmlmepriv->ht_op_mode |= |
1632 | IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT; |
1633 | op_mode_changes++; |
1634 | } else if ((pmlmepriv->ht_op_mode & |
1635 | IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT) && |
1636 | pmlmepriv->num_sta_ht_no_gf == 0) { |
1637 | pmlmepriv->ht_op_mode &= |
1638 | ~IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT; |
1639 | op_mode_changes++; |
1640 | } |
1641 | |
1642 | if (!(pmlmepriv->ht_op_mode & IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT) && |
1643 | (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) { |
1644 | pmlmepriv->ht_op_mode |= IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT; |
1645 | op_mode_changes++; |
1646 | } else if ((pmlmepriv->ht_op_mode & |
1647 | IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT) && |
1648 | (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) { |
1649 | pmlmepriv->ht_op_mode &= |
1650 | ~IEEE80211_HT_OP_MODE_NON_HT_STA_PRSNT; |
1651 | op_mode_changes++; |
1652 | } |
1653 | |
1654 | /* Note: currently we switch to the MIXED op mode if HT non-greenfield |
1655 | * station is associated. Probably it's a theoretical case, since |
1656 | * it looks like all known HT STAs support greenfield. |
1657 | */ |
1658 | new_op_mode = 0; |
1659 | if (pmlmepriv->num_sta_no_ht || |
1660 | (pmlmepriv->ht_op_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT)) |
1661 | new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; |
1662 | else if ( |
1663 | (le16_to_cpu(phtpriv_ap->ht_cap.cap_info) & IEEE80211_HT_CAP_SUP_WIDTH) |
1664 | && pmlmepriv->num_sta_ht_20mhz) |
1665 | new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; |
1666 | else if (pmlmepriv->olbc_ht) |
1667 | new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_NONMEMBER; |
1668 | else |
1669 | new_op_mode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; |
1670 | |
1671 | cur_op_mode = pmlmepriv->ht_op_mode & IEEE80211_HT_OP_MODE_PROTECTION; |
1672 | if (cur_op_mode != new_op_mode) { |
1673 | pmlmepriv->ht_op_mode &= ~IEEE80211_HT_OP_MODE_PROTECTION; |
1674 | pmlmepriv->ht_op_mode |= new_op_mode; |
1675 | op_mode_changes++; |
1676 | } |
1677 | |
1678 | return op_mode_changes; |
1679 | } |
1680 | |
1681 | void associated_clients_update(struct adapter *padapter, u8 updated) |
1682 | { |
1683 | /* update associated stations cap. */ |
1684 | if (updated) { |
1685 | struct list_head *phead, *plist; |
1686 | struct sta_info *psta = NULL; |
1687 | struct sta_priv *pstapriv = &padapter->stapriv; |
1688 | |
1689 | spin_lock_bh(lock: &pstapriv->asoc_list_lock); |
1690 | |
1691 | phead = &pstapriv->asoc_list; |
1692 | /* check asoc_queue */ |
1693 | list_for_each(plist, phead) { |
1694 | psta = list_entry(plist, struct sta_info, asoc_list); |
1695 | |
1696 | VCS_update(padapter, psta); |
1697 | } |
1698 | |
1699 | spin_unlock_bh(lock: &pstapriv->asoc_list_lock); |
1700 | } |
1701 | } |
1702 | |
1703 | /* called > TSR LEVEL for USB or SDIO Interface*/ |
1704 | void bss_cap_update_on_sta_join(struct adapter *padapter, struct sta_info *psta) |
1705 | { |
1706 | u8 beacon_updated = false; |
1707 | struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); |
1708 | struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); |
1709 | |
1710 | if (!(psta->flags & WLAN_STA_SHORT_PREAMBLE)) { |
1711 | if (!psta->no_short_preamble_set) { |
1712 | psta->no_short_preamble_set = 1; |
1713 | |
1714 | pmlmepriv->num_sta_no_short_preamble++; |
1715 | |
1716 | if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && |
1717 | (pmlmepriv->num_sta_no_short_preamble == 1)) { |
1718 | beacon_updated = true; |
1719 | update_beacon(padapter, ie_id: 0xFF, NULL, tx: true); |
1720 | } |
1721 | } |
1722 | } else { |
1723 | if (psta->no_short_preamble_set) { |
1724 | psta->no_short_preamble_set = 0; |
1725 | |
1726 | pmlmepriv->num_sta_no_short_preamble--; |
1727 | |
1728 | if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && |
1729 | (pmlmepriv->num_sta_no_short_preamble == 0)) { |
1730 | beacon_updated = true; |
1731 | update_beacon(padapter, ie_id: 0xFF, NULL, tx: true); |
1732 | } |
1733 | } |
1734 | } |
1735 | |
1736 | if (psta->flags & WLAN_STA_NONERP) { |
1737 | if (!psta->nonerp_set) { |
1738 | psta->nonerp_set = 1; |
1739 | |
1740 | pmlmepriv->num_sta_non_erp++; |
1741 | |
1742 | if (pmlmepriv->num_sta_non_erp == 1) { |
1743 | beacon_updated = true; |
1744 | update_beacon(padapter, ie_id: WLAN_EID_ERP_INFO, NULL, tx: true); |
1745 | } |
1746 | } |
1747 | } else { |
1748 | if (psta->nonerp_set) { |
1749 | psta->nonerp_set = 0; |
1750 | |
1751 | pmlmepriv->num_sta_non_erp--; |
1752 | |
1753 | if (pmlmepriv->num_sta_non_erp == 0) { |
1754 | beacon_updated = true; |
1755 | update_beacon(padapter, ie_id: WLAN_EID_ERP_INFO, NULL, tx: true); |
1756 | } |
1757 | } |
1758 | } |
1759 | |
1760 | if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME)) { |
1761 | if (!psta->no_short_slot_time_set) { |
1762 | psta->no_short_slot_time_set = 1; |
1763 | |
1764 | pmlmepriv->num_sta_no_short_slot_time++; |
1765 | |
1766 | if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && |
1767 | (pmlmepriv->num_sta_no_short_slot_time == 1)) { |
1768 | beacon_updated = true; |
1769 | update_beacon(padapter, ie_id: 0xFF, NULL, tx: true); |
1770 | } |
1771 | } |
1772 | } else { |
1773 | if (psta->no_short_slot_time_set) { |
1774 | psta->no_short_slot_time_set = 0; |
1775 | |
1776 | pmlmepriv->num_sta_no_short_slot_time--; |
1777 | |
1778 | if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && |
1779 | (pmlmepriv->num_sta_no_short_slot_time == 0)) { |
1780 | beacon_updated = true; |
1781 | update_beacon(padapter, ie_id: 0xFF, NULL, tx: true); |
1782 | } |
1783 | } |
1784 | } |
1785 | |
1786 | if (psta->flags & WLAN_STA_HT) { |
1787 | u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info); |
1788 | |
1789 | if (psta->no_ht_set) { |
1790 | psta->no_ht_set = 0; |
1791 | pmlmepriv->num_sta_no_ht--; |
1792 | } |
1793 | |
1794 | if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) { |
1795 | if (!psta->no_ht_gf_set) { |
1796 | psta->no_ht_gf_set = 1; |
1797 | pmlmepriv->num_sta_ht_no_gf++; |
1798 | } |
1799 | } |
1800 | |
1801 | if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) { |
1802 | if (!psta->ht_20mhz_set) { |
1803 | psta->ht_20mhz_set = 1; |
1804 | pmlmepriv->num_sta_ht_20mhz++; |
1805 | } |
1806 | } |
1807 | |
1808 | } else { |
1809 | if (!psta->no_ht_set) { |
1810 | psta->no_ht_set = 1; |
1811 | pmlmepriv->num_sta_no_ht++; |
1812 | } |
1813 | } |
1814 | |
1815 | if (rtw_ht_operation_update(padapter) > 0) { |
1816 | update_beacon(padapter, ie_id: WLAN_EID_HT_CAPABILITY, NULL, tx: false); |
1817 | update_beacon(padapter, ie_id: WLAN_EID_HT_OPERATION, NULL, tx: true); |
1818 | } |
1819 | |
1820 | /* update associated stations cap. */ |
1821 | associated_clients_update(padapter, updated: beacon_updated); |
1822 | } |
1823 | |
1824 | u8 bss_cap_update_on_sta_leave(struct adapter *padapter, struct sta_info *psta) |
1825 | { |
1826 | u8 beacon_updated = false; |
1827 | struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); |
1828 | struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv); |
1829 | |
1830 | if (!psta) |
1831 | return beacon_updated; |
1832 | |
1833 | if (psta->no_short_preamble_set) { |
1834 | psta->no_short_preamble_set = 0; |
1835 | pmlmepriv->num_sta_no_short_preamble--; |
1836 | if (pmlmeext->cur_wireless_mode > WIRELESS_11B |
1837 | && pmlmepriv->num_sta_no_short_preamble == 0){ |
1838 | beacon_updated = true; |
1839 | update_beacon(padapter, ie_id: 0xFF, NULL, tx: true); |
1840 | } |
1841 | } |
1842 | |
1843 | if (psta->nonerp_set) { |
1844 | psta->nonerp_set = 0; |
1845 | pmlmepriv->num_sta_non_erp--; |
1846 | if (pmlmepriv->num_sta_non_erp == 0) { |
1847 | beacon_updated = true; |
1848 | update_beacon(padapter, ie_id: WLAN_EID_ERP_INFO, NULL, tx: true); |
1849 | } |
1850 | } |
1851 | |
1852 | if (psta->no_short_slot_time_set) { |
1853 | psta->no_short_slot_time_set = 0; |
1854 | pmlmepriv->num_sta_no_short_slot_time--; |
1855 | if (pmlmeext->cur_wireless_mode > WIRELESS_11B |
1856 | && pmlmepriv->num_sta_no_short_slot_time == 0){ |
1857 | beacon_updated = true; |
1858 | update_beacon(padapter, ie_id: 0xFF, NULL, tx: true); |
1859 | } |
1860 | } |
1861 | |
1862 | if (psta->no_ht_gf_set) { |
1863 | psta->no_ht_gf_set = 0; |
1864 | pmlmepriv->num_sta_ht_no_gf--; |
1865 | } |
1866 | |
1867 | if (psta->no_ht_set) { |
1868 | psta->no_ht_set = 0; |
1869 | pmlmepriv->num_sta_no_ht--; |
1870 | } |
1871 | |
1872 | if (psta->ht_20mhz_set) { |
1873 | psta->ht_20mhz_set = 0; |
1874 | pmlmepriv->num_sta_ht_20mhz--; |
1875 | } |
1876 | |
1877 | if (rtw_ht_operation_update(padapter) > 0) { |
1878 | update_beacon(padapter, ie_id: WLAN_EID_HT_CAPABILITY, NULL, tx: false); |
1879 | update_beacon(padapter, ie_id: WLAN_EID_HT_OPERATION, NULL, tx: true); |
1880 | } |
1881 | |
1882 | return beacon_updated; |
1883 | } |
1884 | |
1885 | u8 ap_free_sta( |
1886 | struct adapter *padapter, |
1887 | struct sta_info *psta, |
1888 | bool active, |
1889 | u16 reason |
1890 | ) |
1891 | { |
1892 | u8 beacon_updated = false; |
1893 | |
1894 | if (!psta) |
1895 | return beacon_updated; |
1896 | |
1897 | if (active) { |
1898 | /* tear down Rx AMPDU */ |
1899 | send_delba(padapter, initiator: 0, addr: psta->hwaddr);/* recipient */ |
1900 | |
1901 | /* tear down TX AMPDU */ |
1902 | send_delba(padapter, initiator: 1, addr: psta->hwaddr);/* // originator */ |
1903 | |
1904 | issue_deauth(padapter, da: psta->hwaddr, reason); |
1905 | } |
1906 | |
1907 | psta->htpriv.agg_enable_bitmap = 0x0;/* reset */ |
1908 | psta->htpriv.candidate_tid_bitmap = 0x0;/* reset */ |
1909 | |
1910 | /* report_del_sta_event(padapter, psta->hwaddr, reason); */ |
1911 | |
1912 | /* clear cam entry / key */ |
1913 | rtw_clearstakey_cmd(padapter, sta: psta, enqueue: true); |
1914 | |
1915 | spin_lock_bh(lock: &psta->lock); |
1916 | psta->state &= ~_FW_LINKED; |
1917 | spin_unlock_bh(lock: &psta->lock); |
1918 | |
1919 | rtw_cfg80211_indicate_sta_disassoc(padapter, da: psta->hwaddr, reason); |
1920 | |
1921 | report_del_sta_event(padapter, MacAddr: psta->hwaddr, reason); |
1922 | |
1923 | beacon_updated = bss_cap_update_on_sta_leave(padapter, psta); |
1924 | |
1925 | rtw_free_stainfo(padapter, psta); |
1926 | |
1927 | return beacon_updated; |
1928 | } |
1929 | |
1930 | void rtw_sta_flush(struct adapter *padapter) |
1931 | { |
1932 | struct list_head *phead, *plist, *tmp; |
1933 | struct sta_info *psta = NULL; |
1934 | struct sta_priv *pstapriv = &padapter->stapriv; |
1935 | struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; |
1936 | struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); |
1937 | u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
1938 | |
1939 | if ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE) |
1940 | return; |
1941 | |
1942 | spin_lock_bh(lock: &pstapriv->asoc_list_lock); |
1943 | phead = &pstapriv->asoc_list; |
1944 | /* free sta asoc_queue */ |
1945 | list_for_each_safe(plist, tmp, phead) { |
1946 | psta = list_entry(plist, struct sta_info, asoc_list); |
1947 | |
1948 | list_del_init(entry: &psta->asoc_list); |
1949 | pstapriv->asoc_list_cnt--; |
1950 | |
1951 | /* spin_unlock_bh(&pstapriv->asoc_list_lock); */ |
1952 | ap_free_sta(padapter, psta, active: true, reason: WLAN_REASON_DEAUTH_LEAVING); |
1953 | /* spin_lock_bh(&pstapriv->asoc_list_lock); */ |
1954 | } |
1955 | spin_unlock_bh(lock: &pstapriv->asoc_list_lock); |
1956 | |
1957 | issue_deauth(padapter, da: bc_addr, reason: WLAN_REASON_DEAUTH_LEAVING); |
1958 | |
1959 | associated_clients_update(padapter, updated: true); |
1960 | } |
1961 | |
1962 | /* called > TSR LEVEL for USB or SDIO Interface*/ |
1963 | void sta_info_update(struct adapter *padapter, struct sta_info *psta) |
1964 | { |
1965 | int flags = psta->flags; |
1966 | struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); |
1967 | |
1968 | /* update wmm cap. */ |
1969 | if (WLAN_STA_WME & flags) |
1970 | psta->qos_option = 1; |
1971 | else |
1972 | psta->qos_option = 0; |
1973 | |
1974 | if (pmlmepriv->qospriv.qos_option == 0) |
1975 | psta->qos_option = 0; |
1976 | |
1977 | /* update 802.11n ht cap. */ |
1978 | if (WLAN_STA_HT & flags) { |
1979 | psta->htpriv.ht_option = true; |
1980 | psta->qos_option = 1; |
1981 | } else { |
1982 | psta->htpriv.ht_option = false; |
1983 | } |
1984 | |
1985 | if (!pmlmepriv->htpriv.ht_option) |
1986 | psta->htpriv.ht_option = false; |
1987 | |
1988 | update_sta_info_apmode(padapter, psta); |
1989 | } |
1990 | |
1991 | /* called >= TSR LEVEL for USB or SDIO Interface*/ |
1992 | void ap_sta_info_defer_update(struct adapter *padapter, struct sta_info *psta) |
1993 | { |
1994 | struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; |
1995 | struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info); |
1996 | |
1997 | if (psta->state & _FW_LINKED) { |
1998 | pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta; |
1999 | |
2000 | /* add ratid */ |
2001 | add_RATid(padapter, psta, rssi_level: 0);/* DM_RATR_STA_INIT */ |
2002 | } |
2003 | } |
2004 | /* restore hw setting from sw data structures */ |
2005 | void rtw_ap_restore_network(struct adapter *padapter) |
2006 | { |
2007 | struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; |
2008 | struct sta_priv *pstapriv = &padapter->stapriv; |
2009 | struct sta_info *psta; |
2010 | struct security_priv *psecuritypriv = &(padapter->securitypriv); |
2011 | struct list_head *phead, *plist; |
2012 | u8 chk_alive_num = 0; |
2013 | char chk_alive_list[NUM_STA]; |
2014 | int i; |
2015 | |
2016 | rtw_setopmode_cmd(padapter, Ndis802_11APMode, enqueue: false); |
2017 | |
2018 | set_channel_bwmode( |
2019 | padapter, |
2020 | channel: pmlmeext->cur_channel, |
2021 | channel_offset: pmlmeext->cur_ch_offset, |
2022 | bwmode: pmlmeext->cur_bwmode |
2023 | ); |
2024 | |
2025 | start_bss_network(padapter); |
2026 | |
2027 | if ((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) || |
2028 | (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) { |
2029 | /* restore group key, WEP keys is restored in ips_leave() */ |
2030 | rtw_set_key( |
2031 | adapter: padapter, |
2032 | psecuritypriv, |
2033 | keyid: psecuritypriv->dot118021XGrpKeyid, |
2034 | set_tx: 0, |
2035 | enqueue: false |
2036 | ); |
2037 | } |
2038 | |
2039 | spin_lock_bh(lock: &pstapriv->asoc_list_lock); |
2040 | |
2041 | phead = &pstapriv->asoc_list; |
2042 | list_for_each(plist, phead) { |
2043 | int stainfo_offset; |
2044 | |
2045 | psta = list_entry(plist, struct sta_info, asoc_list); |
2046 | |
2047 | stainfo_offset = rtw_stainfo_offset(stapriv: pstapriv, sta: psta); |
2048 | if (stainfo_offset_valid(stainfo_offset)) |
2049 | chk_alive_list[chk_alive_num++] = stainfo_offset; |
2050 | } |
2051 | |
2052 | spin_unlock_bh(lock: &pstapriv->asoc_list_lock); |
2053 | |
2054 | for (i = 0; i < chk_alive_num; i++) { |
2055 | psta = rtw_get_stainfo_by_offset(stapriv: pstapriv, offset: chk_alive_list[i]); |
2056 | |
2057 | if (!psta) |
2058 | continue; |
2059 | |
2060 | if (psta->state & _FW_LINKED) { |
2061 | rtw_sta_media_status_rpt(adapter: padapter, psta, mstatus: 1); |
2062 | Update_RA_Entry(padapter, psta); |
2063 | /* pairwise key */ |
2064 | /* per sta pairwise key and settings */ |
2065 | if ((psecuritypriv->dot11PrivacyAlgrthm == _TKIP_) || |
2066 | (psecuritypriv->dot11PrivacyAlgrthm == _AES_)) { |
2067 | rtw_setstakey_cmd(padapter, sta: psta, unicast_key: true, enqueue: false); |
2068 | } |
2069 | } |
2070 | } |
2071 | } |
2072 | |
2073 | void start_ap_mode(struct adapter *padapter) |
2074 | { |
2075 | int i; |
2076 | struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); |
2077 | struct sta_priv *pstapriv = &padapter->stapriv; |
2078 | struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; |
2079 | struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; |
2080 | |
2081 | pmlmepriv->update_bcn = false; |
2082 | |
2083 | /* init_mlme_ap_info(padapter); */ |
2084 | pmlmeext->bstart_bss = false; |
2085 | |
2086 | pmlmepriv->num_sta_non_erp = 0; |
2087 | |
2088 | pmlmepriv->num_sta_no_short_slot_time = 0; |
2089 | |
2090 | pmlmepriv->num_sta_no_short_preamble = 0; |
2091 | |
2092 | pmlmepriv->num_sta_ht_no_gf = 0; |
2093 | pmlmepriv->num_sta_no_ht = 0; |
2094 | pmlmepriv->num_sta_ht_20mhz = 0; |
2095 | |
2096 | pmlmepriv->olbc = false; |
2097 | |
2098 | pmlmepriv->olbc_ht = false; |
2099 | |
2100 | pmlmepriv->ht_op_mode = 0; |
2101 | |
2102 | for (i = 0; i < NUM_STA; i++) |
2103 | pstapriv->sta_aid[i] = NULL; |
2104 | |
2105 | pmlmepriv->wps_beacon_ie = NULL; |
2106 | pmlmepriv->wps_probe_resp_ie = NULL; |
2107 | pmlmepriv->wps_assoc_resp_ie = NULL; |
2108 | |
2109 | pmlmepriv->p2p_beacon_ie = NULL; |
2110 | pmlmepriv->p2p_probe_resp_ie = NULL; |
2111 | |
2112 | /* for ACL */ |
2113 | INIT_LIST_HEAD(list: &(pacl_list->acl_node_q.queue)); |
2114 | pacl_list->num = 0; |
2115 | pacl_list->mode = 0; |
2116 | for (i = 0; i < NUM_ACL; i++) { |
2117 | INIT_LIST_HEAD(list: &pacl_list->aclnode[i].list); |
2118 | pacl_list->aclnode[i].valid = false; |
2119 | } |
2120 | } |
2121 | |
2122 | void stop_ap_mode(struct adapter *padapter) |
2123 | { |
2124 | struct list_head *phead, *plist, *tmp; |
2125 | struct rtw_wlan_acl_node *paclnode; |
2126 | struct sta_info *psta = NULL; |
2127 | struct sta_priv *pstapriv = &padapter->stapriv; |
2128 | struct mlme_priv *pmlmepriv = &(padapter->mlmepriv); |
2129 | struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; |
2130 | struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; |
2131 | struct __queue *pacl_node_q = &pacl_list->acl_node_q; |
2132 | |
2133 | pmlmepriv->update_bcn = false; |
2134 | pmlmeext->bstart_bss = false; |
2135 | |
2136 | /* reset and init security priv , this can refine with rtw_reset_securitypriv */ |
2137 | memset( |
2138 | (unsigned char *)&padapter->securitypriv, |
2139 | 0, |
2140 | sizeof(struct security_priv) |
2141 | ); |
2142 | padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen; |
2143 | padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled; |
2144 | |
2145 | /* for ACL */ |
2146 | spin_lock_bh(lock: &(pacl_node_q->lock)); |
2147 | phead = get_list_head(queue: pacl_node_q); |
2148 | list_for_each_safe(plist, tmp, phead) { |
2149 | paclnode = list_entry(plist, struct rtw_wlan_acl_node, list); |
2150 | |
2151 | if (paclnode->valid) { |
2152 | paclnode->valid = false; |
2153 | |
2154 | list_del_init(entry: &paclnode->list); |
2155 | |
2156 | pacl_list->num--; |
2157 | } |
2158 | } |
2159 | spin_unlock_bh(lock: &(pacl_node_q->lock)); |
2160 | |
2161 | rtw_sta_flush(padapter); |
2162 | |
2163 | /* free_assoc_sta_resources */ |
2164 | rtw_free_all_stainfo(padapter); |
2165 | |
2166 | psta = rtw_get_bcmc_stainfo(padapter); |
2167 | rtw_free_stainfo(padapter, psta); |
2168 | |
2169 | rtw_init_bcmc_stainfo(padapter); |
2170 | |
2171 | rtw_free_mlme_priv_ie_data(pmlmepriv); |
2172 | |
2173 | rtw_btcoex_MediaStatusNotify(padapter, mediaStatus: 0); /* disconnect */ |
2174 | } |
2175 | |