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 HighestRate = VHT_MCS_DATA_RATE[bw][pvhtpriv->sgi_80m][((pvhtpriv->vht_highest_rate - MGN_VHT1SS_MCS0) & 0x3f)];
1149 HighestRate = (HighestRate + 1) >> 1;
1150
1151 SET_VHT_CAPABILITY_ELE_MCS_RX_HIGHEST_RATE(pcap, HighestRate); /* indicate we support highest rx rate is 600Mbps. */
1152 SET_VHT_CAPABILITY_ELE_MCS_TX_HIGHEST_RATE(pcap, HighestRate); /* indicate we support highest tx rate is 600Mbps. */
1153
1154 pbuf = rtw_set_ie(pbuf, EID_VHTCapability, 12, pcap, &len);
1155
1156 return len;
1157 }
1158
rtw_restructure_vht_ie(_adapter * padapter,u8 * in_ie,u8 * out_ie,uint in_len,uint * pout_len,struct country_chplan * req_chplan)1159 u32 rtw_restructure_vht_ie(_adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len, struct country_chplan *req_chplan)
1160 {
1161 struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
1162 RT_CHANNEL_INFO *chset = rfctl->channel_set;
1163 u32 ielen;
1164 u8 max_bw;
1165 u8 oper_ch, oper_bw = CHANNEL_WIDTH_20, oper_offset = CHAN_OFFSET_NO_EXT;
1166 u8 *out_vht_op_ie, *ht_op_ie, *vht_cap_ie, *vht_op_ie;
1167 struct registry_priv *pregistrypriv = &padapter->registrypriv;
1168 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1169 struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
1170
1171 rtw_vht_get_real_setting(padapter);
1172
1173 ht_op_ie = rtw_get_ie(in_ie + 12, WLAN_EID_HT_OPERATION, &ielen, in_len - 12);
1174 if (!ht_op_ie || ielen != HT_OP_IE_LEN)
1175 goto exit;
1176 vht_cap_ie = rtw_get_ie(in_ie + 12, EID_VHTCapability, &ielen, in_len - 12);
1177 if (!vht_cap_ie || ielen != VHT_CAP_IE_LEN)
1178 goto exit;
1179 vht_op_ie = rtw_get_ie(in_ie + 12, EID_VHTOperation, &ielen, in_len - 12);
1180 if (!vht_op_ie || ielen != VHT_OP_IE_LEN)
1181 goto exit;
1182
1183 /* VHT Capabilities element */
1184 *pout_len += rtw_build_vht_cap_ie(padapter, out_ie + *pout_len);
1185
1186
1187 /* VHT Operation element */
1188 out_vht_op_ie = out_ie + *pout_len;
1189 rtw_set_ie(out_vht_op_ie, EID_VHTOperation, VHT_OP_IE_LEN, vht_op_ie + 2 , pout_len);
1190
1191 /* get primary channel from HT_OP_IE */
1192 oper_ch = GET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2);
1193
1194 /* find the largest bw supported by both registry and hal */
1195 max_bw = rtw_hw_largest_bw(adapter_to_dvobj(padapter), REGSTY_BW_5G(pregistrypriv));
1196
1197 if (max_bw >= CHANNEL_WIDTH_40) {
1198 /* get bw offset form HT_OP_IE */
1199 if (GET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2)) {
1200 switch (GET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2)) {
1201 case IEEE80211_SCA:
1202 oper_bw = CHANNEL_WIDTH_40;
1203 oper_offset = CHAN_OFFSET_UPPER;
1204 break;
1205 case IEEE80211_SCB:
1206 oper_bw = CHANNEL_WIDTH_40;
1207 oper_offset = CHAN_OFFSET_LOWER;
1208 break;
1209 }
1210 }
1211
1212 if (oper_bw == CHANNEL_WIDTH_40) {
1213 switch (GET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2)) {
1214 case 1: /* 80MHz */
1215 case 2: /* 160MHz */
1216 case 3: /* 80+80 */
1217 oper_bw = CHANNEL_WIDTH_80; /* only support up to 80MHz for now */
1218 break;
1219 }
1220
1221 oper_bw = rtw_min(oper_bw, max_bw);
1222
1223 /* try downgrage bw to fit in channel plan setting */
1224 while ((req_chplan && !rtw_country_chplan_is_chbw_valid(req_chplan, BAND_ON_5G, oper_ch, oper_bw, oper_offset, 1, 1, pregistrypriv))
1225 || (!req_chplan && !rtw_chset_is_chbw_valid(chset, oper_ch, oper_bw, oper_offset, 1, 1))
1226 || (IS_DFS_SLAVE_WITH_RD(rfctl)
1227 && !rtw_rfctl_dfs_domain_unknown(rfctl)
1228 && rtw_chset_is_chbw_non_ocp(chset, oper_ch, oper_bw, oper_offset))
1229 ) {
1230 oper_bw--;
1231 if (oper_bw == CHANNEL_WIDTH_20) {
1232 oper_offset = CHAN_OFFSET_NO_EXT;
1233 break;
1234 }
1235 }
1236 }
1237 }
1238
1239 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));
1240 rtw_warn_on(!req_chplan && !rtw_chset_is_chbw_valid(chset, oper_ch, oper_bw, oper_offset, 1, 1));
1241 if (IS_DFS_SLAVE_WITH_RD(rfctl) && !rtw_rfctl_dfs_domain_unknown(rfctl))
1242 rtw_warn_on(rtw_chset_is_chbw_non_ocp(chset, oper_ch, oper_bw, oper_offset));
1243
1244 /* update VHT_OP_IE */
1245 if (oper_bw < CHANNEL_WIDTH_80) {
1246 SET_VHT_OPERATION_ELE_CHL_WIDTH(out_vht_op_ie + 2, 0);
1247 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(out_vht_op_ie + 2, 0);
1248 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(out_vht_op_ie + 2, 0);
1249 } else if (oper_bw == CHANNEL_WIDTH_80) {
1250 u8 cch = rtw_phl_get_center_ch(oper_ch, oper_bw, oper_offset);
1251
1252 SET_VHT_OPERATION_ELE_CHL_WIDTH(out_vht_op_ie + 2, 1);
1253 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(out_vht_op_ie + 2, cch);
1254 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(out_vht_op_ie + 2, 0);
1255 } else {
1256 RTW_ERR(FUNC_ADPT_FMT" unsupported BW:%u\n", FUNC_ADPT_ARG(padapter), oper_bw);
1257 rtw_warn_on(1);
1258 }
1259
1260 /* Operating Mode Notification element */
1261 *pout_len += rtw_build_vht_op_mode_notify_ie(padapter, out_ie + *pout_len, oper_bw);
1262
1263 pvhtpriv->vht_option = _TRUE;
1264
1265 exit:
1266 return pvhtpriv->vht_option;
1267
1268 }
1269
VHTOnAssocRsp(_adapter * padapter)1270 void VHTOnAssocRsp(_adapter *padapter)
1271 {
1272 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1273 struct vht_priv *pvhtpriv = &pmlmepriv->vhtpriv;
1274 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1275 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1276 u8 ht_AMPDU_len;
1277
1278 RTW_INFO("%s\n", __FUNCTION__);
1279
1280 if (!pmlmeinfo->HT_enable)
1281 return;
1282
1283 if (!pmlmeinfo->VHT_enable)
1284 return;
1285
1286 ht_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
1287
1288 if (pvhtpriv->ampdu_len > ht_AMPDU_len)
1289 rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&pvhtpriv->ampdu_len));
1290
1291 rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MAX_TIME, (u8 *)(&pvhtpriv->vht_highest_rate));
1292 }
1293
rtw_vht_ies_attach(_adapter * padapter,WLAN_BSSID_EX * pnetwork)1294 void rtw_vht_ies_attach(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
1295 {
1296 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1297 u8 cap_len, operation_len;
1298 uint len = 0;
1299 sint ie_len = 0;
1300 u8 *p = NULL;
1301
1302 p = rtw_get_ie(pnetwork->IEs + _BEACON_IE_OFFSET_, EID_VHTCapability, &ie_len,
1303 (pnetwork->IELength - _BEACON_IE_OFFSET_));
1304 if (p && ie_len > 0)
1305 return;
1306
1307 rtw_vht_get_real_setting(padapter);
1308
1309 /* VHT Operation mode notifiy bit in Extended IE (127) */
1310 rtw_add_ext_cap_info(pmlmepriv->ext_capab_ie_data, &(pmlmepriv->ext_capab_ie_len), OP_MODE_NOTIFICATION);
1311 rtw_update_ext_cap_ie(pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len, pnetwork->IEs \
1312 , &(pnetwork->IELength), _BEACON_IE_OFFSET_);
1313
1314 /* VHT Capabilities element */
1315 cap_len = rtw_build_vht_cap_ie(padapter, pnetwork->IEs + pnetwork->IELength);
1316 pnetwork->IELength += cap_len;
1317
1318 /* VHT Operation element */
1319 operation_len = rtw_build_vht_operation_ie(padapter, pnetwork->IEs + pnetwork->IELength,
1320 pnetwork->Configuration.DSConfig);
1321 pnetwork->IELength += operation_len;
1322
1323 rtw_check_for_vht20(padapter, pnetwork->IEs + _BEACON_IE_OFFSET_, pnetwork->IELength - _BEACON_IE_OFFSET_);
1324
1325 pmlmepriv->vhtpriv.vht_option = _TRUE;
1326 }
1327
rtw_vht_ies_detach(_adapter * padapter,WLAN_BSSID_EX * pnetwork)1328 void rtw_vht_ies_detach(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
1329 {
1330 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1331
1332 rtw_remove_ext_cap_info(pmlmepriv->ext_capab_ie_data, &(pmlmepriv->ext_capab_ie_len), OP_MODE_NOTIFICATION);
1333 rtw_update_ext_cap_ie(pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len, pnetwork->IEs \
1334 , &(pnetwork->IELength), _BEACON_IE_OFFSET_);
1335
1336 rtw_remove_bcn_ie(padapter, pnetwork, EID_VHTCapability);
1337 rtw_remove_bcn_ie(padapter, pnetwork, EID_VHTOperation);
1338 rtw_remove_bcn_ie(padapter, pnetwork, EID_VHTTransmitPower);
1339
1340 pmlmepriv->vhtpriv.vht_option = _FALSE;
1341 }
1342
rtw_check_for_vht20(_adapter * adapter,u8 * ies,int ies_len)1343 void rtw_check_for_vht20(_adapter *adapter, u8 *ies, int ies_len)
1344 {
1345 u8 ht_ch, ht_bw, ht_offset;
1346 u8 vht_ch, vht_bw, vht_offset;
1347
1348 rtw_ies_get_chbw(ies, ies_len, &ht_ch, &ht_bw, &ht_offset, 1, 0);
1349 rtw_ies_get_chbw(ies, ies_len, &vht_ch, &vht_bw, &vht_offset, 1, 1);
1350
1351 if (ht_bw == CHANNEL_WIDTH_20 && vht_bw >= CHANNEL_WIDTH_80) {
1352 u8 *vht_op_ie;
1353 int vht_op_ielen;
1354
1355 RTW_INFO(FUNC_ADPT_FMT" vht80 is not allowed without ht40\n", FUNC_ADPT_ARG(adapter));
1356 vht_op_ie = rtw_get_ie(ies, EID_VHTOperation, &vht_op_ielen, ies_len);
1357 if (vht_op_ie && vht_op_ielen) {
1358 RTW_INFO(FUNC_ADPT_FMT" switch to vht20\n", FUNC_ADPT_ARG(adapter));
1359 SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, 0);
1360 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, 0);
1361 SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0);
1362 }
1363 }
1364 }
1365
1366 /* We need to update the (mlmepriv->vhtpriv) */
rtw_update_drv_vht_cap(_adapter * padapter,u8 * vht_cap_ie)1367 void rtw_update_drv_vht_cap(_adapter *padapter, u8 *vht_cap_ie)
1368 {
1369 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1370 struct vht_priv *pvhtpriv = &(pmlmepriv->vhtpriv);
1371 struct registry_priv *pregpriv = &padapter->registrypriv;
1372 s32 ie_len = 0;
1373 u32 rx_packet_offset, max_recvbuf_sz, available_mpdu_sz;
1374 u8 cap_val;
1375 u8 *pvht_cap;
1376
1377 /* Initialize VHT capability element */
1378 rtw_vht_get_real_setting(padapter);
1379
1380 RTW_INFO("Don't setting VHT capability IE from hostap, builded by driver temporarily\n");
1381 rtw_build_vht_cap_ie(padapter, vht_cap_ie);
1382 }
1383
rtw_check_vht_ies(_adapter * padapter,WLAN_BSSID_EX * pnetwork)1384 void rtw_check_vht_ies(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
1385 {
1386 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1387 struct vht_priv *pvhtpriv = &(pmlmepriv->vhtpriv);
1388 u32 ie_len;
1389 u32 ies_len = pnetwork->IELength - _BEACON_IE_OFFSET_;
1390 u8 *ies = pnetwork->IEs + _BEACON_IE_OFFSET_;
1391 u8 *vht_cap_ie, *vht_op_ie;
1392
1393 vht_cap_ie = rtw_get_ie(ies, EID_VHTCapability, &ie_len, ies_len);
1394
1395 vht_op_ie = rtw_get_ie(ies, EID_VHTOperation, &ie_len, ies_len);
1396
1397 rtw_update_drv_vht_cap(padapter, vht_cap_ie);
1398
1399 rtw_add_ext_cap_info(pmlmepriv->ext_capab_ie_data, &(pmlmepriv->ext_capab_ie_len), OP_MODE_NOTIFICATION);
1400 rtw_update_ext_cap_ie(pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len, pnetwork->IEs \
1401 , &(pnetwork->IELength), _BEACON_IE_OFFSET_);
1402
1403 /* Backup these two VHT IEs from hostapd/wpa_supplicant for restore usage */
1404 if (vht_cap_ie != NULL)
1405 _rtw_memcpy(pvhtpriv->vht_cap_ie_backup, vht_cap_ie + 2, VHT_CAP_IE_LEN);
1406
1407 if (vht_op_ie != NULL)
1408 _rtw_memcpy(pvhtpriv->vht_op_ie_backup, vht_op_ie + 2, VHT_OP_IE_LEN);
1409
1410 /* TODO : We don't handle this IE like before, so remove it */
1411 rtw_remove_bcn_ie(padapter, pnetwork, EID_VHTTransmitPower);
1412 }
1413
rtw_reattach_vht_ies(_adapter * padapter,WLAN_BSSID_EX * pnetwork)1414 void rtw_reattach_vht_ies(_adapter *padapter, WLAN_BSSID_EX *pnetwork)
1415 {
1416 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1417 struct vht_priv *pvhtpriv = &(pmlmepriv->vhtpriv);
1418 u8 *vht_cap_ie = pnetwork->IEs + pnetwork->IELength;
1419 u8 *vht_op_ie;
1420
1421 RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
1422
1423 if (pnetwork->IEs != NULL) {
1424 vht_op_ie = rtw_set_ie(vht_cap_ie, EID_VHTCapability, VHT_CAP_IE_LEN,
1425 pvhtpriv->vht_cap_ie_backup, &(pnetwork->IELength));
1426
1427 rtw_set_ie(vht_op_ie, EID_VHTOperation, VHT_OP_IE_LEN,
1428 pvhtpriv->vht_op_ie_backup, &(pnetwork->IELength));
1429
1430 rtw_add_ext_cap_info(pmlmepriv->ext_capab_ie_data, &(pmlmepriv->ext_capab_ie_len), OP_MODE_NOTIFICATION);
1431 rtw_update_ext_cap_ie(pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len, pnetwork->IEs \
1432 , &(pnetwork->IELength), _BEACON_IE_OFFSET_);
1433 }
1434
1435 pmlmepriv->vhtpriv.vht_option = _TRUE;
1436 }
1437 #endif /* CONFIG_80211AC_VHT */
1438