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