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