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