1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2017 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15 #define _RTW_VHT_C
16
17 #include <drv_types.h>
18 #include <hal_data.h>
19
20 #ifdef CONFIG_80211AC_VHT
21 const u16 _vht_max_mpdu_len[] = {
22 3895,
23 7991,
24 11454,
25 0,
26 };
27
28 const u8 _vht_sup_ch_width_set_to_bw_cap[] = {
29 BW_CAP_80M,
30 BW_CAP_80M | BW_CAP_160M,
31 BW_CAP_80M | BW_CAP_160M | BW_CAP_80_80M,
32 0,
33 };
34
35 #ifdef CONFIG_RTW_DEBUG
36 const char *const _vht_sup_ch_width_set_str[] = {
37 "80MHz",
38 "160MHz",
39 "160MHz & 80+80MHz",
40 "BW-RSVD",
41 };
42
dump_vht_cap_ie_content(void * sel,const u8 * buf,u32 buf_len)43 void dump_vht_cap_ie_content(void *sel, const u8 *buf, u32 buf_len)
44 {
45 if (buf_len != VHT_CAP_IE_LEN) {
46 RTW_PRINT_SEL(sel, "Invalid VHT capability IE len:%d != %d\n", buf_len, VHT_CAP_IE_LEN);
47 return;
48 }
49
50 RTW_PRINT_SEL(sel, "cap_info:%02x %02x %02x %02x: MAX_MPDU_LEN:%u %s%s%s%s%s RX-STBC:%u MAX_AMPDU_LEN:%u\n"
51 , *(buf), *(buf + 1), *(buf + 2), *(buf + 3)
52 , vht_max_mpdu_len(GET_VHT_CAPABILITY_ELE_MAX_MPDU_LENGTH(buf))
53 , vht_sup_ch_width_set_str(GET_VHT_CAPABILITY_ELE_CHL_WIDTH(buf))
54 , GET_VHT_CAPABILITY_ELE_RX_LDPC(buf) ? " RX-LDPC" : ""
55 , GET_VHT_CAPABILITY_ELE_SHORT_GI80M(buf) ? " SGI-80" : ""
56 , GET_VHT_CAPABILITY_ELE_SHORT_GI160M(buf) ? " SGI-160" : ""
57 , GET_VHT_CAPABILITY_ELE_TX_STBC(buf) ? " TX-STBC" : ""
58 , GET_VHT_CAPABILITY_ELE_RX_STBC(buf)
59 , VHT_MAX_AMPDU_LEN(GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(buf))
60 );
61 }
62
dump_vht_cap_ie(void * sel,const u8 * ie,u32 ie_len)63 void dump_vht_cap_ie(void *sel, const u8 *ie, u32 ie_len)
64 {
65 const u8 *vht_cap_ie;
66 sint vht_cap_ielen;
67
68 vht_cap_ie = rtw_get_ie(ie, WLAN_EID_VHT_CAPABILITY, &vht_cap_ielen, ie_len);
69 if (!ie || vht_cap_ie != ie)
70 return;
71
72 dump_vht_cap_ie_content(sel, vht_cap_ie + 2, vht_cap_ielen);
73 }
74
75 const char *const _vht_op_ch_width_str[] = {
76 "20 or 40MHz",
77 "80MHz",
78 "160MHz",
79 "80+80MHz",
80 "BW-RSVD",
81 };
82
dump_vht_op_ie_content(void * sel,const u8 * buf,u32 buf_len)83 void dump_vht_op_ie_content(void *sel, const u8 *buf, u32 buf_len)
84 {
85 if (buf_len != VHT_OP_IE_LEN) {
86 RTW_PRINT_SEL(sel, "Invalid VHT operation IE len:%d != %d\n", buf_len, VHT_OP_IE_LEN);
87 return;
88 }
89
90 RTW_PRINT_SEL(sel, "\tVHT Operation Info:\n");
91 RTW_PRINT_SEL(sel, "\tChannel Width: %u\n"
92 , GET_VHT_OPERATION_ELE_CHL_WIDTH(buf));
93 RTW_PRINT_SEL(sel, "\tCenter Frequency Channel for 80 and 160 MHz Operation: %u\n"
94 , GET_VHT_OPERATION_ELE_CENTER_FREQ1(buf));
95 RTW_PRINT_SEL(sel, "\tCenter Frequency Channel for 80+80 MHz Operation: %u\n"
96 , GET_VHT_OPERATION_ELE_CENTER_FREQ2(buf));
97 RTW_PRINT_SEL(sel, "\tVHT Basic MCS Set: 0x%04x\n"
98 , GET_VHT_OPERATION_ELE_BASIC_MCS_SET(buf));
99 }
100
dump_vht_op_ie(void * sel,const u8 * ie,u32 ie_len)101 void dump_vht_op_ie(void *sel, const u8 *ie, u32 ie_len)
102 {
103 const u8 *vht_op_ie;
104 sint vht_op_ielen;
105
106 vht_op_ie = rtw_get_ie(ie, WLAN_EID_VHT_OPERATION, &vht_op_ielen, ie_len);
107 if (!ie || vht_op_ie != ie)
108 return;
109
110 dump_vht_op_ie_content(sel, vht_op_ie + 2, vht_op_ielen);
111 }
112 #endif
113
114 /* 20/40/80, ShortGI, MCS Rate */
115 const u16 VHT_MCS_DATA_RATE[3][2][40] = { /* unit: 0.5M */
116 { {
117 13, 26, 39, 52, 78, 104, 117, 130, 156, 156,
118 26, 52, 78, 104, 156, 208, 234, 260, 312, 312,
119 39, 78, 117, 156, 234, 312, 351, 390, 468, 520,
120 52, 104, 156, 208, 312, 416, 468, 520, 624, 624,
121 }, /* Long GI, 20MHz */
122 {
123 14, 29, 43, 58, 87, 116, 130, 144, 173, 173,
124 29, 58, 87, 116, 173, 231, 260, 289, 347, 347,
125 43, 87, 130, 173, 260, 347, 390, 433, 520, 578,
126 58, 116, 173, 231, 347, 462, 520, 578, 693, 693,
127 }
128 }, /* Short GI, 20MHz */
129 { {
130 27, 54, 81, 108, 162, 216, 243, 270, 324, 360,
131 54, 108, 162, 216, 324, 432, 486, 540, 648, 720,
132 81, 162, 243, 324, 486, 648, 729, 810, 972, 1080,
133 108, 216, 324, 432, 648, 864, 972, 1080, 1296, 1440,
134 }, /* Long GI, 40MHz */
135 {
136 30, 60, 90, 120, 180, 240, 270, 300, 360, 400,
137 60, 120, 180, 240, 360, 480, 540, 600, 720, 800,
138 90, 180, 270, 360, 540, 720, 810, 900, 1080, 1200,
139 120, 240, 360, 480, 720, 960, 1080, 1200, 1440, 1600,
140 }
141 }, /* Short GI, 40MHz */
142 { {
143 59, 117, 176, 234, 351, 468, 527, 585, 702, 780,
144 117, 234, 351, 468, 702, 936, 1053, 1170, 1404, 1560,
145 176, 351, 527, 702, 1053, 1404, 1580, 1755, 2106, 2340,
146 234, 468, 702, 936, 1404, 1872, 2106, 2340, 2808, 3120,
147 }, /* Long GI, 80MHz */
148 {
149 65, 130, 195, 260, 390, 520, 585, 650, 780, 867,
150 130, 260, 390, 520, 780, 1040, 1170, 1300, 1560, 1734,
151 195, 390, 585, 780, 1170, 1560, 1755, 1950, 2340, 2600,
152 260, 520, 780, 1040, 1560, 2080, 2340, 2600, 3120, 3467,
153 }
154 } /* Short GI, 80MHz */
155 };
156
rtw_get_vht_highest_rate(u8 * pvht_mcs_map)157 u8 rtw_get_vht_highest_rate(u8 *pvht_mcs_map)
158 {
159 u8 i, j;
160 u8 bit_map;
161 u8 vht_mcs_rate = 0;
162
163 for (i = 0; i < 2; i++) {
164 if (pvht_mcs_map[i] != 0xff) {
165 for (j = 0; j < 8; j += 2) {
166 bit_map = (pvht_mcs_map[i] >> j) & 3;
167
168 if (bit_map != 3)
169 vht_mcs_rate = MGN_VHT1SS_MCS7 + 10 * j / 2 + i * 40 + bit_map; /* VHT rate indications begin from 0x90 */
170 }
171 }
172 }
173
174 /* RTW_INFO("HighestVHTMCSRate is %x\n", vht_mcs_rate); */
175 return vht_mcs_rate;
176 }
177
rtw_vht_mcsmap_to_nss(u8 * pvht_mcs_map)178 u8 rtw_vht_mcsmap_to_nss(u8 *pvht_mcs_map)
179 {
180 u8 i, j;
181 u8 bit_map;
182 u8 nss = 0;
183
184 for (i = 0; i < 2; i++) {
185 if (pvht_mcs_map[i] != 0xff) {
186 for (j = 0; j < 8; j += 2) {
187 bit_map = (pvht_mcs_map[i] >> j) & 3;
188
189 if (bit_map != 3)
190 nss++;
191 }
192 }
193 }
194
195 /* RTW_INFO("%s : %dSS\n", __FUNCTION__, nss); */
196 return nss;
197 }
198
rtw_vht_nss_to_mcsmap(u8 nss,u8 * target_mcs_map,u8 * cur_mcs_map)199 void rtw_vht_nss_to_mcsmap(u8 nss, u8 *target_mcs_map, u8 *cur_mcs_map)
200 {
201 u8 i, j;
202 u8 cur_rate, target_rate;
203
204 for (i = 0; i < 2; i++) {
205 target_mcs_map[i] = 0;
206 for (j = 0; j < 8; j += 2) {
207 cur_rate = (cur_mcs_map[i] >> j) & 3;
208 if (cur_rate == 3) /* 0x3 indicates not supported that num of SS */
209 target_rate = 3;
210 else if (nss <= ((j / 2) + i * 4))
211 target_rate = 3;
212 else
213 target_rate = cur_rate;
214
215 target_mcs_map[i] |= (target_rate << j);
216 }
217 }
218
219 /* RTW_INFO("%s : %dSS\n", __FUNCTION__, nss); */
220 }
221
rtw_vht_mcs_to_data_rate(u8 bw,u8 short_GI,u8 vht_mcs_rate)222 u16 rtw_vht_mcs_to_data_rate(u8 bw, u8 short_GI, u8 vht_mcs_rate)
223 {
224 if (vht_mcs_rate > MGN_VHT4SS_MCS9)
225 vht_mcs_rate = MGN_VHT4SS_MCS9;
226 /* RTW_INFO("bw=%d, short_GI=%d, ((vht_mcs_rate - MGN_VHT1SS_MCS0)&0x3f)=%d\n", bw, short_GI, ((vht_mcs_rate - MGN_VHT1SS_MCS0)&0x3f)); */
227 return VHT_MCS_DATA_RATE[bw][short_GI][((vht_mcs_rate - MGN_VHT1SS_MCS0) & 0x3f)];
228 }
229
rtw_vht_use_default_setting(_adapter * padapter)230 void rtw_vht_use_default_setting(_adapter *padapter)
231 {
232 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
233 struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
234 struct registry_priv *pregistrypriv = &padapter->registrypriv;
235 BOOLEAN bHwLDPCSupport = _FALSE, bHwSTBCSupport = _FALSE;
236 #ifdef CONFIG_BEAMFORMING
237 BOOLEAN bHwSupportBeamformer = _FALSE, bHwSupportBeamformee = _FALSE;
238 u8 mu_bfer, mu_bfee;
239 #endif /* CONFIG_BEAMFORMING */
240 u8 tx_nss, rx_nss;
241 u8 rf_type = 0;
242 struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
243 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
244
245 pvhtpriv->sgi_80m = 0;
246 pvhtpriv->sgi_160m = 0;
247 pvhtpriv->txop_ps = 0;
248 pvhtpriv->htc_vht = 1;
249 pvhtpriv->link_adap_cap = 0;
250 pvhtpriv->tx_ant_pattern= 0;
251 pvhtpriv->rx_ant_pattern= 0;
252 pvhtpriv->ext_nss_bw = 0;
253
254 if (TEST_FLAG(pregistrypriv->short_gi, BIT2) && hal_chk_bw_cap(padapter, BW_CAP_80M))
255 pvhtpriv->sgi_80m = 1;
256
257 if (TEST_FLAG(pregistrypriv->short_gi, BIT3) && hal_chk_bw_cap(padapter, BW_CAP_160M))
258 pvhtpriv->sgi_160m = 1;
259
260 /* LDPC support */
261 rtw_hal_get_def_var(padapter, HAL_DEF_RX_LDPC, (u8 *)&bHwLDPCSupport);
262 CLEAR_FLAGS(pvhtpriv->ldpc_cap);
263 if (bHwLDPCSupport) {
264 if (TEST_FLAG(pregistrypriv->ldpc_cap, BIT0))
265 SET_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_RX);
266 }
267 rtw_hal_get_def_var(padapter, HAL_DEF_TX_LDPC, (u8 *)&bHwLDPCSupport);
268 if (bHwLDPCSupport) {
269 if (TEST_FLAG(pregistrypriv->ldpc_cap, BIT1))
270 SET_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_TX);
271 }
272 if (pvhtpriv->ldpc_cap)
273 RTW_INFO("[VHT] Support LDPC = 0x%02X\n", pvhtpriv->ldpc_cap);
274
275 /* STBC */
276 rtw_hal_get_def_var(padapter, HAL_DEF_TX_STBC, (u8 *)&bHwSTBCSupport);
277 CLEAR_FLAGS(pvhtpriv->stbc_cap);
278 if (bHwSTBCSupport) {
279 if (TEST_FLAG(pregistrypriv->stbc_cap, BIT1))
280 SET_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX);
281 }
282
283 rtw_hal_get_def_var(padapter, HAL_DEF_RX_STBC, (u8 *)(&pvhtpriv->rx_stbc_nss));
284 if (pvhtpriv->rx_stbc_nss && TEST_FLAG(pregistrypriv->stbc_cap, BIT0)) {
285 SET_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_RX);
286 }
287
288 if (pvhtpriv->stbc_cap)
289 RTW_INFO("[VHT] Support STBC = 0x%02X\n", pvhtpriv->stbc_cap);
290
291 /* Beamforming setting */
292 CLEAR_FLAGS(pvhtpriv->beamform_cap);
293 #ifdef CONFIG_BEAMFORMING
294 #ifdef RTW_BEAMFORMING_VERSION_2
295 #ifdef CONFIG_CONCURRENT_MODE
296 /* only enable beamforming in STA client mode */
297 if (MLME_IS_STA(padapter) && !MLME_IS_GC(padapter))
298 #else
299 if ((MLME_IS_AP(padapter) && !MLME_IS_GO(padapter)) ||
300 (MLME_IS_STA(padapter) && !MLME_IS_GC(padapter)))
301 #endif
302 #endif
303 {
304 rtw_hal_get_def_var(padapter, HAL_DEF_EXPLICIT_BEAMFORMER,
305 (u8 *)&bHwSupportBeamformer);
306 rtw_hal_get_def_var(padapter, HAL_DEF_EXPLICIT_BEAMFORMEE,
307 (u8 *)&bHwSupportBeamformee);
308 mu_bfer = _FALSE;
309 mu_bfee = _FALSE;
310 rtw_hal_get_def_var(padapter, HAL_DEF_VHT_MU_BEAMFORMER, &mu_bfer);
311 rtw_hal_get_def_var(padapter, HAL_DEF_VHT_MU_BEAMFORMEE, &mu_bfee);
312 if (TEST_FLAG(pregistrypriv->beamform_cap, BIT0) && bHwSupportBeamformer) {
313 #ifdef CONFIG_CONCURRENT_MODE
314 if ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
315 SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
316 RTW_INFO("[VHT] CONCURRENT AP Support Beamformer\n");
317 if (TEST_FLAG(pregistrypriv->beamform_cap, BIT(2))
318 && (_TRUE == mu_bfer)) {
319 SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
320 RTW_INFO("[VHT] Support MU-MIMO AP\n");
321 }
322 } else
323 RTW_INFO("[VHT] CONCURRENT not AP ;not allow Support Beamformer\n");
324 #else
325 SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
326 RTW_INFO("[VHT] Support Beamformer\n");
327 if (TEST_FLAG(pregistrypriv->beamform_cap, BIT(2))
328 && (_TRUE == mu_bfer)
329 && ((pmlmeinfo->state & 0x03) == WIFI_FW_AP_STATE)) {
330 SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
331 RTW_INFO("[VHT] Support MU-MIMO AP\n");
332 }
333 #endif
334 }
335 if (TEST_FLAG(pregistrypriv->beamform_cap, BIT1) && bHwSupportBeamformee) {
336 SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
337 RTW_INFO("[VHT] Support Beamformee\n");
338 if (TEST_FLAG(pregistrypriv->beamform_cap, BIT(3))
339 && (_TRUE == mu_bfee)
340 && ((pmlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)) {
341 SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE);
342 RTW_INFO("[VHT] Support MU-MIMO STA\n");
343 }
344 }
345 }
346 #endif /* CONFIG_BEAMFORMING */
347
348 pvhtpriv->ampdu_len = pregistrypriv->ampdu_factor;
349
350 tx_nss = GET_HAL_TX_NSS(padapter);
351 rx_nss = GET_HAL_RX_NSS(padapter);
352
353 /* for now, vhtpriv.vht_mcs_map comes from RX NSS */
354 rtw_vht_nss_to_mcsmap(rx_nss, pvhtpriv->vht_mcs_map, pregistrypriv->vht_rx_mcs_map);
355 pvhtpriv->vht_highest_rate = rtw_get_vht_highest_rate(pvhtpriv->vht_mcs_map);
356 }
357
rtw_vht_mcs_map_to_bitmap(u8 * mcs_map,u8 nss)358 u64 rtw_vht_mcs_map_to_bitmap(u8 *mcs_map, u8 nss)
359 {
360 u8 i, j, tmp;
361 u64 bitmap = 0;
362 u8 bits_nss = nss * 2;
363
364 for (i = j = 0; i < bits_nss; i += 2, j += 10) {
365 /* every two bits means single sptial stream */
366 tmp = (mcs_map[i / 8] >> i) & 3;
367
368 switch (tmp) {
369 case 2:
370 bitmap = bitmap | ((u64)0x03ff << j);
371 break;
372 case 1:
373 bitmap = bitmap | ((u64)0x01ff << j);
374 break;
375 case 0:
376 bitmap = bitmap | ((u64)0x00ff << j);
377 break;
378 default:
379 break;
380 }
381 }
382
383 RTW_INFO("vht_mcs_map=%02x %02x, nss=%u => bitmap=%016llx\n"
384 , mcs_map[0], mcs_map[1], nss, bitmap);
385
386 return bitmap;
387 }
388
389 #ifdef CONFIG_BEAMFORMING
update_sta_vht_info_apmode_bf_cap(_adapter * padapter,struct sta_info * psta)390 void update_sta_vht_info_apmode_bf_cap(_adapter *padapter, struct sta_info *psta)
391 {
392 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
393 struct vht_priv *pvhtpriv_ap = &pmlmepriv->vhtpriv;
394 struct vht_priv *pvhtpriv_sta = &psta->vhtpriv;
395 u16 cur_beamform_cap = 0;
396
397 /* B11 SU Beamformer Capable, the target supports Beamformer and we are Beamformee */
398 if (TEST_FLAG(pvhtpriv_ap->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE) &&
399 GET_VHT_CAPABILITY_ELE_SU_BFEE(pvhtpriv_sta->vht_cap)) {
400 SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
401 /*Shift to BEAMFORMING_VHT_BEAMFORMER_STS_CAP*/
402 SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pvhtpriv_sta->vht_cap) << 8);
403 }
404
405 /* B12 SU Beamformee Capable, the target supports Beamformee and we are Beamformer */
406 if (TEST_FLAG(pvhtpriv_ap->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) &&
407 GET_VHT_CAPABILITY_ELE_SU_BFER(pvhtpriv_sta->vht_cap)) {
408 SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
409 /*Shit to BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM*/
410 SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pvhtpriv_sta->vht_cap) << 12);
411 }
412
413 if (cur_beamform_cap)
414 RTW_INFO("Current STA(%d) VHT Beamforming Setting = %02X\n", psta->cmn.aid, cur_beamform_cap);
415
416 pvhtpriv_sta->beamform_cap = cur_beamform_cap;
417 psta->cmn.bf_info.vht_beamform_cap = cur_beamform_cap;
418 }
419 #endif
420
update_sta_vht_info_apmode(_adapter * padapter,void * sta)421 void update_sta_vht_info_apmode(_adapter *padapter, void *sta)
422 {
423 struct sta_info *psta = (struct sta_info *)sta;
424 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
425 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
426 struct vht_priv *pvhtpriv_ap = &pmlmepriv->vhtpriv;
427 struct vht_priv *pvhtpriv_sta = &psta->vhtpriv;
428 u8 cur_ldpc_cap = 0, cur_stbc_cap = 0;
429 s8 bw_mode = -1;
430 u8 *pcap_mcs;
431
432 if (pvhtpriv_sta->vht_option == _FALSE)
433 return;
434
435 if (pvhtpriv_sta->op_present) {
436 switch (GET_VHT_OPERATION_ELE_CHL_WIDTH(pvhtpriv_sta->vht_op)) {
437 case 1: /* 80MHz */
438 case 2: /* 160MHz */
439 case 3: /* 80+80 */
440 bw_mode = CHANNEL_WIDTH_80; /* only support up to 80MHz for now */
441 break;
442 }
443 }
444
445 if (pvhtpriv_sta->notify_present)
446 bw_mode = GET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(&pvhtpriv_sta->vht_op_mode_notify);
447 else if (MLME_IS_AP(padapter)) {
448 /* for VHT client without Operating Mode Notify IE; minimal 80MHz */
449 if (bw_mode < CHANNEL_WIDTH_80)
450 bw_mode = CHANNEL_WIDTH_80;
451 }
452
453 if (bw_mode != -1)
454 psta->cmn.bw_mode = bw_mode; /* update bw_mode only if get value from VHT IEs */
455
456 psta->cmn.ra_info.is_vht_enable = _TRUE;
457
458 /* B4 Rx LDPC */
459 if (TEST_FLAG(pvhtpriv_ap->ldpc_cap, LDPC_VHT_ENABLE_TX) &&
460 GET_VHT_CAPABILITY_ELE_RX_LDPC(pvhtpriv_sta->vht_cap)) {
461 SET_FLAG(cur_ldpc_cap, (LDPC_VHT_ENABLE_TX | LDPC_VHT_CAP_TX));
462 RTW_INFO("Current STA(%d) VHT LDPC = %02X\n", psta->cmn.aid, cur_ldpc_cap);
463 }
464 pvhtpriv_sta->ldpc_cap = cur_ldpc_cap;
465
466 if (psta->cmn.bw_mode > pmlmeext->cur_bwmode)
467 psta->cmn.bw_mode = pmlmeext->cur_bwmode;
468
469 if (psta->cmn.bw_mode == CHANNEL_WIDTH_80) {
470 /* B5 Short GI for 80 MHz */
471 pvhtpriv_sta->sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI80M(pvhtpriv_sta->vht_cap) & pvhtpriv_ap->sgi_80m) ? _TRUE : _FALSE;
472 /* RTW_INFO("Current STA ShortGI80MHz = %d\n", pvhtpriv_sta->sgi_80m); */
473 } else if (psta->cmn.bw_mode >= CHANNEL_WIDTH_160) {
474 /* B5 Short GI for 80 MHz */
475 pvhtpriv_sta->sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI160M(pvhtpriv_sta->vht_cap) & pvhtpriv_ap->sgi_80m) ? _TRUE : _FALSE;
476 /* RTW_INFO("Current STA ShortGI160MHz = %d\n", pvhtpriv_sta->sgi_80m); */
477 }
478
479 /* B8 B9 B10 Rx STBC */
480 if (TEST_FLAG(pvhtpriv_ap->stbc_cap, STBC_VHT_ENABLE_TX) &&
481 GET_VHT_CAPABILITY_ELE_RX_STBC(pvhtpriv_sta->vht_cap)) {
482 SET_FLAG(cur_stbc_cap, (STBC_VHT_ENABLE_TX | STBC_VHT_CAP_TX));
483 RTW_INFO("Current STA(%d) VHT STBC = %02X\n", psta->cmn.aid, cur_stbc_cap);
484 }
485 pvhtpriv_sta->stbc_cap = cur_stbc_cap;
486
487 #ifdef CONFIG_BEAMFORMING
488 update_sta_vht_info_apmode_bf_cap(padapter, psta);
489 #endif
490
491 /* B23 B24 B25 Maximum A-MPDU Length Exponent */
492 pvhtpriv_sta->ampdu_len = GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pvhtpriv_sta->vht_cap);
493
494 pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pvhtpriv_sta->vht_cap);
495 _rtw_memcpy(pvhtpriv_sta->vht_mcs_map, pcap_mcs, 2);
496 pvhtpriv_sta->vht_highest_rate = rtw_get_vht_highest_rate(pvhtpriv_sta->vht_mcs_map);
497 }
498
update_hw_vht_param(_adapter * padapter)499 void update_hw_vht_param(_adapter *padapter)
500 {
501 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
502 struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
503 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
504 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
505 u8 ht_AMPDU_len;
506
507 ht_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
508
509 if (pvhtpriv->ampdu_len > ht_AMPDU_len)
510 rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&pvhtpriv->ampdu_len));
511 }
512
513 #ifdef ROKU_PRIVATE
VHT_get_ss_from_map(u8 * vht_mcs_map)514 u8 VHT_get_ss_from_map(u8 *vht_mcs_map)
515 {
516 u8 i, j;
517 u8 ss = 0;
518
519 for (i = 0; i < 2; i++) {
520 if (vht_mcs_map[i] != 0xff) {
521 for (j = 0; j < 8; j += 2) {
522 if (((vht_mcs_map[i] >> j) & 0x03) == 0x03)
523 break;
524 ss++;
525 }
526 }
527
528 }
529
530 return ss;
531 }
532
VHT_caps_handler_infra_ap(_adapter * padapter,PNDIS_802_11_VARIABLE_IEs pIE)533 void VHT_caps_handler_infra_ap(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
534 {
535 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
536 struct vht_priv_infra_ap *pvhtpriv = &pmlmepriv->vhtpriv_infra_ap;
537 u8 cur_stbc_cap_infra_ap = 0;
538 u16 cur_beamform_cap_infra_ap = 0;
539 u8 *pcap_mcs;
540 u8 *pcap_mcs_tx;
541 u8 Rx_ss = 0, Tx_ss = 0;
542
543 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
544 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
545
546 if (pIE == NULL)
547 return;
548
549 pmlmeinfo->ht_vht_received |= BIT(1);
550
551 pvhtpriv->ldpc_cap_infra_ap = GET_VHT_CAPABILITY_ELE_RX_LDPC(pIE->data);
552
553 if (GET_VHT_CAPABILITY_ELE_RX_STBC(pIE->data))
554 SET_FLAG(cur_stbc_cap_infra_ap, STBC_VHT_ENABLE_RX);
555 if (GET_VHT_CAPABILITY_ELE_TX_STBC(pIE->data))
556 SET_FLAG(cur_stbc_cap_infra_ap, STBC_VHT_ENABLE_TX);
557 pvhtpriv->stbc_cap_infra_ap = cur_stbc_cap_infra_ap;
558
559 /*store ap info for channel bandwidth*/
560 pvhtpriv->channel_width_infra_ap = GET_VHT_CAPABILITY_ELE_CHL_WIDTH(pIE->data);
561
562 /*check B11: SU Beamformer Capable and B12: SU Beamformee B19: MU Beamformer B20:MU Beamformee*/
563 if (GET_VHT_CAPABILITY_ELE_SU_BFER(pIE->data))
564 SET_FLAG(cur_beamform_cap_infra_ap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
565 if (GET_VHT_CAPABILITY_ELE_SU_BFEE(pIE->data))
566 SET_FLAG(cur_beamform_cap_infra_ap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
567 if (GET_VHT_CAPABILITY_ELE_MU_BFER(pIE->data))
568 SET_FLAG(cur_beamform_cap_infra_ap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
569 if (GET_VHT_CAPABILITY_ELE_MU_BFEE(pIE->data))
570 SET_FLAG(cur_beamform_cap_infra_ap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE);
571 pvhtpriv->beamform_cap_infra_ap = cur_beamform_cap_infra_ap;
572
573 /*store information about vht_mcs_set*/
574 pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pIE->data);
575 pcap_mcs_tx = GET_VHT_CAPABILITY_ELE_TX_MCS(pIE->data);
576 _rtw_memcpy(pvhtpriv->vht_mcs_map_infra_ap, pcap_mcs, 2);
577 _rtw_memcpy(pvhtpriv->vht_mcs_map_tx_infra_ap, pcap_mcs_tx, 2);
578
579 Rx_ss = VHT_get_ss_from_map(pvhtpriv->vht_mcs_map_infra_ap);
580 Tx_ss = VHT_get_ss_from_map(pvhtpriv->vht_mcs_map_tx_infra_ap);
581 if (Rx_ss >= Tx_ss) {
582 pvhtpriv->number_of_streams_infra_ap = Rx_ss;
583 } else{
584 pvhtpriv->number_of_streams_infra_ap = Tx_ss;
585 }
586
587 }
588 #endif /* ROKU_PRIVATE */
589
VHT_caps_handler(_adapter * padapter,PNDIS_802_11_VARIABLE_IEs pIE)590 void VHT_caps_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
591 {
592 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
593 struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
594 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
595 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
596 u8 cur_ldpc_cap = 0, cur_stbc_cap = 0, rx_nss = 0;
597 u16 cur_beamform_cap = 0;
598 u8 *pcap_mcs;
599
600 if (pIE == NULL)
601 return;
602
603 if (pvhtpriv->vht_option == _FALSE)
604 return;
605
606 pmlmeinfo->VHT_enable = 1;
607
608 /* B4 Rx LDPC */
609 if (TEST_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_TX) &&
610 GET_VHT_CAPABILITY_ELE_RX_LDPC(pIE->data)) {
611 SET_FLAG(cur_ldpc_cap, (LDPC_VHT_ENABLE_TX | LDPC_VHT_CAP_TX));
612 RTW_INFO("Current VHT LDPC Setting = %02X\n", cur_ldpc_cap);
613 }
614 pvhtpriv->ldpc_cap = cur_ldpc_cap;
615
616 /* B5 Short GI for 80 MHz */
617 pvhtpriv->sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI80M(pIE->data) & pvhtpriv->sgi_80m) ? _TRUE : _FALSE;
618 /* RTW_INFO("Current ShortGI80MHz = %d\n", pvhtpriv->sgi_80m); */
619
620 /* B8 B9 B10 Rx STBC */
621 if (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX) &&
622 GET_VHT_CAPABILITY_ELE_RX_STBC(pIE->data)) {
623 SET_FLAG(cur_stbc_cap, (STBC_VHT_ENABLE_TX | STBC_VHT_CAP_TX));
624 RTW_INFO("Current VHT STBC Setting = %02X\n", cur_stbc_cap);
625 }
626 pvhtpriv->stbc_cap = cur_stbc_cap;
627 #ifdef CONFIG_BEAMFORMING
628 #ifdef RTW_BEAMFORMING_VERSION_2
629 /*
630 * B11 SU Beamformer Capable,
631 * the target supports Beamformer and we are Beamformee
632 */
633 if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE)
634 && GET_VHT_CAPABILITY_ELE_SU_BFER(pIE->data)) {
635 SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
636
637 /* Shift to BEAMFORMING_VHT_BEAMFORMEE_STS_CAP */
638 SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pIE->data) << 8);
639
640 /*
641 * B19 MU Beamformer Capable,
642 * the target supports Beamformer and we are Beamformee
643 */
644 if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE)
645 && GET_VHT_CAPABILITY_ELE_MU_BFER(pIE->data))
646 SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE);
647 }
648
649 /*
650 * B12 SU Beamformee Capable,
651 * the target supports Beamformee and we are Beamformer
652 */
653 if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE)
654 && GET_VHT_CAPABILITY_ELE_SU_BFEE(pIE->data)) {
655 SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
656
657 /* Shit to BEAMFORMING_VHT_BEAMFORMER_SOUND_DIM */
658 SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pIE->data) << 12);
659
660 /*
661 * B20 MU Beamformee Capable,
662 * the target supports Beamformee and we are Beamformer
663 */
664 if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)
665 && GET_VHT_CAPABILITY_ELE_MU_BFEE(pIE->data))
666 SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE);
667 }
668
669 pvhtpriv->beamform_cap = cur_beamform_cap;
670 RTW_INFO("Current VHT Beamforming Setting=0x%04X\n", cur_beamform_cap);
671 #else /* !RTW_BEAMFORMING_VERSION_2 */
672 /* B11 SU Beamformer Capable, the target supports Beamformer and we are Beamformee */
673 if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE) &&
674 GET_VHT_CAPABILITY_ELE_SU_BFEE(pIE->data)) {
675 SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
676 /*Shift to BEAMFORMING_VHT_BEAMFORMER_STS_CAP*/
677 SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pIE->data) << 8);
678 }
679
680 /* B12 SU Beamformee Capable, the target supports Beamformee and we are Beamformer */
681 if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) &&
682 GET_VHT_CAPABILITY_ELE_SU_BFER(pIE->data)) {
683 SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
684 /*Shit to BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM*/
685 SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pIE->data) << 12);
686
687 }
688 pvhtpriv->beamform_cap = cur_beamform_cap;
689 if (cur_beamform_cap)
690 RTW_INFO("Current VHT Beamforming Setting = %02X\n", cur_beamform_cap);
691 #endif /* !RTW_BEAMFORMING_VERSION_2 */
692 #endif /* CONFIG_BEAMFORMING */
693 /* B23 B24 B25 Maximum A-MPDU Length Exponent */
694 pvhtpriv->ampdu_len = GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pIE->data);
695
696 pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pIE->data);
697 rx_nss = GET_HAL_RX_NSS(padapter);
698 rtw_vht_nss_to_mcsmap(rx_nss, pvhtpriv->vht_mcs_map, pcap_mcs);
699 pvhtpriv->vht_highest_rate = rtw_get_vht_highest_rate(pvhtpriv->vht_mcs_map);
700 }
701
VHT_operation_handler(_adapter * padapter,PNDIS_802_11_VARIABLE_IEs pIE)702 void VHT_operation_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
703 {
704 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
705 struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
706
707 if (pIE == NULL)
708 return;
709
710 if (pvhtpriv->vht_option == _FALSE)
711 return;
712 }
713
rtw_process_vht_op_mode_notify(_adapter * padapter,u8 * pframe,void * sta)714 void rtw_process_vht_op_mode_notify(_adapter *padapter, u8 *pframe, void *sta)
715 {
716 struct sta_info *psta = (struct sta_info *)sta;
717 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
718 struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
719 struct registry_priv *regsty = adapter_to_regsty(padapter);
720 u8 target_bw;
721 u8 target_rxss, current_rxss;
722 u8 update_ra = _FALSE;
723 u8 tx_nss = 0;
724
725 if (pvhtpriv->vht_option == _FALSE)
726 return;
727
728 target_bw = GET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(pframe);
729 tx_nss = GET_HAL_TX_NSS(padapter);
730 target_rxss = rtw_min(tx_nss, (GET_VHT_OPERATING_MODE_FIELD_RX_NSS(pframe) + 1));
731
732 if (target_bw != psta->cmn.bw_mode) {
733 if (hal_is_bw_support(padapter, target_bw)
734 && REGSTY_IS_BW_5G_SUPPORT(regsty, target_bw)
735 ) {
736 update_ra = _TRUE;
737 psta->cmn.bw_mode = target_bw;
738 }
739 }
740
741 current_rxss = rtw_vht_mcsmap_to_nss(psta->vhtpriv.vht_mcs_map);
742 if (target_rxss != current_rxss) {
743 u8 vht_mcs_map[2] = {};
744
745 update_ra = _TRUE;
746
747 rtw_vht_nss_to_mcsmap(target_rxss, vht_mcs_map, psta->vhtpriv.vht_mcs_map);
748 _rtw_memcpy(psta->vhtpriv.vht_mcs_map, vht_mcs_map, 2);
749
750 rtw_hal_update_sta_ra_info(padapter, psta);
751 }
752
753 if (update_ra)
754 rtw_dm_ra_mask_wk_cmd(padapter, (u8 *)psta);
755 }
756
rtw_build_vht_operation_ie(_adapter * padapter,u8 * pbuf,u8 channel)757 u32 rtw_build_vht_operation_ie(_adapter *padapter, u8 *pbuf, u8 channel)
758 {
759 struct registry_priv *pregistrypriv = &padapter->registrypriv;
760 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
761 struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
762 /* struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; */
763 u8 ChnlWidth, center_freq, bw_mode;
764 u32 len = 0;
765 u8 operation[5];
766
767 _rtw_memset(operation, 0, 5);
768
769 bw_mode = REGSTY_BW_5G(pregistrypriv); /* TODO: control op bw with other info */
770
771 if (hal_chk_bw_cap(padapter, BW_CAP_80M | BW_CAP_160M)
772 && REGSTY_BW_5G(pregistrypriv) >= CHANNEL_WIDTH_80
773 ) {
774 center_freq = rtw_get_center_ch(channel, bw_mode, HAL_PRIME_CHNL_OFFSET_LOWER);
775 ChnlWidth = 1;
776 } else {
777 center_freq = 0;
778 ChnlWidth = 0;
779 }
780
781 SET_VHT_OPERATION_ELE_CHL_WIDTH(operation, ChnlWidth);
782 /* center frequency */
783 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(operation, center_freq);/* Todo: need to set correct center channel */
784 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(operation, 0);
785
786 _rtw_memcpy(operation + 3, pvhtpriv->vht_mcs_map, 2);
787
788 rtw_set_ie(pbuf, EID_VHTOperation, 5, operation, &len);
789
790 return len;
791 }
792
rtw_build_vht_op_mode_notify_ie(_adapter * padapter,u8 * pbuf,u8 bw)793 u32 rtw_build_vht_op_mode_notify_ie(_adapter *padapter, u8 *pbuf, u8 bw)
794 {
795 /* struct registry_priv *pregistrypriv = &padapter->registrypriv; */
796 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
797 struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
798 u32 len = 0;
799 u8 opmode = 0;
800 u8 chnl_width, rx_nss;
801
802 chnl_width = bw;
803 rx_nss = rtw_vht_mcsmap_to_nss(pvhtpriv->vht_mcs_map);
804
805 SET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(&opmode, chnl_width);
806 SET_VHT_OPERATING_MODE_FIELD_RX_NSS(&opmode, (rx_nss - 1));
807 SET_VHT_OPERATING_MODE_FIELD_RX_NSS_TYPE(&opmode, 0); /* Todo */
808
809 pvhtpriv->vht_op_mode_notify = opmode;
810
811 pbuf = rtw_set_ie(pbuf, EID_OpModeNotification, 1, &opmode, &len);
812
813 return len;
814 }
815
rtw_build_vht_cap_ie(_adapter * padapter,u8 * pbuf)816 u32 rtw_build_vht_cap_ie(_adapter *padapter, u8 *pbuf)
817 {
818 u8 bw, rf_num;
819 u16 HighestRate;
820 u8 *pcap, *pcap_mcs;
821 u32 len = 0;
822 u32 rx_packet_offset, max_recvbuf_sz;
823 struct registry_priv *pregistrypriv = &padapter->registrypriv;
824 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
825 struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
826 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
827 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
828
829 pcap = pvhtpriv->vht_cap;
830 _rtw_memset(pcap, 0, 32);
831
832 /*
833 * VHT Capabilities Information field : B0 to B31
834 */
835 /* B0 B1 Maximum MPDU Length */
836 rtw_hal_get_def_var(padapter, HAL_DEF_RX_PACKET_OFFSET, &rx_packet_offset);
837 rtw_hal_get_def_var(padapter, HAL_DEF_MAX_RECVBUF_SZ, &max_recvbuf_sz);
838
839 RTW_DBG("%s, Available RX buf size = %d bytes\n", __FUNCTION__, max_recvbuf_sz - rx_packet_offset);
840
841 if ((max_recvbuf_sz - rx_packet_offset) >= 11454) {
842 SET_VHT_CAPABILITY_ELE_MAX_MPDU_LENGTH(pcap, 2);
843 RTW_INFO("[VHT] Declare supporting MAX MPDU len = 11454 bytes\n");
844 } else if ((max_recvbuf_sz - rx_packet_offset) >= 7991) {
845 SET_VHT_CAPABILITY_ELE_MAX_MPDU_LENGTH(pcap, 1);
846 RTW_INFO("[VHT] Declare supporting MAX MPDU len = 7991 bytes\n");
847 } else if ((max_recvbuf_sz - rx_packet_offset) >= 3895) {
848 SET_VHT_CAPABILITY_ELE_MAX_MPDU_LENGTH(pcap, 0);
849 RTW_INFO("[VHT] Declare supporting MAX MPDU len = 3895 bytes\n");
850 } else
851 RTW_ERR("[VHT] Error!! Available RX buf size < 3895 bytes\n");
852
853 /* B2 B3 Supported Channel Width Set */
854 if (hal_chk_bw_cap(padapter, BW_CAP_160M) && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)) {
855 if (hal_chk_bw_cap(padapter, BW_CAP_80_80M) && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_80_80)) {
856 SET_VHT_CAPABILITY_ELE_CHL_WIDTH(pcap, 2);
857 RTW_INFO("[VHT] Declare supporting 160MHz and 80+80MHz\n");
858 } else {
859 SET_VHT_CAPABILITY_ELE_CHL_WIDTH(pcap, 1);
860 RTW_INFO("[VHT] Declare supporting 160MHz\n");
861 }
862 } else
863 SET_VHT_CAPABILITY_ELE_CHL_WIDTH(pcap, 0);
864
865 /* B4 Rx LDPC */
866 if (TEST_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_RX)) {
867 SET_VHT_CAPABILITY_ELE_RX_LDPC(pcap, 1);
868 RTW_INFO("[VHT] Declare supporting RX LDPC\n");
869 }
870
871 /* B5 ShortGI for 80MHz */
872 SET_VHT_CAPABILITY_ELE_SHORT_GI80M(pcap, pvhtpriv->sgi_80m ? 1 : 0);
873 if (pvhtpriv->sgi_80m)
874 RTW_INFO("[VHT] Declare supporting SGI 80MHz\n");
875
876 /* B6 Short GI for 160 and 80+80 MHz */
877 SET_VHT_CAPABILITY_ELE_SHORT_GI160M(pcap, pvhtpriv->sgi_160m ? 1 : 0);
878 if (pvhtpriv->sgi_160m) {
879 RTW_INFO("[VHT] Declare supporting SGI 160MHz and 80+80MHz\n");
880 }
881
882 /* B7 Tx STBC */
883 if (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX)) {
884 SET_VHT_CAPABILITY_ELE_TX_STBC(pcap, 1);
885 RTW_INFO("[VHT] Declare supporting TX STBC\n");
886 }
887
888 /* B8 B9 B10 Rx STBC */
889 if (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_RX)) {
890 SET_VHT_CAPABILITY_ELE_RX_STBC(pcap, pvhtpriv->rx_stbc_nss);
891 RTW_INFO("[VHT] Declare supporting %uSS RX STBC\n", pvhtpriv->rx_stbc_nss);
892 }
893
894 #ifdef CONFIG_BEAMFORMING
895 /* B11 SU Beamformer Capable */
896 if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE)) {
897 SET_VHT_CAPABILITY_ELE_SU_BFER(pcap, 1);
898 RTW_INFO("[VHT] Declare supporting SU Beamformer\n");
899 /* B16 17 18 Number of Sounding Dimensions */
900 rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMER_CAP, (u8 *)&rf_num);
901 SET_VHT_CAPABILITY_ELE_SOUNDING_DIMENSIONS(pcap, rf_num);
902 /* B19 MU Beamformer Capable */
903 if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_AP_ENABLE)) {
904 SET_VHT_CAPABILITY_ELE_MU_BFER(pcap, 1);
905 RTW_INFO("[VHT] Declare supporting MU Beamformer\n");
906 }
907 }
908
909 /* B12 SU Beamformee Capable */
910 if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE)) {
911 SET_VHT_CAPABILITY_ELE_SU_BFEE(pcap, 1);
912 RTW_INFO("[VHT] Declare supporting SU Beamformee\n");
913
914 rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMEE_CAP, (u8 *)&rf_num);
915
916 /* IOT action suggested by Yu Chen 2017/3/3 */
917 if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_BROADCOM) &&
918 !pvhtpriv->ap_bf_cap.is_mu_bfer &&
919 pvhtpriv->ap_bf_cap.su_sound_dim == 2)
920 rf_num = (rf_num >= 2 ? 2 : rf_num);
921
922 /* B13 14 15 Beamformee STS Capability */
923 SET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pcap, rf_num);
924
925 /* B20 MU Beamformee Capable */
926 if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_MU_MIMO_STA_ENABLE)) {
927 SET_VHT_CAPABILITY_ELE_MU_BFEE(pcap, 1);
928 RTW_INFO("[VHT] Declare supporting MU Beamformee\n");
929 }
930 }
931 #endif/*CONFIG_BEAMFORMING*/
932
933 /* B21 VHT TXOP PS */
934 if (pvhtpriv->txop_ps) {
935 SET_VHT_CAPABILITY_ELE_TXOP_PS(pcap, 1);
936 RTW_INFO("[VHT] Declare supporting VHT TXOP power save\n");
937 }
938
939 /* B22 +HTC-VHT Capable */
940 if (pvhtpriv->htc_vht) {
941 SET_VHT_CAPABILITY_ELE_HTC_VHT(pcap, 1);
942 RTW_INFO("[VHT] Declare supporting VHT variant HT Control\n");
943 }
944
945 /* B23 24 25 Maximum A-MPDU Length Exponent */
946 SET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pcap, pvhtpriv->ampdu_len);
947 RTW_INFO("[VHT] Declare supporting RX A-MPDU Length Exponent = %u\n", pvhtpriv->ampdu_len);
948
949 /* B26 27 VHT Link Adaptation Capable */
950 if (pvhtpriv->link_adap_cap) {
951 SET_VHT_CAPABILITY_ELE_LINK_ADAPTION(pcap, 1);
952 RTW_INFO("[VHT] Declare supporting link adaptation using VHT variant HT Control\n");
953 }
954
955 /* B28 Rx Antenna Pattern Consistency */
956 if (pvhtpriv->rx_ant_pattern) {
957 SET_VHT_CAPABILITY_ELE_RX_ANT_PATTERN(pcap, 1);
958 RTW_INFO("[VHT] Declare supporting RX Antenna Pattern Consistency\n");
959 }
960
961 /* B29 Tx Antenna Pattern Consistency */
962 if (pvhtpriv->tx_ant_pattern) {
963 SET_VHT_CAPABILITY_ELE_TX_ANT_PATTERN(pcap, 1);
964 RTW_INFO("[VHT] Declare supporting TX Antenna Pattern Consistency\n");
965 }
966
967 /* B30 B31 Extended NSS BW Support */
968 SET_VHT_CAPABILITY_ELE_EXT_NSS_BW(pcap, pvhtpriv->ext_nss_bw);
969
970 /*
971 * Supported VHT-MCS and NSS Set : 8 bytes
972 */
973 pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pcap);
974 _rtw_memcpy(pcap_mcs, pvhtpriv->vht_mcs_map, 2);
975
976 pcap_mcs = GET_VHT_CAPABILITY_ELE_TX_MCS(pcap);
977 _rtw_memcpy(pcap_mcs, pvhtpriv->vht_mcs_map, 2);
978
979 /* find the largest bw supported by both registry and hal */
980 bw = hal_largest_bw(padapter, REGSTY_BW_5G(pregistrypriv));
981
982 HighestRate = VHT_MCS_DATA_RATE[bw][pvhtpriv->sgi_80m][((pvhtpriv->vht_highest_rate - MGN_VHT1SS_MCS0) & 0x3f)];
983 HighestRate = (HighestRate + 1) >> 1;
984
985 SET_VHT_CAPABILITY_ELE_MCS_RX_HIGHEST_RATE(pcap, HighestRate); /* indicate we support highest rx rate is 600Mbps. */
986 SET_VHT_CAPABILITY_ELE_MCS_TX_HIGHEST_RATE(pcap, HighestRate); /* indicate we support highest tx rate is 600Mbps. */
987
988 pbuf = rtw_set_ie(pbuf, EID_VHTCapability, 12, pcap, &len);
989
990 return len;
991 }
992
rtw_restructure_vht_ie(_adapter * padapter,u8 * in_ie,u8 * out_ie,uint in_len,uint * pout_len,struct country_chplan * req_chplan)993 u32 rtw_restructure_vht_ie(_adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len, struct country_chplan *req_chplan)
994 {
995 struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
996 RT_CHANNEL_INFO *chset = rfctl->channel_set;
997 u32 ielen;
998 u8 max_bw;
999 u8 oper_ch, oper_bw = CHANNEL_WIDTH_20, oper_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
1000 u8 *out_vht_op_ie, *ht_op_ie, *vht_cap_ie, *vht_op_ie;
1001 struct registry_priv *pregistrypriv = &padapter->registrypriv;
1002 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1003 struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
1004
1005 rtw_vht_use_default_setting(padapter);
1006
1007 ht_op_ie = rtw_get_ie(in_ie + 12, WLAN_EID_HT_OPERATION, &ielen, in_len - 12);
1008 if (!ht_op_ie || ielen != HT_OP_IE_LEN)
1009 goto exit;
1010 vht_cap_ie = rtw_get_ie(in_ie + 12, EID_VHTCapability, &ielen, in_len - 12);
1011 if (!vht_cap_ie || ielen != VHT_CAP_IE_LEN)
1012 goto exit;
1013 vht_op_ie = rtw_get_ie(in_ie + 12, EID_VHTOperation, &ielen, in_len - 12);
1014 if (!vht_op_ie || ielen != VHT_OP_IE_LEN)
1015 goto exit;
1016
1017 /* VHT Capabilities element */
1018 *pout_len += rtw_build_vht_cap_ie(padapter, out_ie + *pout_len);
1019
1020
1021 /* VHT Operation element */
1022 out_vht_op_ie = out_ie + *pout_len;
1023 rtw_set_ie(out_vht_op_ie, EID_VHTOperation, VHT_OP_IE_LEN, vht_op_ie + 2 , pout_len);
1024
1025 /* get primary channel from HT_OP_IE */
1026 oper_ch = GET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2);
1027
1028 /* find the largest bw supported by both registry and hal */
1029 max_bw = hal_largest_bw(padapter, REGSTY_BW_5G(pregistrypriv));
1030
1031 if (max_bw >= CHANNEL_WIDTH_40) {
1032 /* get bw offset form HT_OP_IE */
1033 if (GET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2)) {
1034 switch (GET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2)) {
1035 case SCA:
1036 oper_bw = CHANNEL_WIDTH_40;
1037 oper_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
1038 break;
1039 case SCB:
1040 oper_bw = CHANNEL_WIDTH_40;
1041 oper_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
1042 break;
1043 }
1044 }
1045
1046 if (oper_bw == CHANNEL_WIDTH_40) {
1047 switch (GET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2)) {
1048 case 1: /* 80MHz */
1049 case 2: /* 160MHz */
1050 case 3: /* 80+80 */
1051 oper_bw = CHANNEL_WIDTH_80; /* only support up to 80MHz for now */
1052 break;
1053 }
1054
1055 oper_bw = rtw_min(oper_bw, max_bw);
1056
1057 /* try downgrage bw to fit in channel plan setting */
1058 while ((req_chplan && !rtw_country_chplan_is_chbw_valid(req_chplan, BAND_ON_5G, oper_ch, oper_bw, oper_offset, 1, 1, pregistrypriv))
1059 || (!req_chplan && !rtw_chset_is_chbw_valid(chset, oper_ch, oper_bw, oper_offset, 1, 1))
1060 || (IS_DFS_SLAVE_WITH_RD(rfctl)
1061 && !rtw_rfctl_dfs_domain_unknown(rfctl)
1062 && rtw_chset_is_chbw_non_ocp(chset, oper_ch, oper_bw, oper_offset))
1063 ) {
1064 oper_bw--;
1065 if (oper_bw == CHANNEL_WIDTH_20) {
1066 oper_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
1067 break;
1068 }
1069 }
1070 }
1071 }
1072
1073 rtw_warn_on(req_chplan && !rtw_country_chplan_is_chbw_valid(req_chplan, BAND_ON_5G, oper_ch, oper_bw, oper_offset, 1, 1, pregistrypriv));
1074 rtw_warn_on(!req_chplan && !rtw_chset_is_chbw_valid(chset, oper_ch, oper_bw, oper_offset, 1, 1));
1075 if (IS_DFS_SLAVE_WITH_RD(rfctl) && !rtw_rfctl_dfs_domain_unknown(rfctl))
1076 rtw_warn_on(rtw_chset_is_chbw_non_ocp(chset, oper_ch, oper_bw, oper_offset));
1077
1078 /* update VHT_OP_IE */
1079 if (oper_bw < CHANNEL_WIDTH_80) {
1080 SET_VHT_OPERATION_ELE_CHL_WIDTH(out_vht_op_ie + 2, 0);
1081 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(out_vht_op_ie + 2, 0);
1082 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(out_vht_op_ie + 2, 0);
1083 } else if (oper_bw == CHANNEL_WIDTH_80) {
1084 u8 cch = rtw_get_center_ch(oper_ch, oper_bw, oper_offset);
1085
1086 SET_VHT_OPERATION_ELE_CHL_WIDTH(out_vht_op_ie + 2, 1);
1087 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(out_vht_op_ie + 2, cch);
1088 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(out_vht_op_ie + 2, 0);
1089 } else {
1090 RTW_ERR(FUNC_ADPT_FMT" unsupported BW:%u\n", FUNC_ADPT_ARG(padapter), oper_bw);
1091 rtw_warn_on(1);
1092 }
1093
1094 /* Operating Mode Notification element */
1095 *pout_len += rtw_build_vht_op_mode_notify_ie(padapter, out_ie + *pout_len, oper_bw);
1096
1097 pvhtpriv->vht_option = _TRUE;
1098
1099 exit:
1100 return pvhtpriv->vht_option;
1101
1102 }
1103
VHTOnAssocRsp(_adapter * padapter)1104 void VHTOnAssocRsp(_adapter *padapter)
1105 {
1106 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1107 struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
1108 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1109 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1110 u8 ht_AMPDU_len;
1111
1112 RTW_INFO("%s\n", __FUNCTION__);
1113
1114 if (!pmlmeinfo->HT_enable)
1115 return;
1116
1117 if (!pmlmeinfo->VHT_enable)
1118 return;
1119
1120 ht_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
1121
1122 if (pvhtpriv->ampdu_len > ht_AMPDU_len)
1123 rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&pvhtpriv->ampdu_len));
1124
1125 rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MAX_TIME, (u8 *)(&pvhtpriv->vht_highest_rate));
1126 }
1127
1128 #ifdef CONFIG_AP_MODE
rtw_vht_ies_attach(_adapter * padapter,WLAN_BSSID_EX * pnetwork)1129 void rtw_vht_ies_attach(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
1130 {
1131 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1132 u8 cap_len, operation_len;
1133 uint len = 0;
1134 sint ie_len = 0;
1135 u8 *p = NULL;
1136
1137 p = rtw_get_ie(pnetwork->IEs + _BEACON_IE_OFFSET_, EID_VHTCapability, &ie_len,
1138 (pnetwork->IELength - _BEACON_IE_OFFSET_));
1139 if (p && ie_len > 0)
1140 return;
1141
1142 rtw_vht_use_default_setting(padapter);
1143
1144 /* VHT Operation mode notifiy bit in Extended IE (127) */
1145 rtw_add_ext_cap_info(pmlmepriv->ext_capab_ie_data, &(pmlmepriv->ext_capab_ie_len), OP_MODE_NOTIFICATION);
1146 rtw_update_ext_cap_ie(pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len, pnetwork->IEs \
1147 , &(pnetwork->IELength), _BEACON_IE_OFFSET_);
1148
1149 /* VHT Capabilities element */
1150 cap_len = rtw_build_vht_cap_ie(padapter, pnetwork->IEs + pnetwork->IELength);
1151 pnetwork->IELength += cap_len;
1152
1153 /* VHT Operation element */
1154 operation_len = rtw_build_vht_operation_ie(padapter, pnetwork->IEs + pnetwork->IELength,
1155 pnetwork->Configuration.DSConfig);
1156 pnetwork->IELength += operation_len;
1157
1158 rtw_check_for_vht20(padapter, pnetwork->IEs + _BEACON_IE_OFFSET_, pnetwork->IELength - _BEACON_IE_OFFSET_);
1159
1160 pmlmepriv->vhtpriv.vht_option = _TRUE;
1161 }
1162
rtw_vht_ies_detach(_adapter * padapter,WLAN_BSSID_EX * pnetwork)1163 void rtw_vht_ies_detach(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
1164 {
1165 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1166
1167 rtw_remove_ext_cap_info(pmlmepriv->ext_capab_ie_data, &(pmlmepriv->ext_capab_ie_len), OP_MODE_NOTIFICATION);
1168 rtw_update_ext_cap_ie(pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len, pnetwork->IEs \
1169 , &(pnetwork->IELength), _BEACON_IE_OFFSET_);
1170
1171 rtw_remove_bcn_ie(padapter, pnetwork, EID_VHTCapability);
1172 rtw_remove_bcn_ie(padapter, pnetwork, EID_VHTOperation);
1173 rtw_remove_bcn_ie(padapter, pnetwork, EID_VHTTransmitPower);
1174
1175 pmlmepriv->vhtpriv.vht_option = _FALSE;
1176 }
1177
rtw_check_for_vht20(_adapter * adapter,u8 * ies,int ies_len)1178 void rtw_check_for_vht20(_adapter *adapter, u8 *ies, int ies_len)
1179 {
1180 u8 ht_ch, ht_bw, ht_offset;
1181 u8 vht_ch, vht_bw, vht_offset;
1182
1183 rtw_ies_get_chbw(ies, ies_len, &ht_ch, &ht_bw, &ht_offset, 1, 0);
1184 rtw_ies_get_chbw(ies, ies_len, &vht_ch, &vht_bw, &vht_offset, 1, 1);
1185
1186 if (ht_bw == CHANNEL_WIDTH_20 && vht_bw >= CHANNEL_WIDTH_80) {
1187 u8 *vht_op_ie;
1188 int vht_op_ielen;
1189
1190 RTW_INFO(FUNC_ADPT_FMT" vht80 is not allowed without ht40\n", FUNC_ADPT_ARG(adapter));
1191 vht_op_ie = rtw_get_ie(ies, EID_VHTOperation, &vht_op_ielen, ies_len);
1192 if (vht_op_ie && vht_op_ielen) {
1193 RTW_INFO(FUNC_ADPT_FMT" switch to vht20\n", FUNC_ADPT_ARG(adapter));
1194 SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, 0);
1195 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, 0);
1196 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0);
1197 }
1198 }
1199 }
1200
1201 /* We need to update the (mlmepriv->vhtpriv) */
rtw_update_drv_vht_cap(_adapter * padapter,u8 * vht_cap_ie)1202 void rtw_update_drv_vht_cap(_adapter *padapter, u8 *vht_cap_ie)
1203 {
1204 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1205 struct vht_priv *pvhtpriv = &(pmlmepriv->vhtpriv);
1206 struct registry_priv *pregpriv = &padapter->registrypriv;
1207 s32 ie_len = 0;
1208 u32 rx_packet_offset, max_recvbuf_sz, available_mpdu_sz;
1209 u8 cap_val;
1210 u8 *pvht_cap;
1211
1212 /* Initialize VHT capability element */
1213 rtw_vht_use_default_setting(padapter);
1214
1215 RTW_INFO("Don't setting VHT capability IE from hostap, builded by driver temporarily\n");
1216 rtw_build_vht_cap_ie(padapter, vht_cap_ie);
1217 }
1218
rtw_set_vht_ext_cap(_adapter * padapter,WLAN_BSSID_EX * pnetwork)1219 void rtw_set_vht_ext_cap(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
1220 {
1221 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1222 struct vht_priv *pvhtpriv = &(pmlmepriv->vhtpriv);
1223 u32 frlen = 0;
1224 u32 ie_len;
1225 u32 ies_len = pnetwork->IELength - _BEACON_IE_OFFSET_;
1226 u8 *ies = pnetwork->IEs + _BEACON_IE_OFFSET_;
1227 u8 *pbuf;
1228
1229 rtw_add_ext_cap_info(pmlmepriv->ext_capab_ie_data, &(pmlmepriv->ext_capab_ie_len), OP_MODE_NOTIFICATION);
1230 rtw_update_ext_cap_ie(pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len, pnetwork->IEs \
1231 , &(pnetwork->IELength), _BEACON_IE_OFFSET_);
1232 }
1233
rtw_check_vht_ies(_adapter * padapter,WLAN_BSSID_EX * pnetwork)1234 void rtw_check_vht_ies(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
1235 {
1236 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1237 struct vht_priv *pvhtpriv = &(pmlmepriv->vhtpriv);
1238 u32 ie_len;
1239 u32 ies_len = pnetwork->IELength - _BEACON_IE_OFFSET_;
1240 u8 *ies = pnetwork->IEs + _BEACON_IE_OFFSET_;
1241 u8 *vht_cap_ie, *vht_op_ie;
1242
1243 vht_cap_ie = rtw_get_ie(ies, EID_VHTCapability, &ie_len, ies_len);
1244 vht_op_ie = rtw_get_ie(ies, EID_VHTOperation, &ie_len, ies_len);
1245
1246 rtw_update_drv_vht_cap(padapter, vht_cap_ie);
1247 rtw_set_vht_ext_cap(padapter, pnetwork);
1248
1249 /* Backup these two VHT IEs from hostapd/wpa_supplicant for restore usage */
1250 if (vht_cap_ie != NULL)
1251 _rtw_memcpy(pvhtpriv->vht_cap_ie_backup, vht_cap_ie + 2, VHT_CAP_IE_LEN);
1252
1253 if (vht_op_ie != NULL)
1254 _rtw_memcpy(pvhtpriv->vht_op_ie_backup, vht_op_ie + 2, VHT_OP_IE_LEN);
1255
1256 /* TODO : We don't handle this IE like before, so remove it */
1257 rtw_remove_bcn_ie(padapter, pnetwork, EID_VHTTransmitPower);
1258 }
1259
rtw_reattach_vht_ies(_adapter * padapter,WLAN_BSSID_EX * pnetwork)1260 void rtw_reattach_vht_ies(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
1261 {
1262 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1263 struct vht_priv *pvhtpriv = &(pmlmepriv->vhtpriv);
1264 u8 *vht_cap_ie = pnetwork->IEs + pnetwork->IELength;
1265 u8 *vht_op_ie;
1266
1267 RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
1268
1269 if (pnetwork->IEs != NULL) {
1270 vht_op_ie = rtw_set_ie(vht_cap_ie, EID_VHTCapability, VHT_CAP_IE_LEN,
1271 pvhtpriv->vht_cap_ie_backup, &(pnetwork->IELength));
1272
1273 rtw_set_ie(vht_op_ie, EID_VHTOperation, VHT_OP_IE_LEN,
1274 pvhtpriv->vht_op_ie_backup, &(pnetwork->IELength));
1275
1276 rtw_set_vht_ext_cap(padapter, pnetwork);
1277 }
1278
1279 pmlmepriv->vhtpriv.vht_option = _TRUE;
1280 }
1281 #endif /* CONFIG_AP_MODE */
1282 #endif /* CONFIG_80211AC_VHT */
1283